How can convert PyObject variable to Mat in c++ opencv code

跟風遠走 提交于 2020-05-01 09:16:52

问题


I have a c++ facerecognition code and a python code in opencv. In python code i read frames from a robot and i want to send this fram to my c++ code. I use this link tho call python function in c++ function.

my c++ function is embed.cpp:

#include <Python.h>
#include <stdlib.h>
#include "opencv2/core/core.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <fstream>
#include <sstream>
#include </home/nao/Desktop/python/boost_1_61_0/boost/python/extract.hpp>
#include </home/nao/Desktop/python/boost_1_61_0/boost/python/converter/registry.hpp>

namespace py = boost::python;
int main()
{

// Set PYTHONPATH TO working directory
   setenv("PYTHONPATH",".",1);
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *presult;
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyString_FromString((char*)"alvideo2");
// Load the module object
 pModule = PyImport_Import(pName);
// pDict is a borrowed reference 
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference 
pFunc = PyDict_GetItemString(pDict, (char*)"showNaoImage");

if (PyCallable_Check(pFunc))
{
 pValue=Py_BuildValue("(z)",(char*)"something");
PyErr_Print();
printf("Let's give this a shot!\n");
presult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
} else{
PyErr_Print();
}

cv::imshow("Original_image",presult);

cvWaitKey(0);

Py_DECREF(pValue);
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
 Py_Finalize();
 return 0;
}

and my python code is alvideo2.py:

# -*- encoding: UTF-8 -*-
# Get an image from NAO. Display it and save it using PIL.

import cv2
import os #new
import sys
import time 
import numpy as np
from PIL import Image
from naoqi import ALProxy
from PIL import ImageFont
from PIL import ImageDraw 

#---------------------------------------------------------------------------
def showNaoImage(text):
  """
  First get an image from Nao, then show it on the screen with PIL.
  """
  IP = "192.168.1.18"  # Replace here with your NaoQi's IP address.
  PORT = 9559

  # Read IP address from first argument if any.
  #if len(sys.argv) > 1:
    #IP = sys.argv[1]

  camProxy = ALProxy("ALVideoDevice", IP, PORT)
  resolution = 2    # VGA
  colorSpace = 11   # RGB

  videoClient = camProxy.subscribe("python_client", resolution, colorSpace, 5)

  #t0 = time.time()

  # Get a camera image.
  # image[6] contains the image data passed as an array of ASCII chars.
  naoImage = camProxy.getImageRemote(videoClient)

  # Time the image transfer.
  #print "acquisition delay ", t1 - t0

  camProxy.unsubscribe(videoClient)


  # Now we work with the image returned and save it as a PNG  using ImageDraw
  # package.

  # Get the image size and pixel array.
  imageWidth = naoImage[0]
  imageHeight = naoImage[1]
  array = naoImage[6]

  # Create a PIL Image from our pixel array.
  im = Image.frombytes("RGB", (imageWidth, imageHeight), array)
  frame=np.array(im)
  #cv2.imshow("Faces found", frame)
  #cv2.waitKey(0) 
  return frame

So, my question is how can i use returnd fram in cv::imshow("Original_image",presult); ? . in otherwise how can i convert pyobject to Mat?

thanks alot.


回答1:


For Python 3.x C-API:

In Python side return the frame in bytearray format:

return bytearray(frame)

and in cpp side get it by PyByteArray_AsString function:

pData = PyObject_CallObject(pFunc, pArgs);
uchar *data = (uchar *)PyByteArray_AsString(pData );
cv::Mat img(rows, cols, CV_8UC3, data)



回答2:


Since showNaoImage returns a numpy array, you can use numpy's C API to extract values from the frame, or obtain the pointer to the memory that holds the values. See the documentation, specifically the part that deals with array data access.

To convert the data to a Mat array accepted by cv::imshow, use the Mat constructor with the data and its dimensions. For example:

// numpy array created from a PIL image is 3-dimensional:
// height x width x num_channels (num_channels being 3 for RGB)
assert (PyArray_NDIM(presult) == 3 && PyArray_SHAPE(presult)[2] == 3);

// Extract the metainformation and the data.
int rows = PyArray_SHAPE(presult)[0];
int cols = PyArray_SHAPE(presult)[1];
void *frame_data = PyArray_DATA(presult);

// Construct the Mat object and use it.
Mat cv_frame(rows, cols, CV_8UC3, frame_data);
cv::imshow("Original_image", cv_frame);



回答3:


If I remember correctly, there should be a specific function available in opencv for python called pyopencv_to(pyobject, cv::mat, ... ), which also takes strides into the account and can handle both gray and color images.



来源:https://stackoverflow.com/questions/39201533/how-can-convert-pyobject-variable-to-mat-in-c-opencv-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!