Python 调用 C++ 传递numpy 数据详情

目录
  • 1.C++ 代码
  • 2.Python 代码

1.C++ 代码

Demo.h

#pragma once
void GeneratorGaussKernel(int ksize, float sigma, float* kernel);

void LeftAndRightMirrorImageUInt8(unsigned char* in, unsigned char* out, int width, int height);

void LeftAndRightMirrorImageFloat(float* in, float* out, int width, int height);

void UpAndDownMirrorImageFloat(float* in, float* out, int width, int height);

void UpAndDownMirrorImageUInt8(unsigned char* in, unsigned char* out, int width, int height);
void ImageFilterFloat(float* in, float* out, int width, int height, float* filterKernel, int kw, int kh);

void SaltAndPepperFloat(float* in, float* out, int width, int height, float minV, float maxV, float proportion);

void SaltAndPepperUInt8(unsigned char* in, unsigned char* out, int width, int height, float minV, float maxV, float proportion);
void ImageMinMax(float* in, int width, int height, int channels, float* minV, float* maxV);

void ImageMinMax(unsigned char* in, int width, int height, int channels, unsigned char* minV, unsigned char* maxV);
void ImageMulAAddBFloatFloat(float* in, float* out, int width, int height, int channels, float A, float B);

void ImageMulAAddBUInt8UInt8(unsigned char* in, unsigned char* out, int width, int height, int channels, float A, float B);
void ImageMulAAddBUInt8Float(unsigned char* in, float* out, int width, int height, int channels, float A, float B);

void NormalizeUInt8Float(unsigned char* in, float* out, int width, int height, int channels, int type);
void NormalizeFloatFloat(float* in, float* out, int width, int height, int channels, int type);
void RGBAvgUInt8Float(unsigned char* in, float* out, int width, int height);
void RGBAvgFloatFloat(float* in, float* out, int width, int height);

Demo.cpp

#include <Python.h>
#include <malloc.h>
#include <numpy/arrayobject.h>
#include <iostream>
#include <vector>
#include <xmmintrin.h>
#include <immintrin.h>
#include "omp.h"

class ImageCoord {
public:
    ImageCoord() {
        x = 0; y = 0;
    }

    ImageCoord(const ImageCoord& coord) {
        x = coord.x;
        y = coord.y;
    }
    ImageCoord(int x, int y) {
        this->x = x;
        this->y = y;
    }
    void operator= (ImageCoord& coord) {
        x = coord.x;
        y = coord.y;
    }

    int x, y;
};

class Random {
public:
    Random() {
        srand((unsigned int)time(NULL));
    }

    ImageCoord RandomImageCoord(int width, int height) {
        ImageCoord ans;
        ans.x = rand() % width;
        ans.y = rand() % height;
        return ans;
    }
    bool RandomBoolean() {
        return rand() % 2 == 1;
    }
};

static Random gRandom;

void GeneratorGaussKernel(int ksize, float sigma, float* kernel)
{
    int bufferSize = ksize * ksize;
    float sigmasigma2 = 2.0f * sigma * sigma;
    float sigmasigma2Inv = 1.f / sigmasigma2;
    float sigmasigma2PIInv = sigmasigma2Inv / 3.14159265358979f;
    int radius = ksize / 2;
    float sum = 0.f;
    for (int i = -radius; i <= radius; ++i) {
        for (int j = -radius; j <= radius; ++j) {
            kernel[(i + radius) * ksize + (j + radius)] = sigmasigma2PIInv * expf(-(i * i + j * j) * sigmasigma2Inv);
        }
    }

    for (int i = 0; i < bufferSize; ++i) {
        sum += kernel[i];
    }
    sum = 1.f / sum;
    for (int i = 0; i < bufferSize; ++i) {
        kernel[i] = kernel[i] * sum;
    }
}

void LeftAndRightMirrorImageUInt8(unsigned char* in, unsigned char* out, int width, int height)
{
    for (int i = 0; i < height; ++i) {
        int hoffset = i * width;
        for (int j = 0; j < width; ++j) {

            int woffset = (hoffset + j) * 3;
            int woffset_ = (hoffset + width - 1 - j) * 3;
            for (int n = 0; n < 3; ++n) {
                out[woffset_ + n] = in[woffset + n];
            }
        }
    }
}

