C++调用Matlab引擎 图像读写与处理 (知识+代码篇)
准备知识 之 Matlab Engine
执行命令
/* Execute matlab statement */
int engEvalString(Engine* ep, const char* string);
让engine执行string中的命令,命令格式为matlab命令。
在这里主要用到的有:
x = imread(filename)
figure
imshow(x)
imwrite(x, filename)
功能依次为
读入filename中的内容到x中
打开一个图形窗口
显示读入的图像x
将x写入到filename中
注意:1) 表示filename的字符串中两边是单引号
	2) 为了避免转义字符的影响,最好在路径中都用双斜杠'\\'
例如:'F:\\picture\\background\\0.png'
例
	engEvalString(ep, "x = imread('F:\\picture\\background\\0.png')");
	engEvalString(ep, "figure");
	engEvalString(ep, "imshow(x)");
	engEvalString(ep, "imwrite(x, 'F:\\picture\\background\\1.png')");
变量交互
get
/* Get a variable with the specified name from MATLAB's workspace */
mxArray *engGetVariable(Engine *ep, const char *name);
获取name变量中的内容到数组中。
在这里主要用在从文件中读取图像后。
例:
	engEvalString(ep, "x = imread('F:\\picture\\background\\0.png')");
	mxArray* pic = engGetVariable(ep, "x");
put
/* Put a variable into MATLAB's workspace with the specified name */
int engPutVariable(Engine *ep, const char *var_name, const mxArray *ap);
将数组ap中的内容放到变量中以待后续调用engine执行命令。
在这里主要用在准备将图像数据写入到文件中前。
例
	engPutVariable(ep, "y", pic);
	engEvalString(ep, "imwrite(y, 'F:\\picture\\background\\1.png')");
打开关闭
/* Start matlab process */
Engine *engOpen(const char *startcmd);
/* Close down matlab server */
int engClose(Engine *ep);
作为准备工作和结束工作。
准备知识 之 图像
数据及数据类型
mxArray*:从engine中获得的图像数据类型
mwSize:图像的维度数及每一维度的大小的数据类型
uint8_t:存放图像信息的矩阵的数据类型
函数及具体使用
图像的基本参数
//	获取数组的维数
size_t mxGetNumberOfDimensions_730(const mxArray *pa);
//	获取数组每一维的大小
const size_t *mxGetDimensions_730(const mxArray *pa);
假设我们不知道存放图片的数组是三维的,那么通用写法为:
	mwSize dims = mxGetNumberOfDimensions(pic);
	mwSize* dim = new mwSize[dims];
	memcpy(dim, mxGetDimensions(pic), dims * sizeof(mwSize));
即可获得这个数组的维数以及每一维的大小。
而事实上我们是知道这个数组是三维哒~
并且最后一维大小为3,存放的就是RGB值。
所以只需要如下这样这样
例
	mwSize row, col;
	memcpy(&row, mxGetDimensions(pic), sizeof(mwSize));
	memcpy(&col, mxGetDimensions(pic) + 1, sizeof(mwSize));
即可获得图像的行和列
图像的内容数据
数据类型
首先一个问题是,存放图像内容数据的那个矩阵,是什么数据类型呢?
//	获取数组中数据的类型
mxClassID mxGetClassID(const mxArray *pa);
再查看mxClassID的定义:
typedef enum {
    mxUNKNOWN_CLASS = 0,
    mxCELL_CLASS,
    mxSTRUCT_CLASS,
    mxLOGICAL_CLASS,
    mxCHAR_CLASS,
    mxVOID_CLASS,
    mxDOUBLE_CLASS,
    mxSINGLE_CLASS,
    mxINT8_CLASS,
    mxUINT8_CLASS,
	…………………………………………
} mxClassID;
调用mxGetClassID的返回值为9,由上述定义可知,是uint8_t类型的。
存储方式
ATTENTION
数据并不是我们想当然的按val[row][col][3]这样的三维数组存储的!
在matlab里面,你可以看到它的显示依次是val(:,:,1), val(:,:,2), val(:,:,3)
什么意思呢?就是先是R分量,再是G分量,最后是B分量。
——来自在玄学到怀疑人生之后,认真的比对了我读出来的RGB和它显示的值的差别之后,终于找到了真理之门的钥匙的,我
——不用感谢我,我的名字叫救命怀(溜
首地址
现在万事俱备,只欠东风,只需要知道数组的起始地址,图像内容就尽在掌握之中了。
//	获取指向数组起始位置的指针
void *mxGetData(const mxArray *pa);
例
// 将图像中的数据读入到一个RGB**数组中
	uint8_t* p = (uint8_t*)mxGetData(pic);
	for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) pix[i][j].r = *(p++);
	for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) pix[i][j].g = *(p++);
	for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) pix[i][j].b = *(p++);
