Конвертировать указатель C ++ в массив nyPython - PullRequest
0 голосов
/ 27 июня 2018

Я работаю над C / C ++ DLL , которая использовала OpenCV, и в этом я выполняю некоторые операции. В этом примере я изменяю контраст изображения, которое я читаю на Python , переносу в DLL для выполнения операции и возвращаю результат на Python для его отображения. Я делаю это, используя указатели на первый пиксель каждого изображения, но в Python я не нахожу способ правильно воссоздать изображение, используя этот указатель.

Я уже проверил, что объект Mat в C ++ является непрерывным, и я проверяю результат, сохраненный из DLL, который является правильным. Проблема в Python для меня, но я не вижу, где я делаю что-то не так.

Класс и функция C ++:

#pragma once
#include <vector>
#include <string>
#include <fstream>
#include <opencv2/core/core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <thread>

using namespace cv;
using namespace std;

class EpsImageProcessing
{
    // -------------- Methods --------------
public:
    EpsImageProcessing();
    ~EpsImageProcessing();

    unsigned short * imAdjustContrast(void * ptrImg, int width, int height, int contrastValue);

    // -------------- Atributes --------------
    Mat imgResult;
    unsigned short *imgAdress;
};


unsigned short * EpsImageProcessing::imAdjustContrast(void * ptrImg, int width, int height, int contrastValue)
{
    // Get image and reshape it as Mat object
    Mat imgTemp = Mat(height, width, CV_8UC1, (uchar*)ptrImg);

    // Convert to double to perform calculations
    imgTemp.convertTo(imgTemp, CV_32FC1);

    // Calculate the contrast coefficient
    float coeff = (259*((float)contrastValue+255)) / (255*(259 - (float)contrastValue));

    // Change contrast
    imgTemp = coeff * (imgTemp - 128) + 128;

    // Convert image to original type
    imgTemp.convertTo(imgTemp, CV_8UC1);

    // Return result
    imgResult= imgTemp.clone(); // imgTmp is an attribute of the class of my DLL
    imwrite("imgAfter.jpg", imgResult);

    bool test = imgResult.isContinuous(); // return true

    imgAdress = imgResult.ptr<ushort>();

    return imgAdress; //imgResult.ptr<ushort>(); // (unsigned short *)imgResult.data;
}

Затем оболочка C для связи между C ++ и другими языками, такими как Python:

__declspec(dllexport) unsigned short* __stdcall imAdjustContrast(void* handle, void* imgPtr, int width, int height, int contrastValue)
{
    if (handle)
    {
        EpsImageProcessing* data = (EpsImageProcessing*)handle;
        return data->imAdjustContrast(imgPtr, width, height, contrastValue);
    }
    return false;
}

и код Python:

from ctypes import *
import numpy, os, cv2
import matplotlib.pyplot as plt

dirpath = os.environ['PATH']
os.environ['PATH'] = dirpath + ";C:/x64/Debug/" # include of opencv_world.dll


mydll = cdll.LoadLibrary("MyDll.dll")
class mydllClass(object):
    def __init__(self, width, height, nFrame, path, filename):
        mydll.AllocateHandleImg.argtypes = []
        mydll.AllocateHandleImg.restype = c_void_p

        mydll.imAdjustContrast.argtypes = [c_void_p, c_void_p, c_int, c_int, c_int]
        mydll.imAdjustContrast.restype = POINTER(c_ushort)

        self.obj = mydll.AllocateHandleImg()

    def imAdjustContrast(self, ptrImg, width, height, contrast):
        return mydll.imAdjustContrast(self.obj, ptrImg, width, height, contrast)



img0 = cv2.imread("C:\\Users\\mg\\Downloads\\imgInit.jpg", 0)
imgC = myclass.imAdjustContrast(img0.__array_interface__['data'][0], img0.shape[1], img0.shape[0], -127)
imgAfter = cv2.imread("C:\\Users\\mg\\Downloads\\imgAfter.jpg", 0)

image = numpy.zeros((img0.shape[0],img0.shape[1]), dtype=numpy.dtype(numpy.uint8))
for i in range(img0.shape[0]):
    for j in range(img0.shape[1]):
        indice = i*img0.shape[1]+j
        image[i,j] = numpy.uint8(imgC[indice])
newImg = numpy.ctypeslib.as_array(cast(imgC, POINTER(c_uint8)), shape=(img0.shape))

plt.figure()
plt.subplot(221)
plt.imshow(imgAfter)
plt.gray()
plt.colorbar()
plt.title('image saved from C++ DLL')
plt.subplot(222)
plt.imshow(image)
plt.gray()
plt.colorbar()
plt.title('image recreated in Python (for loop)')
plt.subplot(223)
plt.imshow(newImg)
plt.gray()
plt.colorbar()
plt.title('image recreated in Python (cast)')
plt.show()

И окончательный результат на Python: enter image description here

1 Ответ

0 голосов
/ 27 июня 2018

Я обнаружил, что небольшая разница между двумя «хорошими изображениями» (изображение, сохраненное в C ++ и воссозданное в Python методом приведения) заключается в сжатии изображения (.jpg), которое отличается между Python и C ++. Работа с png и изображением, созданным в Python с указателем C ++, в порядке с методом cast.

Таким образом, проблема теперь в двух циклах for, которые не создают изображение из указателя хорошим способом. Есть идеи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...