void LeftAndRightMirrorImageFloat(float* in, float* out, int width, int height)
{
    for (int i = 0; i < height; ++i) {
        int hoffset = i * width;
        for (int j = 0; j < width; ++j) {
            int woffset = (hoffset + j) * 3;
            int woffset_ = (hoffset + width - 1 - j) * 3;
            for (int n = 0; n < 3; ++n) {
                out[woffset_ + n] = in[woffset + n];
            }
        }
    }
}

void UpAndDownMirrorImageFloat(float* in, float* out, int width, int height)
{
    int lineOffset = width * 3;
    int lineSize = lineOffset * sizeof(float);
    float* outTmp = out + lineOffset * height - lineOffset;
    float* inTmp = in;
    for (int i = 0; i < height; ++i) {
        memcpy_s(outTmp, lineSize, inTmp, lineSize);
        outTmp -= lineOffset;
        inTmp += lineOffset;
    }
}

void UpAndDownMirrorImageUInt8(unsigned char* in, unsigned char* out, int width, int height)
{
    int lineOffset = width * 3;
    int lineSize = lineOffset * sizeof(unsigned char);
    unsigned char* outTmp = out + lineOffset * height - lineOffset;
    unsigned char* inTmp = in;
    for (int i = 0; i < height; ++i) {
        memcpy_s(outTmp, lineSize, inTmp, lineSize);
        outTmp -= lineOffset;
        inTmp += lineOffset;
    }
}

#if 0

void Conv(float* in, float* out, int width, float* filter, int ksize) {

    int lineSize = width * 3;
    float* inTemp = in;
    float* outTemp = out;
    out[0] = 0.f; out[1] = 0.f; out[2] = 0.f;
    for (int i = 0; i < ksize; ++i) {
        for (int j = 0; j < ksize; ++j) {
            int xoffset = j * 3;
            out[0] += (*filter) * inTemp[xoffset + 0];
            out[1] += (*filter) * inTemp[xoffset + 1];
            out[2] += (*filter) * inTemp[xoffset + 2];
            filter++;
        }
        inTemp = inTemp + lineSize;
    }
}

void ImageFilterFloat(float* in, float* out, int width, int height, float* filterKernel, int kw, int kh)
{
    size_t size = (size_t)width * (size_t)height * sizeof(float) * 3;

    int startX = kw / 2;
    int endX = width - kw / 2;
    
    int startY = kh / 2;
    int endY = height - kh / 2;

    float* tempOut = out + (startY * width + startX) * 3;

    memset(out, 0, size);
    //memcpy_s(out, size, in, size);
    omp_set_num_threads(32);

#pragma omp parallel for
    for (int i = 0; i <= height - kh; ++i) {
        int yoffset = i * width * 3;
        for (int j = 0; j <= width - kw; ++j) {
            int xoffset = yoffset + j * 3;
            Conv((in + xoffset), (tempOut + xoffset), width, filterKernel, kw);
        }

    }
}
#elif 1

void Conv(float* in, float* out, int width, __m128* filter, int ksize) {

    int lineSize = width * 3;
    float* inTemp = in;
    float* outTemp = out;
    out[0] = 0.f; out[1] = 0.f; out[2] = 0.f;
    __m128 sum = _mm_set_ps1(0.f);
    for (int i = 0; i < ksize; ++i) {
        for (int j = 0; j < ksize; ++j) {
            int xoffset = j * 3;

            __m128 img_value = _mm_set_ps(1.f, inTemp[xoffset + 2], inTemp[xoffset + 1], inTemp[xoffset + 0]);

            sum = _mm_add_ps(_mm_mul_ps((*filter), img_value), sum);

            filter++;
        }
        inTemp = inTemp + lineSize;
    }
    out[0] = sum.m128_f32[0];
    out[1] = sum.m128_f32[1];
    out[2] = sum.m128_f32[2];
}