自然,有了首地址,修改图像内容也是易如反掌了
完整代码
说完整代码什么的...其实就是一个把上面几个功能简单地拼到一起的小的演示程序_(:з」∠)_
能跑,有效果,对于这样一篇文章来说就足够了(吧
基础的东西有了,于其上的拓展也应该很好操作了
注释就不写了,上面一步一步说过来感觉已经挺完整了_(:з」∠)_
/*
AUTHOR: kahlua
DATE: 2017.12.7
ENVIRONMENT: VS 2015 x64
*/
#include <iostream>
#include "engine.h"
#include <stdio.h>
using namespace std;
struct RGB {
	uint8_t r;
	uint8_t g;
	uint8_t b;
	void print() { cout << (int)r << " " << (int)g << " " << (int)b << endl; }
};
int main() {
	Engine* ep = engOpen(NULL);
	if (!ep) {
		cout << "Unable to start Matlab engine!\n";
		return -1;
	}
	engEvalString(ep, "x = imread('F:\\picture\\background\\0.png')");
	engEvalString(ep, "figure");
	engEvalString(ep, "imshow(x)");
	mxArray* pic = engGetVariable(ep, "x");
	if (!pic) {
		cout << "No such picture!\n";
		return -1;
	}
	mwSize row, col;
	memcpy(&row, mxGetDimensions(pic), sizeof(mwSize));
	memcpy(&col, mxGetDimensions(pic) + 1, sizeof(mwSize));
	cout << row << " " << col << endl;
	RGB** pix = new RGB*[row];
	for (int i = 0; i < row; ++i) pix[i] = new RGB[col];
	uint8_t* p = (uint8_t*)mxGetData(pic);
	for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) pix[i][j].r = *(p++);
	for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) pix[i][j].g = *(p++);
	for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) pix[i][j].b = *(p++);
	engPutVariable(ep, "y", pic);
	engEvalString(ep, "imwrite(y, 'F:\\picture\\background\\1.png')");
	return 0;
}
												
											C++调用Matlab引擎 图像读写与处理 (知识+代码篇)的更多相关文章
- C++调用Matlab引擎及Eigen配置
		
这个周开始要着手实现网格水印的代码了,虽然还什么都不会,但也只能一步步摸索着往前走了. 我要实现的论文题目是<<Watermarking 3D Polygonal Meshes in th ...
 - vs2010 matlab混合编程调用matlab引擎
		
// matlab_engine.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "engine.h" ...
 - VS2015调用matlab Plot函数
		
最近经常采用Matlab仿真,然后C语言实现,最后需要将计算结果使用Qt的qwt或者matlab中的plot函数绘图. 因此想借用matlab的plot函数接口,使用VS2015来编写信号处理代码,最 ...
 - 【转】三种方式在C++中调用matlab
		
C/C++调用Matlab 在工程实践中,C/C++调用Matlab 的方法主要有调用Matlab 计算引擎.包含m 文件转 换的C/C++文件,以及调用m文件生成的DLL 文件. 1 利用Mat ...
 - Python的扩展接口[3] -> Matlab引擎 -> 使用 Python 调用 Matlab 程序
		
Python - Matlab 目录 Python-Matlab 引擎 Python-Matlab 数组 Python-Matlab 基本操作 Python-Matlab 调用 m 文件 Matlab ...
 - matlab  对图像操作的函数概览
		
转自博客:http://blog.163.com/fei_lai_feng/blog/static/9289962200991713415422/ 一. 读写图像文件 1. imread imread ...
 - WPF调用Matlab函数方法
		
有的时候用C#写图像处理方法,比较费事,不如Matlab简单,但是Matlab又做不出WPF那样的好看界面,怎么办呢. 今天正好我要实现这个功能,就顺便写个小例子,给需要的人做个借鉴. 想要用WPF调 ...
 - java调用matlab函数
		
如何将实验结果在matlab中可视化呢,下面使用java语言编程,调用matlab中的函数: 本人安装的是Matlab7.11.0 (R2010a)和 Eclipse 4.2 : 1)首先设置环境变量 ...
 - opencv通过dll调用matlab函数,图片作为参数
		
[blog 项目实战派]opencv通过dll调用matlab函数,图片作为参数 前文介绍了如何“csharp通过dll调用opencv函数,图片作为参数”.而在实 ...
 
随机推荐
- LeetCode949-给定数字能组成的最大时间
			
问题: 给定一个由 4 位数字组成的数组,返回可以设置的符合 24 小时制的最大时间. 最小的 24 小时制时间是 00:00,而最大的是 23:59.从 00:00 (午夜)开始算起,过得越久,时间 ...
 - vue.js 独立引用css文件图片路径错误
			
vue的环境是用vue-cli,写在vue文件的图片引用build之后的路径都没什么问题 但是有的时候我们会有一些公共的css文件单独的放在assets目录下 如下图所示 这里当build后发现写在c ...
 - thinkphp 3.2.3 - App.class.php 解析
			
class App { public static function init() { load_ext_file(COMMON_PATH); // { // /home/www/www.domain ...
 - thinkphp 3.2.3 - Think.class.php 解析
			
class Think { public static function start() { // 注册AUTOLOAD方法 spl_autoload_register('Think\Think::a ...
 - 27.28. VUE学习之--事件修饰符之stop&capture&self&once实例详解
			
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
 - kafka及扩展的安装笔记
			
参考文件 https://blog.csdn.net/weiwenjuan0923/article/details/76152744 一.首先确认下jdk有没有安装 安装参照这个连接 https:// ...
 - linux硬件基础
			
1. 服务器分类 机架式服务器(主要用这个). 刀片式服务器. 塔式服务器. 2. 机架式服务器 服务器的尺: U - 2U. 服务器核心之电源: 双电源 AB 路. 服务器核心之 CPU-计算 CP ...
 - x01.xiangqi: 走动棋子
			
采用 pygame 写的象棋程序,目前只完成绘制棋盘与走动棋子,还没考虑规则等问题. 1. 代码: """ x01.xiangqi (c) 2019 by x01&quo ...
 - 从头开始学习数据库及ADO.NET——竹子整理
			
目前为止,学习编程一年有余,写过管理系统,写过商城,写过桌面,接触的多了,乱七八糟的点太多,一堆前段框架,后台类库,纷纷杂杂,更新迭代之快也是令人咋舌.于是我就在想,作为一名程序员,哪些内容是实打实的 ...
 - readhat7.0  bond配置
			
Bonding的模式一共有7种: 1.mode=0(balance-rr)(平衡抡循环策略) 概念:链路负载均衡,增加带宽,支持容错,一条链路故障会自动切换正常链路.交换机需要配置聚合口,思科叫por ...