当前位置: 首页 > 知识库问答 >
问题:

在python的c扩展中使用opencv的问题?

汪泓
2023-03-14

我试图写一个简单的python c-extension,其中包括一些opencv代码。这是我的c代码:

#include "Python.h"
#include "numpy/arrayobject.h"

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>


 /* .... C matrix utility functions ..................*/
double **pymatrix_to_Carrayptrs(PyArrayObject *arrayin);
double **ptrvector(long n);
void free_Carrayptrs(double **v);
int  not_doublematrix(PyArrayObject *mat);

static PyObject *simple_cv_ops(PyObject *self, PyObject *args)
{
    PyArrayObject *matin, *matout;
    double **cin, **cout;
    int n,m, dims[2];

    /* Parse tuples separately since args will differ between C fcns */
    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &matin))  return NULL;
    if (NULL == matin)  return NULL;

    /* Check that object input is 'double' type and a matrix
       Not needed if python wrapper function checks before call to this routine */
    if (not_doublematrix(matin)) return NULL;

    /* Get the dimensions of the input */
    n=dims[0]=matin->dimensions[0];
    m=dims[1]=matin->dimensions[1];

    /* Make a new double matrix of same dims */
    matout=(PyArrayObject *) PyArray_FromDims(2,dims,NPY_DOUBLE);

    /* Change contiguous arrays into C ** arrays (Memory is Allocated!) */
    cin=pymatrix_to_Carrayptrs(matin);
    cout=pymatrix_to_Carrayptrs(matout);

    // _______ Program LOGIC HERE ________

    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(10, 10), cv::Point(-1, -1));
    cv::Mat imgIn(n, m, CV_64F, cin);
    cv::Mat imgOut(n, m, CV_64F);

    cv::morphologyEx(imgIn, imgOut, cv::MORPH_CLOSE, kernel);
    cv::GaussianBlur(imgOut, imgOut, cv::Size(5, 5), 0, 0);
    cv::medianBlur(imgOut, imgOut, 5);
    cv::threshold(imgOut, imgOut, 127, 255, 0);

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cout[i][j] = imgOut.at<double>(i,j);

        }
    }   

// ____________________________________

    /* Free memory, close file and return */
    free_Carrayptrs(cin);
    free_Carrayptrs(cout);

    return PyArray_Return(matout);
}


/* ==== Set up the methods table ====================== */
static PyMethodDef simple_cv_methods[] = {
    {"simple_cv_ops", simple_cv_ops, METH_VARARGS, "Just a simple cv operation"},
    {NULL, NULL, 0, NULL}     /* Sentinel - marks the end of this structure */
};

static struct PyModuleDef simple_cv_modules = {
    PyModuleDef_HEAD_INIT,
    "simple_cv",
    "Python interface for the simple cv ops C library function",
    -1,
    simple_cv_methods
};

PyMODINIT_FUNC PyInit_simple_cv(void) {
    PyObject *pyob;

    pyob = PyModule_Create(&simple_cv_modules);
    import_array();

    return pyob;
}


/* ==== Create Carray from PyArray ======================
Assumes PyArray is contiguous in memory.
Memory is allocated!                                    */
double **pymatrix_to_Carrayptrs(PyArrayObject *arrayin)  {
    double **c, *a;
    int i,n,m;

    n=arrayin->dimensions[0];
    m=arrayin->dimensions[1];
    c=ptrvector(n);
    a=(double *) arrayin->data;  /* pointer to arrayin data as double */
    for ( i=0; i<n; i++)  {
        c[i]=a+i*m;  }
    return c;
}

/* ==== Allocate a double *vector (vec of pointers) ======================
Memory is Allocated!  See void free_Carray(double ** )                  */
double **ptrvector(long n)  {
    double **v;
    v=(double **)malloc((size_t) (n*sizeof(double)));
    if (!v)   {
        printf("In **ptrvector. Allocation of memory for double array failed.");
        exit(0);  }
    return v;
}

/* ==== Free a double *vector (vec of pointers) ========================== */
void free_Carrayptrs(double **v)  {
    free((char*) v);
}

/* ==== Check that PyArrayObject is a double (Float) type and a matrix ==============
return 1 if an error and raise exception */
int  not_doublematrix(PyArrayObject *mat)  {
    if (mat->descr->type_num != NPY_DOUBLE || mat->nd != 2)  {
        PyErr_SetString(PyExc_ValueError,
            "In not_doublematrix: array must be of type Float and 2 dimensional (n x m).");
        return 1;  }
    return 0;
}

为了编写c-extension,我使用了这里的一些代码,除了在我的代码中使用opencv之外,这些代码运行得非常好。