void ImageFilterFloat(float* in, float* out, int width, int height, float* filterKernel, int kw, int kh)
{
    size_t size = (size_t)width * (size_t)height * sizeof(float) * 3;

    int startX = kw / 2;
    int endX = width - kw / 2;

    int startY = kh / 2;
    int endY = height - kh / 2;

    float* tempOut = out + (startY * width + startX) * 3;

    memset(out, 0, size);

    __m128* filterKernel_m128 = (__m128*)_mm_malloc(kw * kh * sizeof(__m128), sizeof(__m128));
    for (int i = 0; i < kw * kh; ++i) {
        filterKernel_m128[i] = _mm_set_ps1(filterKernel[i]);
    }

    omp_set_num_threads(32);
#pragma omp parallel for
    for (int i = 0; i <= height - kh; ++i) {
        int yoffset = i * width * 3;
        for (int j = 0; j <= width - kw; ++j) {
            int xoffset = yoffset + j * 3;
            Conv((in + xoffset), (tempOut + xoffset), width, filterKernel_m128, kw);
        }

    }

    if (filterKernel_m128) {
        _mm_free(filterKernel_m128);
        filterKernel_m128 = NULL;
    }
}

#endif
void SaltAndPepperFloat(float* in, float* out, int width, int height, float minV, float maxV, float proportion)
{
    int coordNumber = (int)(width * height * proportion);

    if (in != out) {
        memcpy_s(out, width * height * 3 * sizeof(float), in, width * height * 3 * sizeof(float));
    }

    for (int i = 0; i < coordNumber; ++i) {
        ImageCoord coord = gRandom.RandomImageCoord(width, height);
        bool saltOrPepper = gRandom.RandomBoolean();
        float value = saltOrPepper ? minV : maxV;
        int x = coord.x;
        int y = coord.y;
        int offset = (y * width + x) * 3;
        for (int c = 0; c < 3; ++c) {
            out[offset + c] = value;
        }
    }
}

void SaltAndPepperUInt8(unsigned char* in, unsigned char* out, int width, int height, float minV, float maxV, float proportion)
{
    int coordNumber = (int)(width * height * proportion);

    if (in != out) {
        memcpy_s(out, width * height * 3 * sizeof(unsigned char), in, width * height * 3 * sizeof(unsigned char));
    }
    for (int i = 0; i < coordNumber; ++i) {
        ImageCoord coord = gRandom.RandomImageCoord(width, height);
        bool saltOrPepper = gRandom.RandomBoolean();
        float value = saltOrPepper ? minV : maxV;
        int x = coord.x;
        int y = coord.y;
        int offset = (y * width + x) * 3;
        for (int c = 0; c < 3; ++c) {
            out[offset + c] = (unsigned char)value;
        }
    }
}

void ImageMinMax(float* in, int width, int height, int channels, float* minV, float* maxV)
{
    float minValue = 99999.f;
    float maxValue = -minValue;
    int number = width * height * channels;
    for (int i = 0; i < number; ++i) {
        float value = in[i];
        if (value > maxValue) {
            maxValue = value;
        }
        if (value < minValue) {
            minValue = value;
        }
    }
    *minV = (float)minValue;
    *maxV = (float)maxValue;
}

void ImageMinMax(unsigned char* in, int width, int height, int channels, unsigned char* minV, unsigned char* maxV)
{
    int minValue = 256;
    int maxValue = -1;
    int number = width * height * channels;
    for (int i = 0; i < number; ++i) {
        int value = in[i];
        if (value > maxValue) {
            maxValue = value;
        }
        if (value < minValue) {
            minValue = value;
        }
    }
    *minV = (unsigned char)minValue;
    *maxV = (unsigned char)maxValue;
}

void ImageMulAAddBFloatFloat(float* in, float* out, int width, int height, int channels, float A, float B)
{
    int size = width * height * channels;
    for (int i = 0; i < size; ++i) {
        out[i] = in[i] * A + B;
    }
}

void ImageMulAAddBUInt8UInt8(unsigned char* in, unsigned char* out, int width, int height, int channels, float A, float B)
{
#define ALVACLAMP(x, minV, maxV) \
        (x) < (minV) ? (minV) : ((x) > (maxV) ? (maxV) : (x))
    int size = width * height * channels;
    for (int i = 0; i < size; ++i) {
        out[i] = (unsigned char)(ALVACLAMP(in[i] * A + B, 0, 255));
    }
#undef ALVACLAMP
}

void ImageMulAAddBUInt8Float(unsigned char* in, float* out, int width, int height, int channels, float A, float B)
{
    int size = width * height * channels;
    for (int i = 0; i < size; ++i) {
        out[i] = in[i] * A + B;
    }
}

