热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Matlab中利用mex编译Opencv实现画板绘图功能

图形绘制是标记和可视化数据的重要方法.通过在Matlab中集成画板绘图功能,可为科学计算提供便利.1设置Matlab支持Opencv编译操作系统:麒麟14.04(基于Ubu

图形绘制是标记和可视化数据的重要方法.

通过在Matlab中集成画板绘图功能, 可为科学计算提供便利.


1 设置Matlab支持Opencv编译

操作系统: 麒麟14.04(基于Ubuntu 14.04)

命令: mex -v

-> mexopts.sh sourced from directory (DIR = $MATLAB/bin)
FILE = /usr/local/MATLAB/R2013a/bin/mexopts.sh
----------------------------------------------------------------
-> MATLAB = /usr/local/MATLAB/R2013a
-> CC = gcc
-> CC flags:
CFLAGS = -ansi -D_GNU_SOURCE -fexceptions -I/usr/include/opencv -fPIC -fno-omit-frame-pointer -pthread
CDEBUGFLAGS = -g
COPTIMFLAGS = -O -DNDEBUG
CLIBS = -Wl,-rpath-link,/usr/local/MATLAB/R2013a/bin/glnxa64 -L/usr/local/MATLAB/R2013a/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++ -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_ocl -lopencv_photo -lopencv_stitching -lopencv_superres -lopencv_ts -lopencv_video -lopencv_videostab
arguments = -DMX_COMPAT_32
-> CXX = g++
-> CXX flags:
CXXFLAGS = -ansi -D_GNU_SOURCE -std=c++0x -fPIC -fno-omit-frame-pointer -pthread
CXXDEBUGFLAGS = -g
CXXOPTIMFLAGS = -O -DNDEBUG
CXXLIBS = -Wl,-rpath-link,/usr/local/MATLAB/R2013a/bin/glnxa64 -L/usr/local/MATLAB/R2013a/bin/glnxa64 -lmx -lmex -lmat -lm -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_ocl -lopencv_photo -lopencv_stitching -lopencv_superres -lopencv_ts -lopencv_video -lopencv_videostab
arguments = -DMX_COMPAT_32
-> FC = gfortran
-> FC flags:
FFLAGS = -fexceptions -fbackslash -fPIC -fno-omit-frame-pointer
FDEBUGFLAGS = -g
FOPTIMFLAGS = -O
FLIBS = -Wl,-rpath-link,/usr/local/MATLAB/R2013a/bin/glnxa64 -L/usr/local/MATLAB/R2013a/bin/glnxa64 -lmx -lmex -lmat -lm
arguments = -DMX_COMPAT_32
-> LD = gcc
-> Link flags:
LDFLAGS = -pthread -shared -Wl,--version-script,/usr/local/MATLAB/R2013a/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined
LDDEBUGFLAGS = -g
LDOPTIMFLAGS = -O
LDEXTENSION = .mexa64
arguments =
-> LDCXX =
-> Link flags:
LDCXXFLAGS =
LDCXXDEBUGFLAGS =
LDCXXOPTIMFLAGS =
LDCXXEXTENSION =
arguments =

编辑mexopts.sh文件,可支持mex中编译opencv.(事先要安装Opencv)


2 编写drawcanvas.cpp文件

#include 
#include
#include
#include "opencv2/opencv.hpp"
#include
#include

using namespace cv;

#define max(a, b) ((a) > (b) ? (a) : (b))

const char *commands[] = {"lines", "circles", "rectangles", "texts"};

void drawLines(Mat& mat, int nrhs, const mxArray *prhs[]) {
//linesxy_4_columns, linecolor, linewidth,
if (nrhs != 5) {
mexErrMsgTxt("Error usage for draw lines: drawcanvas(img, cmd, pts_4_column, color, width)\n");
return;
}

double *lines = mxGetPr(prhs[2]);
int lrows = mxGetM(prhs[2]),
lcols = mxGetN(prhs[2]);
if (lcols != 4) {
mexErrMsgTxt("Error parameters for lines: it should be a mat with 4 columns.\n");
return;
}

double *Color = mxGetPr(prhs[3]);
if (mxGetNumberOfElements(prhs[3]) != 3) {
mexErrMsgTxt("Error: line color should be a mat with 3 columns indicating RGB.\n");
return;
}
Scalar color;
color[0] = Color[0];
color[1] = Color[1];
color[2] = Color[2];

int thickness = mxGetScalar(prhs[4]);
int linetype = CV_AA;

CvPoint startpt, endpt;
for(int i = 0; i startpt = Point(lines[i], lines[i + lrows]);
endpt = Point(lines[i + 2 * lrows], lines[i + 3 * lrows]);
line( mat, startpt, endpt, color, thickness, linetype );
}
}

void drawCircles(Mat& mat, int nrhs, const mxArray *prhs[]) {
//linesxy_4_columns, linecolor, linewidth,
if (nrhs != 5) {
mexErrMsgTxt("Error usage for draw circles: drawcanvas(img, cmd, circle_mat[x y r;], color, line_thickness)\n");
return;
}

double *circles = mxGetPr(prhs[2]);
int crows = mxGetM(prhs[2]),
ccols = mxGetN(prhs[2]);
if (ccols != 3) {
mexErrMsgTxt("Error parameters for circles: it should be a mat with 3 columns[cx cy r;].\n");
return;
}

double *Color = mxGetPr(prhs[3]);
if (mxGetNumberOfElements(prhs[3]) != 3) {
mexErrMsgTxt("Error: circle color should be a mat with 3 columns indicating RGB.\n");
return;
}
Scalar color;
color[0] = Color[0];
color[1] = Color[1];
color[2] = Color[2];

int thickness = mxGetScalar(prhs[4]);
int linetype = CV_AA;

CvPoint cpt;
double radius;
for(int i = 0; i cpt = Point(circles[i + crows], circles[i]);
radius = circles[i + 2 * crows];
circle( mat, cpt, (int)radius, color, thickness, linetype, 0);
}
}


void drawRectanges(Mat& mat, int nrhs, const mxArray *prhs[]) {
//linesxy_4_columns, linecolor, linewidth,
if (nrhs != 5) {
mexErrMsgTxt("Error usage for draw lines: drawcanvas(img, cmd, rects_4_column, color, width)\n");
return;
}

double *rects = mxGetPr(prhs[2]);
int lrows = mxGetM(prhs[2]),
lcols = mxGetN(prhs[2]);
if (lcols != 4) {
mexErrMsgTxt("Error parameters for lines: it should be a mat with 4 columns.\n");
return;
}

double *Color = mxGetPr(prhs[3]);
if (mxGetNumberOfElements(prhs[3]) != 3) {
mexErrMsgTxt("Error: line color should be a mat with 3 columns indicating RGB.\n");
return;
}
Scalar color;
color[0] = Color[0];
color[1] = Color[1];
color[2] = Color[2];

int thickness = mxGetScalar(prhs[4]);
int linetype = CV_AA;

CvPoint startpt, endpt;
for(int i = 0; i startpt = Point(rects[i], rects[i + lrows]);
endpt = Point(rects[i + 2 * lrows], rects[i + 3 * lrows]);
rectangle( mat, startpt, endpt, color, thickness, linetype );
}
}

void drawTexts(Mat& mat, int nrhs, const mxArray *prhs[]) {
//linesxy_4_columns, linecolor, linewidth,
if (nrhs != 7) {
mexErrMsgTxt("Error usage for draw texts: drawcanvas(img, cmd, sliced_text_with_#, points, fontScale, thickness, color)\n");
return;
}

vector strings;
unsigned char *ptr0 = (unsigned char *)mxGetPr(prhs[2]), *ptr1 = ptr0;
char *buf = mxArrayToString(prhs[2]); //注意:Matlab的字符串类型如何转换为C的字符串类型
int len = strlen(buf);
char tmp[256];
int cnt = 0;
for(int i = 0; i if (buf[i] == '#') {
strings.push_back(string(tmp));
//mexPrintf("%s\n", strings[strings.size()-1].c_str());
cnt = 0;
}
else {
if (cnt <255) {
tmp[cnt++] = buf[i];
tmp[cnt] = '\0';
}
}
}
if (cnt > 0)
strings.push_back(string(tmp));
if (buf)
mxFree(buf);

//debug
/*
for(int i = 0; i mexPrintf("*%s\n", strings[i].c_str());
return;
*/
double *points = (double *)mxGetPr(prhs[3]);
int prows = mxGetM(prhs[3]), pcols = mxGetN(prhs[3]);
if (prows != strings.size()) {
mexErrMsgTxt("Error: the numbers of parsed text and pointers are not equal.\n");
return;
}

int fOntFace= FONT_HERSHEY_PLAIN;
int fOntScale= mxGetScalar(prhs[4]);
int thickness = max(1, mxGetScalar(prhs[5]));
int linetype = CV_AA;

if (fontScale <= 0) {
mexErrMsgTxt("Error: fontsize is less than or equal to 0.\n");
return;
}


double *Color = mxGetPr(prhs[6]);
if (mxGetNumberOfElements(prhs[6]) != 3) {
mexErrMsgTxt("Error: text color should be a mat with 3 columns indicating RGB.\n");
return;
}
Scalar color;
color[0] = Color[0];
color[1] = Color[1];
color[2] = Color[2];

CvPoint startpt;
string str;
Size sz;

int baseLine = 0;
for(int i = 0; i startpt = Point(points[i], points[i + prows]);
str = strings[i];
//sz = getTextSize(str, fontFace, fontScale, thickness, &baseLine);
putText( mat, str.c_str(), startpt, fontFace, fontScale, color, thickness, linetype );
}
}

string transClassID(mxClassID id) {
switch (id) {
case mxLOGICAL_CLASS: return "mxLOGICAL_CLASS";
case mxDOUBLE_CLASS: return "mxDOUBLE_CLASS";
case mxSINGLE_CLASS: return "mxSINGLE_CLASS";
case mxINT8_CLASS: return "mxINT8_CLASS";
case mxUINT8_CLASS: return "mxUINT8_CLASS";
case mxINT16_CLASS: return "mxINT16_CLASS";
case mxUINT16_CLASS: return "mxUINT16_CLASS";
case mxINT32_CLASS: return "mxINT32_CLASS";
case mxUINT32_CLASS: return "mxUINT32_CLASS";
case mxINT64_CLASS: return "mxINT64_CLASS";
case mxUINT64_CLASS: return "mxUINT64_CLASS";
default: return "unknown";
}
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
mxClassID classID = mxGetClassID(prhs[0]);
//mexPrintf("%d --> %s\n", classID, transClassID(classID).c_str());
if (classID != mxINT8_CLASS && classID != mxUINT8_CLASS) {
mexErrMsgTxt("Error: input image should be uint8 type with 3 channels.\n");
return;
}

char buf[256];
int cmdidx = -1;

mxGetString(prhs[1], buf, 255);
for(int i = 0; i <4; i++) {
if (strcmp(buf, commands[i]) == 0)
{
cmdidx = i;
break;
}
}

if (cmdidx == -1)
{
mexErrMsgTxt("Error: command can not be recognized correctly.\n");
return;
}

const int *dims = mxGetDimensions(prhs[0]);
int height = dims[0], width = dims[1], channels = dims[2];
//mexPrintf("%d %d %d\n", height, width, channels);

if (channels != 3) {
mexErrMsgTxt("Error: input image should be of 3 channels.\n");
return;
}
if (height <= 0 || width <= 0) {
mexErrMsgTxt("Error: Wrong canvas sizes information.\n");
return;
}

//转换Matlab图像到Opencv图像
Mat mat = Mat::zeros(height, width, CV_8UC3);
char *inVals = (char *)mxGetPr(prhs[0]);
Vec3b vals;
for(int i = 0; i for(int j = 0; j for(int c = 0; c <3; c++)
vals[c] = inVals[c * mat.rows * mat.cols + j * mat.rows + i];
mat.at(i, j) = vals;
}

switch(cmdidx) {
case 0: drawLines(mat, nrhs, prhs); break;
case 1: drawCircles(mat, nrhs, prhs); break;
case 2: drawRectanges(mat, nrhs, prhs); break;
case 3: drawTexts(mat, nrhs, prhs); break;
default: return;
};

nlhs = 1;
plhs[0] = mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL);
char *outVals = (char *)mxGetPr(plhs[0]);

//转换Opencv图像到matlab图像
for(int i = 0; i for(int j = 0; j vals = mat.at(i, j);
for(int c = 0; c <3; c++)
outVals[c * mat.rows * mat.cols + j * mat.rows + i] = vals[c];
}
}

3 Matlab测试程序

mex drawcanvas.cpp;

img = im2uint8(zeros(500, 500, 3));
close all;

tic;
%绘制线
%drawcanvas(img, cmd, pts_4_column, color, width)
img = drawcanvas(img, 'lines', rand(300, 4) * 500, [255 0 255], 1);

%绘制圆
%drawcanvas(img, cmd, circle_mat[x y r;], color, line_thickness)
xy = rand(30, 2) * 450 + 50;
r = rand(30, 1) .* (30 + rand(30, 1) * 100);
circles = [xy r];
img = drawcanvas(img, 'circles', circles, [0 0 255], 2);
%绘制实心圆--thickness=-1
img = drawcanvas(img, 'circles', [200 200 50], [0 255 255], -1);

%绘制矩形
%drawcanvas(img, cmd, rects_4_column, color, width)
img = drawcanvas(img, 'rectangles', rand(30, 4) * 200 + 100, [255 0 0], 1);

%绘制英文字符数组,用#分割不同数组
%drawcanvas(img, cmd, sliced_text_with_#\\n, points, fontScale, thickness, color)
img = drawcanvas(img, 'texts', 'Hello#world', [30 200; 200 250], 4, 4, [0 255 0]);
toc

imshow(img);

imwrite(img, 'canvas.png', 'png');



4 运行结果



推荐阅读
  • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
  • 解析SQL查询结果的排序问题及其解决方案
    本文探讨了为什么某些SQL查询返回的数据集未能按预期顺序排列,并提供了详细的解决方案,帮助开发者理解并解决这一常见问题。 ... [详细]
  • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
  • 本文详细介绍了C语言的起源、发展及其标准化过程,涵盖了从早期的BCPL和B语言到现代C语言的演变,并探讨了其在操作系统和跨平台编程中的重要地位。 ... [详细]
  • 在创建新的Android项目时,您可能会遇到aapt错误,提示无法打开libstdc++.so.6共享对象文件。本文将探讨该问题的原因及解决方案。 ... [详细]
  • JavaScript 基础语法指南
    本文详细介绍了 JavaScript 的基础语法,包括变量、数据类型、运算符、语句和函数等内容,旨在为初学者提供全面的入门指导。 ... [详细]
  • 本文介绍了一个SQL Server自定义函数,用于从字符串中提取仅包含数字和小数点的子串。该函数通过循环删除非数字字符来实现,并附带创建测试表、存储过程以演示其应用。 ... [详细]
  • 深入理解Java字符串池机制
    本文详细解析了Java中的字符串池(String Pool)机制,探讨其工作原理、实现方式及其对性能的影响。通过具体的代码示例和分析,帮助读者更好地理解和应用这一重要特性。 ... [详细]
  • 本文介绍了如何使用JavaScript的Fetch API与Express服务器进行交互,涵盖了GET、POST、PUT和DELETE请求的实现,并展示了如何处理JSON响应。 ... [详细]
  • 本文探讨了如何通过预处理器开关选择不同的类实现,并解决在特定情况下遇到的链接器错误。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 在尝试使用C# Windows Forms客户端通过SignalR连接到ASP.NET服务器时,遇到了内部服务器错误(500)。本文将详细探讨问题的原因及解决方案。 ... [详细]
  • 使用JS、HTML5和C3创建自定义弹出窗口
    本文介绍如何结合JavaScript、HTML5和C3.js来实现一个功能丰富的自定义弹出窗口。通过具体的代码示例,详细讲解了实现过程中的关键步骤和技术要点。 ... [详细]
  • 搭建Jenkins、Ant与TestNG集成环境
    本文详细介绍了如何在Ubuntu 16.04系统上配置Jenkins、Ant和TestNG的集成开发环境,涵盖从安装到配置的具体步骤,并提供了创建Windows Slave节点及项目构建的指南。 ... [详细]
author-avatar
手机用户2602931923_450
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有