在这里,我还发布了我的 setup.py 代码:

import numpy
from distutils.core import setup, Extension

def main():
    setup(name="simple_cv",
          version="1.0.0",
          description="Python interface for the simple cv C extension library function",
          author="My Name",
          author_email="my_email@email.com",
          ext_modules=[Extension("simple_cv", ["simple_cv.cpp"],
                  include_dirs=[numpy.get_include(), 'C:/opencv/build/include']),
                        ])

if __name__ == "__main__":
    main()

当我运行我的python设置时,我得到以下错误:

simple_cv.obj : 错误 LNK2001: 未解析的外部符号 “双__cdecl cv::阈值(类 cv::_InputArray 常量

现在我知道这些是链接器错误。我在Visual Studio中编码时遇到了这个问题,我通过在Visual Studio项目设置的链接器选项卡中添加指向附加库目录的lib路径解决了这个问题。但是在这里我不知道该怎么办。

顺便说一句,我使用的是windows 10、Visual Studio 2017和python 3.6。

有人能帮助我吗?

共有1个答案

臧正平
2023-03-14

我找到了答案。

看起来Pythons扩展类distutils.core模块有两个额外的库输入参数,它们是library_dirs和库。

所以我只需要修改我的setup.py代码,如下所示:

import numpy
from distutils.core import setup, Extension

def main():
    setup(name="simple_cv",
          version="1.0.0",
          description="Python interface for the simple cv C extension library function",
          author="My Name",
          author_email="my_email@email.com",
          ext_modules=[Extension("simple_cv", ["simple_cv.cpp"],
                  include_dirs=[numpy.get_include(), 'C:/opencv/build/include']),
                  library_dirs = ['C:\\opencv\\build\\x64\\vc14\\lib'],
                  libraries = ['opencv_world330']])

if __name__ == "__main__":
    main()
 类似资料:
  • 本文向大家介绍使用C++扩展Python的功能详解,包括了使用C++扩展Python的功能详解的使用技巧和注意事项,需要的朋友参考一下 本文主要研究的是使用C++扩展Python的功能的相关问题,具体如下。 环境 VS2005Python2.5.4Windows7(32位) 简介 长话短说,这里说的扩展Python功能与直接用其它语言写一个动态链接库,然后让Python来调用有点不一样(虽然本质是

  • 问题内容: 我目前正在使用Selenium来运行Chrome实例来测试网页。每次我的脚本运行时,都会启动一个干净的Chrome实例(清理扩展程序,书签,浏览历史记录等)。我想知道是否可以使用Chrome扩展程序运行脚本。我曾尝试搜索Python示例,但是当我在Google上搜索时什么都没想到。 问题答案: 您应该使用Chrome WebDriver 选项设置要加载的扩展程序列表。这是一个例子: 希

  • 本文向大家介绍C#中的扩展方法,包括了C#中的扩展方法的使用技巧和注意事项,需要的朋友参考一下 扩展方法是静态方法,就像它们是扩展类型的实例方法一样被调用。使用扩展方法,您可以将方法添加到现有类型中,而无需创建新的派生类型,重新编译或修改原始类型。 以下是我们创建的扩展方法。 让我们看一个使用扩展方法的例子。 示例 输出结果

  • 本文向大家介绍Python扩展C/C++库的方法(C转换为Python),包括了Python扩展C/C++库的方法(C转换为Python)的使用技巧和注意事项,需要的朋友参考一下 参考网址:https://www.shanlily.cn/archives/330 一、简介 Python是个非常流行的解释型脚本语言。而C是一个非常流行的编译语言。由于其编译的性质,导致C一般比Python要快,但是它

  • 问题内容: 我正在(自制)基于C的python扩展中进行一些计算量大的模拟。有时我会出错,并想终止模拟。但是,Ctrl- C似乎没有任何作用(除了打印到屏幕上),因此我必须使用或系统监视器终止该进程。 据我所知,python只是等待C扩展完成,并且在这段时间内并没有真正与其通信。 有没有办法使这项工作? 更新 :主要答案(针对我的特定问题)是:1.重写代码以定期将控制权传递回调用方,或2.使用 问

  • 本文向大家介绍PyTorch中的C++扩展实现,包括了PyTorch中的C++扩展实现的使用技巧和注意事项,需要的朋友参考一下 今天要聊聊用 PyTorch 进行 C++ 扩展。 在正式开始前,我们需要了解 PyTorch 如何自定义module。这其中,最常见的就是在 python 中继承torch.nn.Module,用 PyTorch 中已有的 operator 来组装成自己的模块。这种方式