void NormalizeUInt8Float(unsigned char* in, float* out, int width, int height, int channels, int type)
{
    unsigned char minV, maxV;
    ImageMinMax(in, width, height, channels, &minV, &maxV);
    int size = width * height * channels;
    float inv = 1.f / (maxV - minV);
    float offset = 0.f;
    if (type == 1) {
        inv *= 2.f;
        offset = -1.f;
    }
    for (int i = 0; i < size; ++i) {
        out[i] = (in[i] - minV) * inv + offset;
    }
}

void NormalizeFloatFloat(float* in, float* out, int width, int height, int channels, int type)
{
    float minV, maxV;
    ImageMinMax(in, width, height, channels, &minV, &maxV);
    int size = width * height * channels;
    float inv = 1.f / (maxV - minV);
    float offset = 0.f;
    if (type == 1) {
        inv *= 2.f;
        offset = -1.f;
    }
    for (int i = 0; i < size; ++i) {
        out[i] = (in[i] - minV) * inv + offset;
    }
}

void RGBAvgUInt8Float(unsigned char* in, float* out, int width, int height)
{
    int size = width * height;
    for (int i = 0; i < size; ++i) {
        float avg = (in[i * 3 + 0] + in[i * 3 + 1] + in[i * 3 + 2]) / 3.f;
        out[i * 3 + 0] = avg;
        out[i * 3 + 1] = avg;
        out[i * 3 + 2] = avg;
    }
}

void RGBAvgFloatFloat(float* in, float* out, int width, int height)
{
    int size = width * height;
    for (int i = 0; i < size; ++i) {
        float avg = (in[i * 3 + 0] + in[i * 3 + 1] + in[i * 3 + 2]) / 3.f;
        out[i * 3 + 0] = avg;
        out[i * 3 + 1] = avg;
        out[i * 3 + 2] = avg;
    }
}

