Drawing is an important way to mark and visualize data.
By integrating the drawing board function in MATLAB, it can facilitate scientific computing.
1. Set MATLAB to support opencv Compilation
Operating System: Qilin 14.04 (based on Ubuntu 14.04)
Command: 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 =
Edit the mexopts. Sh file to compile opencv in Mex. (You must install opencv in advance)
2. Compile the drawcanvas. cpp file.
#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 Testing Program
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=-1img = 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]);tocimshow(img);imwrite(img, 'canvas.png', 'png');
4. Running result
Use Mex to compile opencv in MATLAB to implement drawing board Function