python和C++共享記憶體傳輸影象
阿新 • • 發佈:2020-10-25
原理
python沒有辦法直接和c++共享記憶體互動,需要間接呼叫c++打包好的庫來實現
流程
1 C++共享記憶體打包成庫
2 python呼叫C++庫往共享記憶體存影象資料
3 C++測試程式碼從共享記憶體讀取影象資料
實現
1c++打包庫
建立檔案
example.cpp
#include <iostream> #include <cassert> #include <stdlib.h> #include <sys/shm.h> #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include "opencv2/videoio.hpp" #define key 650 #define image_size_max 1920*1080*3 using namespace std; using namespace cv; typedef struct{ int rows; int cols; uchar dataPointer[image_size_max]; }image_head; int dump(int cam_num,int row_image, int col_image, void* block_data_image) { int shm_id = shmget(key+cam_num,sizeof(image_head),IPC_CREAT); if(shm_id == -1) { cout<<"shmget error"<<endl; return -1; } cout << " shem id is "<<shm_id<<endl; image_head *buffer_head; buffer_head = (image_head*) shmat(shm_id, NULL, 0); if((long)buffer_head == -1) { cout<<"Share memary can't get pointer"<<endl; return -1; } assert(row_image*col_image*3<=image_size_max); image_head image_dumper; image_dumper.rows=row_image; image_dumper.cols=col_image; uchar* ptr_tmp_image=(uchar*) block_data_image; for (int i=0;i<row_image*col_image*3;i++) { image_dumper.dataPointer[i] = *ptr_tmp_image; ptr_tmp_image++; } memcpy(buffer_head,&image_dumper,sizeof(image_dumper)); return 1; } extern "C" { int dump_(int cam_num,int row_image, int col_image, void* block_data_image) { int result=dump(cam_num,row_image, col_image, block_data_image); return result; } }
CMakeLists.txt
# cmake needs this line cmake_minimum_required(VERSION 2.8) # Define project name project(opencv_example_project) # Find OpenCV, you may need to set OpenCV_DIR variable # to the absolute path to the directory containing OpenCVConfig.cmake file # via the command line or GUI find_package(OpenCV REQUIRED) # If the package has been found, several variables will # be set, you can find the full list with descriptions # in the OpenCVConfig.cmake file. # Print some message showing some of them message(STATUS "OpenCV library status:") message(STATUS " version: ${OpenCV_VERSION}") message(STATUS " libraries: ${OpenCV_LIBS}") message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") if(CMAKE_VERSION VERSION_LESS "2.8.11") # Add OpenCV headers location to your include paths include_directories(${OpenCV_INCLUDE_DIRS}) endif() # Declare the executable target built from your sources add_library(opencv_example SHARED example.cpp) add_executable(test_example test_run.cpp) # Link your application with OpenCV libraries target_link_libraries(opencv_example ${OpenCV_LIBS}) target_link_libraries(test_example ${OpenCV_LIBS})
最後生成庫
2python呼叫C++動態庫進行存圖
#!/usr/bin/env python import sys #sys.path.append("/usr/lib/python3/dist-packages") #sys.path.append("/home/frank/Documents/215/code/parrot-groundsdk/.python/py3/lib/python3.5/site-packages") import cv2 import ctypes import numpy as np ll = ctypes.cdll.LoadLibrary lib = ll("./build/libopencv_example.so") lib.dump_.restype = ctypes.c_int count = 1 #path = "/home/frank/Documents/215/2020.10.24/python_ctypes/image/" while count < 30: path = "./image/"+str(count)+".jpg" print(path) image=cv2.imread(path) #cv2.imshow("test",image) #cv2.waitKey(0) image_data = np.asarray(image, dtype=np.uint8) image_data = image_data.ctypes.data_as(ctypes.c_void_p) value = lib.dump_(0,image.shape[0], image.shape[1], image_data) print(value) count += 1 if count == 30: count = 1
3 C++讀取共享記憶體獲取影象
#include <iostream> #include <stdlib.h> #include <sys/shm.h> #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include "opencv2/videoio.hpp" #define key 650 #define image_size_max 1920*1080*3 using namespace cv; using namespace std; typedef struct{ int rows; int cols; uchar dataPointer[image_size_max]; }image_head; int main() { int count = 1; while(true) { int shm_id = shmget(key+0,sizeof(image_head) ,IPC_CREAT); if(shm_id == -1) { cout<<"shmget error"<<endl; return -1; } cout << " shem id is "<<shm_id<<endl; image_head* buffer_head; buffer_head = (image_head*)shmat(shm_id, NULL, 0); if((long)buffer_head == -1) { perror("Share memary can't get pointer\n"); return -1; } image_head image_dumper; memcpy(&image_dumper, buffer_head, sizeof(image_head)); cout<<image_dumper.rows<<" "<<image_dumper.cols<<endl; uchar* data_raw_image=image_dumper.dataPointer; cv::Mat image(image_dumper.rows, image_dumper.cols, CV_8UC3); uchar* pxvec =image.ptr<uchar>(0); int count = 0; for (int row = 0; row < image_dumper.rows; row++) { pxvec = image.ptr<uchar>(row); for(int col = 0; col < image_dumper.cols; col++) { for(int c = 0; c < 3; c++) { pxvec[col*3+c] = data_raw_image[count]; count++; } } } cv::imshow("Win",image); cv::waitKey(1); } return 1; }