首页 > 代码库 > Matlab中利用mex编译Opencv实现画板绘图功能
Matlab中利用mex编译Opencv实现画板绘图功能
图形绘制是标记和可视化数据的重要方法.
通过在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 <stdlib.h> #include <mex.h> #include <matrix.h> #include "opencv2/opencv.hpp" #include <vector> #include <string> 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 < lrows; 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 < crows; 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 < lrows; 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<string> 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 < len; 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 < strings.size(); 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 < prows; 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 < mat.rows; i++) for(int j = 0; j < mat.cols; j++) { for(int c = 0; c < 3; c++) vals[c] = inVals[c * mat.rows * mat.cols + j * mat.rows + i]; mat.at<Vec3b>(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 < mat.rows; i++) for(int j = 0; j < mat.cols; j++) { vals = mat.at<Vec3b>(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 运行结果
Matlab中利用mex编译Opencv实现画板绘图功能
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。