static PyObject* GeneratorGaussKernel(PyObject* self, PyObject* args) {
    //int ksize, float sigma, float* kernel
    PyObject* pyobj_filter = NULL;
    int ksize;
    float sigma;
    int ret = PyArg_ParseTuple(args, "Oif", &pyobj_filter, &ksize, &sigma);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_filter;

    float* data = (float*)(oarr->data);

    GeneratorGaussKernel(ksize, sigma, data);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* LeftAndRightMirrorImageUInt8(PyObject* self, PyObject* args) {
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height;
    int ret = PyArg_ParseTuple(args, "OOii", &pyobj_img, &pyobj_out_img, &width, &height);
    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;

    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    unsigned char* dataIn = (unsigned char*)(oarr->data);
    unsigned char* dataOut = (unsigned char*)(oarr_out->data);
    
    LeftAndRightMirrorImageUInt8(dataIn, dataOut, width, height);

    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;

    //std::cout << "";
}

static PyObject* LeftAndRightMirrorImageFloat(PyObject* self, PyObject* args) {

    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height;
    int ret = PyArg_ParseTuple(args, "OOii", &pyobj_img, &pyobj_out_img, &width, &height);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;

    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    float* dataIn = (float*)(oarr->data);    
    float* dataOut = (float*)(oarr_out->data);

    LeftAndRightMirrorImageFloat(dataIn, dataOut, width, height);

    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* UpAndDownMirrorImageUInt8(PyObject* self, PyObject* args) {

    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height;
    int ret = PyArg_ParseTuple(args, "OOii", &pyobj_img, &pyobj_out_img, &width, &height);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;

    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    unsigned char* dataIn = (unsigned char*)(oarr->data);

    unsigned char* dataOut = (unsigned char*)(oarr_out->data);

    UpAndDownMirrorImageUInt8(dataIn, dataOut, width, height);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* UpAndDownMirrorImageFloat(PyObject* self, PyObject* args) {

    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height;
    int ret = PyArg_ParseTuple(args, "OOii", &pyobj_img, &pyobj_out_img, &width, &height);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;

    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    float* dataIn = (float*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);

    UpAndDownMirrorImageFloat(dataIn, dataOut, width, height);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* ImageFilterFloat(PyObject* self, PyObject* args) {
    //float* in, float* out, int width, int height, float* filterKernel, int kw, int kh
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    PyObject* pyobj_filterKernel = NULL;
    int width, height;
    int kw, kh;
    int ret = PyArg_ParseTuple(args, "OOiiOii", &pyobj_img, &pyobj_out_img, &width, &height, &pyobj_filterKernel, &kw, &kh);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;
    PyArrayObject* kernel = (PyArrayObject*)pyobj_filterKernel;

    float* dataIn = (float*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);
    float* filter = (float*)(kernel->data);

    ImageFilterFloat(dataIn, dataOut, width, height, filter, kw, kh);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* SaltAndPepperFloat(PyObject* self, PyObject* args) {
    //float* in, float* out, int width, int height, float minV, float maxV, float proportion
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height;
    float minV, maxV, proportion;
    int ret = PyArg_ParseTuple(args, "OOiifff", &pyobj_img, &pyobj_out_img, &width, &height, &minV, &maxV, &proportion);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    float* dataIn = (float*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);

    SaltAndPepperFloat(dataIn, dataOut, width, height, minV, maxV, proportion);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* SaltAndPepperUInt8(PyObject* self, PyObject* args) {
    //float* in, float* out, int width, int height, float minV, float maxV, float proportion
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height;
    float minV, maxV, proportion;
    int ret = PyArg_ParseTuple(args, "OOiifff", &pyobj_img, &pyobj_out_img, &width, &height, &minV, &maxV, &proportion);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    unsigned char* dataIn = (unsigned char*)(oarr->data);
    unsigned char* dataOut = (unsigned char*)(oarr_out->data);

    SaltAndPepperUInt8(dataIn, dataOut, width, height, minV, maxV, proportion);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* ImageMulAAddBFloatFloat(PyObject* self, PyObject* args) {
    //float* in, float* out, int width, int height, int channels, float A, float B
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height, channels = 3;
    float A, B;
    int ret = PyArg_ParseTuple(args, "OOiiff", &pyobj_img, &pyobj_out_img, &width, &height, &A, &B);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    float* dataIn = (float*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);

    ImageMulAAddBFloatFloat(dataIn, dataOut, width, height, channels, A, B);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* ImageMulAAddBUInt8Float(PyObject* self, PyObject* args) {
    //float* in, float* out, int width, int height, int channels, float A, float B
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height, channels = 3;
    float A, B;
    int ret = PyArg_ParseTuple(args, "OOiiff", &pyobj_img, &pyobj_out_img, &width, &height, &A, &B);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    unsigned char* dataIn = (unsigned char*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);

    ImageMulAAddBUInt8Float(dataIn, dataOut, width, height, channels, A, B);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* ImageMulAAddBUInt8UInt8(PyObject* self, PyObject* args) {
    //float* in, float* out, int width, int height, int channels, float A, float B
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height, channels = 3;
    float A, B;
    int ret = PyArg_ParseTuple(args, "OOiiff", &pyobj_img, &pyobj_out_img, &width, &height, &A, &B);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    unsigned char* dataIn = (unsigned char*)(oarr->data);
    unsigned char* dataOut = (unsigned char*)(oarr_out->data);

    ImageMulAAddBUInt8UInt8(dataIn, dataOut, width, height, channels, A, B);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* NormalizeUInt8Float(PyObject* self, PyObject* args) {
    // unsigned char* in, float* out, int width, int height, int channels, int type
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height, channels = 3;
    int type;
    int ret = PyArg_ParseTuple(args, "OOiii", &pyobj_img, &pyobj_out_img, &width, &height, &type);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    unsigned char* dataIn = (unsigned char*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);

    NormalizeUInt8Float(dataIn, dataOut, width, height, channels, type);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* NormalizeFloatFloat(PyObject* self, PyObject* args) {
    // unsigned char* in, float* out, int width, int height, int channels, int type
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height, channels = 3;
    int type;
    int ret = PyArg_ParseTuple(args, "OOiii", &pyobj_img, &pyobj_out_img, &width, &height, &type);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    float* dataIn = (float*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);

    NormalizeFloatFloat(dataIn, dataOut, width, height, channels, type);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* RGBAvgUInt8Float(PyObject* self, PyObject* args) {
    // unsigned char* in, float* out, int width, int height
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height;
    int ret = PyArg_ParseTuple(args, "OOii", &pyobj_img, &pyobj_out_img, &width, &height);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    unsigned char* dataIn = (unsigned char*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);

    RGBAvgUInt8Float(dataIn, dataOut, width, height);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyObject* RGBAvgFloatFloat(PyObject* self, PyObject* args) {
    // unsigned char* in, float* out, int width, int height
    PyObject* pyobj_img = NULL;
    PyObject* pyobj_out_img = NULL;
    int width, height;
    int ret = PyArg_ParseTuple(args, "OOii", &pyobj_img, &pyobj_out_img, &width, &height);

    PyArrayObject* oarr = (PyArrayObject*)pyobj_img;
    PyArrayObject* oarr_out = (PyArrayObject*)pyobj_out_img;

    float* dataIn = (float*)(oarr->data);
    float* dataOut = (float*)(oarr_out->data);

    RGBAvgFloatFloat(dataIn, dataOut, width, height);
    PyObject* result = PyUnicode_FromFormat("result:%s", "ok");
    return result;
}

static PyMethodDef DemoMethods[] = {
    {"LeftAndRightMirrorImageUInt8", (PyCFunction)LeftAndRightMirrorImageUInt8, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"LeftAndRightMirrorImageFloat", (PyCFunction)LeftAndRightMirrorImageFloat, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"UpAndDownMirrorImageUInt8", (PyCFunction)UpAndDownMirrorImageUInt8, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"UpAndDownMirrorImageFloat", (PyCFunction)UpAndDownMirrorImageFloat, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"ImageFilterFloat", (PyCFunction)ImageFilterFloat, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"SaltAndPepperFloat", (PyCFunction)SaltAndPepperFloat, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"SaltAndPepperUInt8", (PyCFunction)SaltAndPepperUInt8, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"ImageMulAAddBFloatFloat", (PyCFunction)ImageMulAAddBFloatFloat, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"ImageMulAAddBUInt8Float", (PyCFunction)ImageMulAAddBUInt8Float, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"ImageMulAAddBUInt8UInt8", (PyCFunction)ImageMulAAddBUInt8UInt8, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"NormalizeUInt8Float", (PyCFunction)NormalizeUInt8Float, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"NormalizeFloatFloat", (PyCFunction)NormalizeFloatFloat, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"RGBAvgUInt8Float", (PyCFunction)RGBAvgUInt8Float, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"RGBAvgFloatFloat", (PyCFunction)RGBAvgFloatFloat, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {"GeneratorGaussKernel", (PyCFunction)GeneratorGaussKernel, METH_VARARGS | METH_KEYWORDS, "I guess here is description." },
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef demoModule = {
    PyModuleDef_HEAD_INIT,
    "mirror",
    NULL,
    -1,
    DemoMethods
};

PyMODINIT_FUNC
PyInit_ImgProcessing(void) {  // ImgProcessing 为生成的dll名称
    return PyModule_Create(&demoModule);
}

2.Python 代码

把C++ 编译出的ImgProcessing.dll 改为 ImgProcessing.pyd 并 拷贝到Python工程下

# -*- coding:utf-8 -*-
import cv2
import random
import numpy as np
import ImgProcessing as aug

class AugmentImagesBase:
    def _gauss(self, x, y, sigma=1.):
        Z = 2 * np.pi * sigma ** 2
        kernel_value = 1 / Z * np.exp(-(x ** 2 + y ** 2) / 2 / sigma ** 2)
        return kernel_value

    def _gauss_kernel(self, kwidth, kheight, kchannel=1):
        kernels = np.zeros((kheight, kwidth, kchannel, 1), np.float32)
        mid = np.floor(kwidth / 2)
        for kernel_idx in range(kchannel):
            for i in range(kheight):
                for j in range(kwidth):
                    kernels[i, j, kernel_idx, 0] = self._gauss(i - mid, j - mid)
        if kchannel == 1:
            kernels = np.reshape(kernels, (kheight, kwidth))
        return kernels

    def left_right_flip(self, img_in, img_out, width=336, height=192):
        aug.AlvaLeftAndRightMirrorImageUInt8(img_in, img_out, width, height)
        return img_out

    def up_down_flip(self, img_in, img_out, width=336, height=192):
        aug.AlvaUpAndDownMirrorImageUInt8(img_in, img_out, width, height)
        return img_out

    def filtering(self, img_in, img_out, width=336, height=192, kernel=None, kwidth=3, kheight=3):
        aug.AlvaImageFilterFloat(img_in, img_out, width, height, kernel, kwidth, kheight)
        return img_out

    def pepper_salt(self, img_in, img_out, width=336, height=192, min_v=0, max_v=255, proportion=0.1):
        rand_proportion = random.uniform(0., proportion)
        aug.AlvaSaltAndPepperUInt8(img_in, img_out, width, height, min_v, max_v, rand_proportion)
        return img_out

    def contrast(self, img_in, img_out, width=336, height=192, a=0.6, b=0.4):
        aug.AlvaImageMulAAddBUInt8UInt8(img_in, img_out, width, height, a, b)
        return img_out

    def average_rgb(self, img_in, img_out, width=336, height=192):
        img_in = img_in.astype(np.float32)
        img_out = img_out.astype(np.float32)
        aug.AlvaRGBAvgFloatFloat(img_in, img_out, width, height)
        img_out = img_out.astype(np.uint8)
        return img_out

    def normalize(self, img_in, img_out, width=336, height=192, type=1):
        aug.AlvaNormalizeUInt8Float(img_in, img_out, width, height, type)
        return img_out

    def normal(self, img_in, img_out):
        return img_in

    def rota_180(self, img_in, img_out):
        return cv2.rotate(img_in, cv2.ROTATE_180)

    def rand_aug(self, img_in):
        img_in = np.asarray(img_in, dtype=np.uint8)
        img_out = np.ones_like(img_in).astype(np.uint8)
        aug_func = {
            "left_right_flip": self.left_right_flip,
            'up_down_flip': self.up_down_flip,
            'pepper_salt': self.pepper_salt,
            'contrast': self.contrast,
            'average_rgb': self.average_rgb,
            "normal": self.normal,
            "rota_180": self.rota_180,
        }
        img_out_curr = np.ones_like(img_in[0]).astype(np.uint8)
        aug_names = []
        for i in range(img_in.shape[0]):
            aug_name = random.sample(list(aug_func.keys()), 1)[0]
            img_out_curr = aug_func[aug_name](np.squeeze(img_in[i]), img_out_curr)
            img_out[i] = img_out_curr
            aug_names.append(aug_name)
        return img_out, aug_names

def image_aug(img_path):
    import cv2
    import time
    aug_tools = AugmentImagesBase()
    kernel = aug_tools._gauss_kernel(5, 5)
    img_in = cv2.imread(img_path).astype(np.float32)
    img_out = np.ones_like(img_in).astype(np.float32)
    time1 = time.time()
    for i in range(1000):
        # img_out, aug_names = aug_tools.average_rgb(img_in, img_out)
        img_out = aug_tools.filtering(img_in, img_out, kernel=kernel, kwidth=5, kheight=5)

    time2 = time.time()
    print("end time:", time2 - time1)
    # cv2.imshow(aug_names[0], img_out[0])
    cv2.imshow("aug img", img_out.astype(np.uint8))
    cv2.imshow('src img', img_in.astype(np.uint8))
    cv2.waitKey(0)

if __name__ == "__main__":
    img_path = r"G:\20210917\img\1.jpg"
    image_aug(img_path)

PyArg_ParseTuple 的使用见:PyArg_ParseTuple

到此这篇关于Python 调用 C++ 传递numpy 数据详情的文章就介绍到这了,更多相关Python调用 C++内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python 与c++相互调用实现

    目录 一.c++调用Python 1.Python脚本 2.C++调用python脚本 二.接口方法 1.规范化语法 三.Pthon调用c++ 1.基于extern 2.基于swig 一.c++调用Python 将Python安装目录下的include和libs文件夹引入到项目中,将libs目录下的python37.lib复制一份为python37_d.lib 1.Python脚本 def Hello():     print("Hello")       def Add(a,b):

  • 如何利用Python实现简单C++程序范围分析

    目录 1.实验说明 2.项目使用 3.算法原理 3.1构建CFG 3.2构建ConstraintGraph 3.3构建E-SSAConstraintGraph 3.4三步法 3.4.1Widen 3.4.2FutureResolution& Narrow 4.实验结果 5.总结 1. 实验说明 问题要求:针对静态单赋值(SSA)形式的函数中间代码输入,输出函数返回值的范围 实现思路: 基本根据 2013年在CGO会议上提出的“三步法”范围分析法加以实现[3],求得各个变量的范围 算法优势:空间复

  • C++通过内嵌解释器调用Python及间接调用Python三方库

    目录 1.移植Python解释器 2.VS配置(VS2017为例,此教程与VS版本无关) 3.C++调用程序样例 4.被调Python程序样例 本文章目的是脱离安装Python环境的前提下,由C++程序调用Python程序及Python相关三方库 1.移植Python解释器 Python环境的目录结构 路径详解 需要用的如下图 1.红色部分是生成路径下解释器运行时依赖 将红色部分拷贝到C++编译主ExE路径下即可 2.蓝色部分是VS配置编译时依赖 路径或文件名 作用 DLLs Python内部运

  • 如何在C++中调用python代码你知道吗

    目录 一.环境设置 二.VS项目中设置 (1)首先在acaconda中找到include文件夹和libs文件夹,如图所示 (2)点击链接器,然后输入,附加依赖项,添加python36_d.lib的路径 (3)python代码 三.可能会出现的问题 总结 一.环境设置 windows VS2015 python的话用的是acaconda自带的python环境,不同版本的acaconda自带的python不同,我的是python3.6(这一步很重要,如果使用acaconda创建的虚拟环境的pytho

  • C++调用python(执行py文件)的全过程

    1.首先要配好vs开发工程 注意版本:我这使用32位的python那么我vs工程这边也选择32位的编译环境去配置 注意点:需要将python安装目录的一些文件拷过来作为vs工程使用. 2.C++调用Python结果 py代码 这里引用了cdll库也需要放置到运行目录,py文件也是需要放置到运行目录(也就是exe生成所在目录) import os import time from ctypes import * def testDLL(): pDll = CDLL("./pythonTestCDl

  • python直接调用和使用swig法方调用c++库

    c++运算速度快于python,python简单易写.很多时候对于已有的c++代码也不想用python重写,此时就自然而然地想到用python调用c或者c++,两全其美.然而根据这些博客的说法,python只能实现c的调用,如果需要调用c++,还需要对c++代码进行额外的处理. 首先是python调用c代码: //gcc -g -o libpycall_c.so -shared -fPIC pycall_c.c #include <stdio.h>  #include <stdlib.h

  • Python与C++中梯度方向直方图的实现

    目录 什么是特征描述子 如何计算梯度方向直方图 Step1:预处理 Step2:计算梯度图 Step3:在8×8的cell中计算梯度直方图 Step4:16×16Block标准化 Step5:计算HOG特征向量 梯度直方图可视化 原文链接:Histogram of Oriented Gradients (文中的图片均来自翻译原文) 什么是特征描述子 特征描述子一张图片或者一个图片块的一种表示,通过提取有用信息并扔掉多余的信息来简化图像. 通常,特征描述子将一张大小为width×height×3

  • c++和python实现顺序查找实例

    目录 (1)python实现顺序查找 (2)C++实现顺序查找 如何在一堆数据中找到某个数值的位置? 数值型数据作为信息的基本载体,广泛用于各种信息的记录,这些数据不仅需要被存储,更需要被使用.因此,从数据库中正确的找到目标数据,是至关重要的操作. 我们先不考虑计算机是如何完成数值查找的,你会如何从下面这张表(黑色是数值,蓝色是位置索引)中找到724这个数值? 显然,上面有序表所有的数值都按照次序进行排列,人眼可以根据数值大小关系确定区间从而很快的找到724在133位置上.但是,当我们面临的是几

  • c++与python实现二分查找的原理及实现

    目录 1.时间复杂度与优缺点 2.python实现 3.C++实现 在计算机中,数据的查找方式与其存储方式关系密切.试想一下,如果图书馆中书籍杂乱无章的存放,那么要想找到心仪的书籍将会非常困难.为此,人们常常将物品按照某种规则或次序进行放置,目的是便于日后的查找. 作为查找算法家族中的一员,二分查找正是利用数据按次序存储这一优点,极大的提升了查找目标值所在位置的速度. 二分查找的核心思想是:首先将数组中间值和目标值进行比较,如果相等则返回:如果不相等,则选择中间值左边的一半或者右边的一半进行比较

  • C++和python实现单链表及其原理

    目录 一.链表的基本概念 二.单链表 1.python实现 (1)节点设计 (2)链表类:Single_Linked_List (3)判断链表是否为空:is_empty()函数 (4)头插法:add()函数 (5)尾插法:append()函数 (6)在任意位置插入:insert()函数 (7)计算链表长度:get_length()函数 (8)遍历所有节点:traversal()函数 (9)搜索:search()函数 (10)删除:delete()函数 2.C++实现 (1)节点设计 (2)链表类

随机推荐