stay ( One )python call c++ Code 《 from C++ Shared link library compiled to python Call Guide 》 in , We have achieved in python Call in C++ The effect of the code . But new problems arise ,python in opencv The image data is ndarray Format ,C++ in opencv The image data is Mat Format , stay C++ As defined in test Function input parameter is Mat data , stay python You can't directly call ndarray Data as test The parameters of the function .
In this part, we will design c++ Function to receive and return image data , You can see how the image data is python Of ndarray and c++ Of Mat Directly circulating .
Here we define a MatSo class , This class has two functions , A function receives uchar type ( Image data ), And back to uchar type ( Image data ); Another function receives uchar* type ( Image data ), And back to buffer type ( Image data ).
// Dll2.cpp: Definition DLL Export function of application program .
#define EXPORT __declspec(dllexport)
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// MatSO Statement
class MatSO
{
public:
// This function receives uchar data , To Mat data , Show , And then back again uchar data
uchar *get_mat_and_return_uchar(uchar *matrix, int rows, int cols, int channels);
// This function receives uchar data , To Mat data , Show , And then back again buffle data
uchar *get_mat_and_return_buffer(uchar *matrix, int rows, int cols, int channels);
};
// mat Data is received and sent in uchar return
uchar *MatSO::get_mat_and_return_uchar(uchar *matrix, int rows, int cols, int channels)
{
// To be received uchar To Mat
cout << "rows=" << rows << "\ncols=" << cols << "\nchannels=" << channels;
Mat input_mat = Mat(Size(cols, rows), CV_8UC3, Scalar(255, 255, 255));
input_mat.data = matrix;
// Show Mat
imshow("input_mat", input_mat);
cv::waitKey(0);
// take Mat To uchar Type and return
// Be careful : Remember here Mat Of rol、row and channels, stay python To receive correctly
uchar *s = input_mat.data; // Mat turn ucahr*
return s;
}
// mat Data is received and sent in buffer return
uchar *MatSO::get_mat_and_return_buffer(uchar *matrix, int rows, int cols, int channels)
{
// To be received uchar To Mat
cout << "rows=" << rows << "\ncols=" << cols << "\nchannels=" << channels;
Mat input_mat = Mat(Size(cols, rows), CV_8UC3, Scalar(255, 255, 255));
input_mat.data = matrix;
// Show Mat
imshow("input_mat", input_mat);
cv::waitKey(0);
// take Mat To buffer And back to
// Be careful : Remember here Mat Of rol、row and channels, stay python To receive correctly
int height = input_mat.cols;
int width = input_mat.rows;
uchar *buffer = (uchar *)malloc(sizeof(uchar) * height * width * 3);
memcpy(buffer, input_mat.data, height * width * 3);
return buffer;
}
extern "C"
{
MatSO td; // packing MatSO, So that it can be in so Call outside the file
uchar *get_mat_and_return_uchar(uchar *matrix, int rows, int cols, int channels)
{
return td.get_mat_and_return_uchar(matrix, rows, cols, channels);
}
uchar *get_mat_and_return_buffer(uchar *matrix, int rows, int cols, int channels)
{
return td.get_mat_and_return_buffer(matrix, rows, cols, channels);
}
}
By the way CMakeLists.txt To configure :
cmake_minimum_required(VERSION 3.0.0)
project(hbp VERSION 0.1.0) # Project name
set(CMAKE_CXX_FLAGS "-std=c++11") # add to c++11 standard
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS}) # Header Directory
add_library(MatSo SHARED MatSo.cpp) # Set the type of output library
target_link_libraries(MatSo ${OpenCV_LIBS})
Here we have to finish cv2 Read a picture , And call MatSo Functions in class , Get the returned data and display .
The main steps are :
import cv2
import ctypes
from ctypes import *
import numpy as np
# Load shared link library
matso = ctypes.cdll.LoadLibrary("build/libMatSo.so")
# matso There are two functions we will use in
# Now define the types of input and output parameters for these two functions
# Reference resources :https://blog.csdn.net/qq_40047008/article/details/107785856
matso.get_mat_and_return_uchar.argtypes = (POINTER(c_ubyte), c_int, c_int, c_int)
matso.get_mat_and_return_uchar.restype = POINTER(c_ubyte)
img = cv2.imread("face.jpeg")
rows, cols, channels = img.shape
img = img.ctypes.data_as(POINTER(c_ubyte)) # take ndarray To c++ Of uchar type
return_uchar_data = matso.get_mat_and_return_uchar(img, rows, cols, channels) # Call the link library function , obtain uchar* data
# Notice the rows、rows and channels yes C++ When the function returns Mat Size , It doesn't mean the same as the above
# However, the image is not changed in the process of passing in the function and returning shape, So the numerical value is the same
np_canny = np.array(np.fromiter(return_uchar_data, dtype=np.uint8, count=cols * rows * channels))
np_canny = np_canny.reshape((rows, cols, 3))
cv2.imshow("q", np_canny)
cv2.waitKey(0)
get_mat_and_return_uchar and get_mat_and_return_buffer The difference is that the return type is different , Namely uchar* and buffer, But from the function type, we can see that they are all uchar, So in python The code in is the same
import cv2
import ctypes
from ctypes import *
import numpy as np
# Load shared link library
matso = ctypes.cdll.LoadLibrary("build/libMatSo.so")
# matso There are two functions we will use in
# Now define the types of input and output parameters for these two functions
# Reference resources :https://blog.csdn.net/qq_40047008/article/details/107785856
matso.get_mat_and_return_buffer.argtypes = (POINTER(c_ubyte), c_int, c_int, c_int)
# matso.get_mat_and_return_buffer.restype = POINTER(c_uint8)
matso.get_mat_and_return_buffer.restype = POINTER(c_ubyte)
img = cv2.imread("face.jpeg")
rows, cols, channels = img.shape
img = img.ctypes.data_as(POINTER(c_ubyte)) # take ndarray To c++ Of uchar type
return_uchar_data = matso.get_mat_and_return_buffer(img, rows, cols, channels) # Call the link library function , obtain uchar* data
# Notice the rows、rows and channels yes C++ When the function returns Mat Size , It doesn't mean the same as the above
# However, the image is not changed in the process of passing in the function and returning shape, So the numerical value is the same
np_canny = np.array(np.fromiter(return_uchar_data, dtype=np.uint8, count=cols * rows * channels))
np_canny = np_canny.reshape((rows, cols, 3))
cv2.imshow("q", np_canny)
cv2.waitKey(0)
Reference resources :Python call c++ The dynamics of the dll Data mapping in (Mat Type passing and structure passing )