2

I open the picture with python, send it to the C ++ function for processing, and return the picture. How to correctly get a picture from a c ++ function?

Segmentation error

Code example:

C++

// t_lib.cpp 
#include "opencv2/opencv.hpp"

extern "C" unsigned char*  getfg(int rows,int cols, unsigned char* fdata)
//extern "C" void getfg(int rows,int cols, unsigned char* fdata)
{
    cv::Mat frame = cv::Mat(rows, cols, CV_8UC3, (void *) fdata);
    // Work 
    //cv::imshow("Display window C++", frame);
    //cv::waitKey(0);

    // do something

    return frame.data; //fdata;
}

Python 2.7

# test.py
import cv2
import numpy as np
import ctypes
lib = ctypes.cdll.LoadLibrary('./lib.so')

def getfg(img):
    ptr = lib.getfg(img.shape[0], img.shape[1], img.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte)))
    buf = (ctypes.c_ubyte * img.shape[0] * img.shape[1]  * 3).from_address(ptr)
    res = np.ndarray(buffer=buf, dtype=np.uint8, shape=(img.shape[0], img.shape[1], 3), order="C")
    return res

f = cv2.imread("sample.jpg")
#gray_image = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)
AS = getfg(f)
print AS.shape
#np.array(AS)[0]
cv2.imshow("Window Python", AS)
cv2.waitKey(0)

Compilation:

g++ -c -fPIC t_lib.cpp -o lib -lX11 $(pkg-config opencv --cflags --libs) -I/usr/include/python2.7 -I/usr/lib/python2.7;

g++ -shared -Wl,-soname,lib.so -o lib.so lib -lopencv_core -lopencv_highgui -lopencv_imgproc

command for see opencv libs:

pkg-config opencv --cflags --libs

output:

-I/usr/include/opencv -lopencv_shape -lopencv_stitching 
-lopencv_superres -lopencv_videostab -lopencv_aruco 
-lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib
-lopencv_datasets -lopencv_dpm -lopencv_face 
-lopencv_freetype -lopencv_fuzzy -lopencv_hdf 
-lopencv_line_descriptor -lopencv_optflow -lopencv_video 
-lopencv_plot -lopencv_reg -lopencv_saliency -lopencv_stereo 
-lopencv_structured_light -lopencv_phase_unwrapping -lopencv_rgbd 
-lopencv_viz -lopencv_surface_matching -lopencv_text 
-lopencv_ximgproc -lopencv_calib3d -lopencv_features2d 
-lopencv_flann -lopencv_xobjdetect -lopencv_objdetect 
-lopencv_ml -lopencv_xphoto -lopencv_highgui 
-lopencv_videoio -lopencv_imgcodecs -lopencv_photo 
-lopencv_imgproc -lopencv_core

version c++ OpenCV 3.2.0

  • Please check your compilation command - I believe the `pkg-config` stuff should be inside modern backticks, i.e. `g++ ... $(pkg-config --cflags --libs opencv) ...` – Mark Setchell Sep 11 '19 at 16:19
  • Please run the `pkg-config` command I suggested on its own. It should spit out a load of include and link info. If so, please correct your question as I suggested. If not, that is probably the problem. – Mark Setchell Sep 11 '19 at 16:36
  • If this is a new project, why are you using Python 2.7 which is discontinued in 5 months when Python 3 has been out 10+ years? – Mark Setchell Sep 11 '19 at 16:37
  • Please run this and add the output into your question `pkg-config opencv --cflags --libs` Start any line of code with 4 spaces to format it as code. – Mark Setchell Sep 11 '19 at 17:02
  • Comments are not a good place for lots of code and output... ;-) – Mark Setchell Sep 11 '19 at 17:03
  • I have nominated this question for re-opening. It seems quite clear to me that it is a legitimate question, with a pretty good attempt at code, that reasonably asks how to pass an image in a Numpy array from Python to C++ and then process and return the result. – Mark Setchell Sep 11 '19 at 18:46
  • Did you try putting some `std::cout` statements in your C++ code to see if you get the correct height and width at keast without returning anything. Then try zeroing the pixel data as well. Then try returning some data. Just small steps so you can see where it fails. – Mark Setchell Sep 12 '19 at 08:57
  • I'm not sure I am the right person to help you so I am deleting my answer so that others are more likely to help you. Sorry I couldn't solve it. – Mark Setchell Sep 12 '19 at 14:46

2 Answers2

0

you have to compile this c++ code into a shared library, according to this and then write a wrapper

ignacio
  • 1,181
  • 2
  • 15
  • 28
0

One of the way you can do, using memcpy

python3.x main.py

import cv2
import numpy as np
import ctypes

cv_lib = ctypes.CDLL("./cpp_function.so")

def opencv_cpp_operation(im):
    ND_POINTER_1 = np.ctypeslib.ndpointer(dtype=np.float64, 
                                        ndim=im.ndim,
                                        flags="C")
    cv_lib.opencv_op.argtypes = [ND_POINTER_1,ctypes.c_size_t]
    cv_lib.opencv_op.restype = np.ctypeslib.ndpointer(dtype=np.float64, ndim=im.ndim, shape=im.shape, flags="C")
    ret_img = cv_lib.opencv_op(im, *im.shape, im.shape[0] * im.shape[1])
    return ret_img

im = cv2.imread("./imagepath.jpg", 0)
np_array = opencv_cpp_operation(im)

c++ cpp_function.cpp

Compile using g++ -shared -fPIC cpp_function.cpp -o cpp_function.so -I /usr/include/opencv4/ -L /usr/lib -lopencv_core -lopencv_imgproc

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
extern "C" {
    double* opencv_op(double *a1, size_t a1_h, size_t a1_w, int size){
            cv::Mat A(a1_h,a1_w,CV_64F);
            std::memcpy(A.data, a1, a1_h*a1_w*sizeof(double));   

            // Now use Mat A for your processing than return it python

            cv::Mat C(a1_h,a1_w,CV_64F);
            C = A * 2; 
            double* ret_arr = new double[size]; 
            std::memcpy(ret_arr, C.data, a2_h*a2_w*sizeof(double));
            
            return ret_arr;

    }
}
Devil
  • 1,054
  • 12
  • 18