Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cuixing158 committed Aug 12, 2023
0 parents commit b67dd16
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 0 deletions.
76 changes: 76 additions & 0 deletions OpenCV_API.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
%================================================================
% This class abstracts the API to an external OpenCV library.
% It implements static methods for updating the build information
% at compile time and build time.

classdef OpenCV_API < coder.ExternalDependency
%#codegen

methods (Static)

function bName = getDescriptiveName(~)
bName = 'OpenCV_API';
end

function tf = isSupportedContext(buildContext)
myTarget = {'mex','rtw'};% 验证代码生成目标为mex或者dll,lib,exe
if buildContext.isCodeGenTarget(myTarget)
tf = true;
else
error('OpenCV_API only supported for mex, lib, exe, dll');
end

% hw = buildContext.getHardwareImplementation();

end

function updateBuildInfo(buildInfo, buildContext)
% 输入buildInfo请参考:RTW.BuildInfo
% 输入buildContext请参考:coder.BuildConfig class
%
% Get file extensions for the current platform
% [~, linkLibExt, execLibExt, ~] = buildContext.getStdLibInfo();

% Code to run on Linux platform
includeFilePath = fullfile("E:\opencv4_4_0\opencv\MinGW64_v8_OpenCV4_4_Contrib_install\include");
buildInfo.addIncludePaths(includeFilePath);

% Link files
libPath = fullfile("E:\opencv4_4_0\opencv\MinGW64_v8_OpenCV4_4_Contrib_install\x64\mingw\lib");
linkFiles = "libopencv_world440.dll.a";
linkPath = libPath;
linkPriority = "";
linkPrecompiled = true;
linkLinkOnly = true;
group = '';
buildInfo.addLinkObjects(linkFiles, linkPath, ...
linkPriority, linkPrecompiled, linkLinkOnly, group);

% include and source path
% buildInfo.addIncludePaths("./");
% buildInfo.addSourcePaths("./");
end

%API for library function 'imread'
function outImg = imread(imagePath)
arguments
imagePath (1,1) string
end

outImg = coder.nullcopy(zeros(480,640,3,"uint8"));
if coder.target('MATLAB')
% running in MATLAB, use built-in addition
outImg = imread_opencv_mex(imagePath);
else
% Add the required include statements to the generated function code
coder.cinclude('opencvAPI.h');
% include external C++ functions
coder.updateBuildInfo('addSourceFiles', "opencvAPI.cpp");

% 调用OpenCV C++代码包装器
imgPath = [char(imagePath),0];
coder.ceval('imreadOpenCV', coder.rref(imgPath),coder.wref(outImg));
end
end
end
end
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# MATLAB MEX file For C/C++ code generation

![logo](images/logo.PNG)

## OverView

In order to call external C/C++ library functions, it is generally recommended to use the [mex](https://ww2.mathworks.cn/help/matlab/ref/mex.html) built-in function to compile the source code into a mex executable file, but the disadvantage is that it is not easy to generate C/C++ code in turn if there are other matlab code mixed in. This example is just to show how to use [codegen](https://ww2.mathworks.cn/help/coder/ref/codegen.html) two-way through this process, not limited to the example itself, is a general method, another advantage is not limited to the code generation of various restrictions, fully integrated with C/C++ programming.

## Requirements

- MATLAB
- Matlab Coder toolbox
- [Supported and Compatible Compilers](https://ww2.mathworks.cn/en/support/requirements/supported-compilers.html)
- Your External C/C++ Library(This example uses OpenCV as an example)

## How to setup

### 1.Configuring the compiler

In the command window,configure your complier.

```matlab
mex -setup C++
```

### 2.Source Code Preparation

Prepare your C/C++ code and MATLAB entry-point function.Prepare the implementation of the `updateBuildInfo(buildInfo, buildContext)` member function, rewritten according to the path of the external library. (header files and library files).

### 3.Generate or Compile

Generate or compile the files you want with the `codegen` command.
For example:

```matlab
imagePath = "./test_480x640x3.jpg";
input1 = coder.typeof(imagePath);
input1.StringLength=inf;
codegen -config:mex imread_opencv -args {input1} -lang:c++ -report
```
Binary file added images/logo.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions imread_opencv.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
function outImg = imread_opencv(imagePath)%#codegen
% Brief: Write a function imreadOpencv that calls the external library function.
% Details:
% Read a uint8 image of size 480*640
%
% Syntax:
% outImg = imread_opencv(imagePath)
%
% Inputs:
% imagePath - [1,1] size,[string] type,image path
%
% Outputs:
% outImg - [480,640] size,[uint8] type,Description
%
% codegen command:
% imagePath = "./test_480x640_uint8.jpg";
% input1 = coder.typeof(imagePath);
% input1.StringLength=inf;
%
% codegen -config:mex imread_opencv -args {input1} -lang:c++ -report
%
% Usage Example:
% imagePath = "./test_480x640_uint8.jpg";
% result = imread_opencv(imagePath);
%
%
% Example:
% None
%
% See also: None


arguments
imagePath (1,1) string
end
outImg = OpenCV_API.imread(imagePath);
end
29 changes: 29 additions & 0 deletions opencvAPI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "opencvAPI.h"

// 对应OpenCV的cv::Mat转MATLAB uint8类型或logical图像
void convertCVToMatrix(cv::Mat &srcImg, int rows, int cols, int channels, unsigned char dst[]) {
CV_Assert(srcImg.type() == CV_8UC1 || srcImg.type() == CV_8UC3);
size_t elems = rows * cols;
if (channels == 3) {
cv::Mat channels[3];
cv::split(srcImg.t(), channels);

memcpy(dst, channels[2].data, elems * sizeof(unsigned char)); //copy channel[2] to the red channel
memcpy(dst + elems, channels[1].data, elems * sizeof(unsigned char)); // green
memcpy(dst + 2 * elems, channels[0].data, elems * sizeof(unsigned char)); // blue
} else {
srcImg = srcImg.t();
memcpy(dst, srcImg.data, elems * sizeof(unsigned char));
}
}


void imreadOpenCV(const char *imagePath, unsigned char outImg[]) {
std::string imgPath(imagePath);
cv::Mat srcImg = cv::imread(imgPath, cv::IMREAD_COLOR);
if (srcImg.empty()) {
std::runtime_error("read image is empty!");
}

convertCVToMatrix(srcImg, srcImg.rows, srcImg.cols, srcImg.channels(), outImg);
}
22 changes: 22 additions & 0 deletions opencvAPI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

#ifndef _OPENCVAPI_ALLPLATFORM_
#define _OPENCVAPI_ALLPLATFORM_

// base
#include <iostream>
#include <string>
#include <fstream>
#include <vector>

// OpenCV
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>


// "marshalling"
void convertCVToMatrix(cv::Mat &srcImg, int rows, int cols, int channels, unsigned char dst[]);

void imreadOpenCV(const char *imagePath, unsigned char outImg[]);

#endif
Binary file added test_480x640x3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b67dd16

Please sign in to comment.