准备知识 之 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引擎 图像读写与处理 (知识+代码篇)的更多相关文章

  1. C++调用Matlab引擎及Eigen配置

    这个周开始要着手实现网格水印的代码了,虽然还什么都不会,但也只能一步步摸索着往前走了. 我要实现的论文题目是<<Watermarking 3D Polygonal Meshes in th ...

  2. vs2010 matlab混合编程调用matlab引擎

    // matlab_engine.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "engine.h" ...

  3. VS2015调用matlab Plot函数

    最近经常采用Matlab仿真,然后C语言实现,最后需要将计算结果使用Qt的qwt或者matlab中的plot函数绘图. 因此想借用matlab的plot函数接口,使用VS2015来编写信号处理代码,最 ...

  4. 【转】三种方式在C++中调用matlab

      C/C++调用Matlab 在工程实践中,C/C++调用Matlab 的方法主要有调用Matlab 计算引擎.包含m 文件转 换的C/C++文件,以及调用m文件生成的DLL 文件. 1 利用Mat ...

  5. Python的扩展接口[3] -> Matlab引擎 -> 使用 Python 调用 Matlab 程序

    Python - Matlab 目录 Python-Matlab 引擎 Python-Matlab 数组 Python-Matlab 基本操作 Python-Matlab 调用 m 文件 Matlab ...

  6. matlab 对图像操作的函数概览

    转自博客:http://blog.163.com/fei_lai_feng/blog/static/9289962200991713415422/ 一. 读写图像文件 1. imread imread ...

  7. WPF调用Matlab函数方法

    有的时候用C#写图像处理方法,比较费事,不如Matlab简单,但是Matlab又做不出WPF那样的好看界面,怎么办呢. 今天正好我要实现这个功能,就顺便写个小例子,给需要的人做个借鉴. 想要用WPF调 ...

  8. java调用matlab函数

    如何将实验结果在matlab中可视化呢,下面使用java语言编程,调用matlab中的函数: 本人安装的是Matlab7.11.0 (R2010a)和 Eclipse 4.2 : 1)首先设置环境变量 ...

  9. opencv通过dll调用matlab函数,图片作为参数

    [blog 项目实战派]opencv通过dll调用matlab函数,图片作为参数                   前文介绍了如何“csharp通过dll调用opencv函数,图片作为参数”.而在实 ...

随机推荐

  1. Linux菜鸟起飞之路【一】基本知识与Linux的安装

    一.操作系统基本常识 1.操作系统的定义:操作系统是用来协调.管理和控制计算机硬件与软件资源的系统程序,介于硬件与应用程序之间. 2.操作系统内核的定义:操作系统内核是一个管理和控制程序,负责管理计算 ...

  2. GoF23种设计模式之创建型模式之建造者模式

    一.概述 将一个复杂对象的构建与其表示分离开来,使得同样的构建过程可以创建不同的表示. 二.适用性 1.当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式的时候. 2.当构造过程必须允许 ...

  3. 数学算法:CF534A-Exam(思维)

    Exam time limit per test 1 second memory limit per test 256 megabytes input standard input output st ...

  4. P1616 疯狂的采药【模板】

    此题为NOIP2005普及组第三题的疯狂版. 此题为纪念LiYuxiang而生. 题目描述 LiYuxiang是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师. ...

  5. HDU1272小希的迷宫

    小希的迷宫 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一 ...

  6. 笔记-python-lib-re

    笔记-python-lib-re 1.      re模块简介 re模块提供了与perl类似的正则匹配功能. 要搜索的模式和字符串都可以是Unicode字符串(str)以及8位字符串(bytes).但 ...

  7. python re 模块小结

    前言: 本人环境windows 7 64位,python2.7 re是什么: regular expression缩写,意为正则表达式,是python的众多模块之一 re用途: 从文本中有选择的批量抽 ...

  8. 聊聊、RabbitMQ 配置文件

    windows 下面安装 rabbitMQ 比较简单,但是想去改端口相关信息却找不到配置文件在哪.Linux 在 /etc/rabbitmq/rabbitmq.config 下面就可以找到.来看看 w ...

  9. java 四舍五入 保留两位小数

    1. 格式化字符串 java.text.DecimalFormat df = new java.text.DecimalFormat("#0.00"); float val=Flo ...

  10. Summary—【base】(JavaScript)

    1.认识Js     1.1 Js就是一门运行在客户端浏览器的脚本编程语言     1.2 组成            ECMAScript:Js的语法标准            DOM:JS操作网页 ...