linux系统下Opencv4.1.1编译安装,以及增加子函数和python中调用

目录

Table of Contents

目录

一 源码编译和安装

添加opencv路径

二 增加并列子函数的方法

三 增加库函数形参的方法

四 cv增加子函数一些数据变量的问题

4.1 数据类型



一 源码编译和安装

选择python感觉就是被它强大的跨平台能力以及多语言集成能力所吸引。最近需要查看opencv源码,索性在linux上编译一次源码,随后也好修改定制。

1、下载最新的源码:

https://opencv.org/releases/ 

2、解压到当前文件夹下,一般是在Downloads下面,直接双击Extract就行了。

3、cd Downloads/opencv-4.1.1      (这部分是参考其他教程的https://www.cnblogs.com/xupeidong/p/9376395.html)

mkdir build

cd build/

sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..

然后sudo make

最后sudo make install

添加opencv路径

想要使用,还需要添加包含路径:

sudo gedit /etc/ld.so.conf.d/opencv.conf,写入: /usr/local/lib,该路径是opencv安装路径,也就是CMAKE_INSTALL_PREFIX的安装路径。然后保存,执行sudo ldconfig -v就可以了!

系统大部分不自带cmake,安装cmake参考这篇博客:https://blog.csdn.net/mathlxj/article/details/99645647

针对安装后使用时提醒的问题:error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Cocoa support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvShowImage

先安装libgtk2.0-dev 和 pkg-config:

sudo apt-get install libgtk2.0-dev

sudo apt-get install pkg-config

一般pkg-config是已经装好的,安装前使用 pkg-config --version看一下版本。

根据提示,以及其他资料,将build中的文件全部删除,然后重新编译,先设置好cmake:

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=OFF -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D WITH_QT=OFF -D WITH_GTK=ON -D WITH_OPENGL=OFF ..

然后继续sudo make   sudo make install

系统默认是将opencv安装在linux自带的python2.7版本内,/usr/local/lib/python2.7/dist-packages/cv2/,其实正好符合需求,因为希望使用的caffe2也是基于python2.7的,就按默认的来。

之前学习python用的是Python3.5,那么就换一下版本吧,其实区别不大,出错的话安装提示改就行了。我使用的是pycharm环境,换编译器是在 File->Settings->Project interpreter,在Project interpreter:后面点击:设置的六角星

然后点Add,在Existing environment下的interpreter中找到:/usr/bin/python2.7即可。

但是在package中看不到opencv的包,代码能正常运行,就是不能给出提示,init.py文件中没有imread函数,并且按住ctrl+左键也不会进入提示。

翻了整整一下午的博客,尝试了各种ln做链接的,修改__init__的,都没有解决。现在将问题归纳总结,希望高手路过时指点一二!  

ubuntu系统下,编译OPENCV4.1.1源码并导入到pycharm中,可以正常运行cv程序,但是ctrl+左键无法跳转,提示__init__.py中无cv.imread()函数,这到底是为什么呢?

二 增加并列子函数的方法

尝试了在opencv源码中增加新的函数,结果失败了,不知道为什么总是出现undefined symbol,暂时不用这种方法增加函数。

最近在做圆弧检测,发现opencv中自带的圆检测函数不太适合我的需求,那就增加一种方法,具体修改如下:

1、在hough.cpp中增加一个自己的函数:

template <typename CircleType>
static void myArcDetection(InputArray _image, OutputArray _circles,
                                 float dp, float minDist,
                                 int minRadius, int maxRadius, int cannyThreshold,
                                 int accThreshold, int maxCircles, int kernelSize, bool centersOnly)
{
    CV_Assert(kernelSize == -1 || kernelSize == 3 || kernelSize == 5 || kernelSize == 7);

    dp = max(dp, 1.f);
    float idp = 1.f/dp;
    std::cout<<"nihaomyArcD"<<std::endl;
}

并在 static void HoughCircles   函数中调用它:

switch( method )
{
case CV_HOUGH_GRADIENT:
    if (type == CV_32FC3)
        HoughCirclesGradient<Vec3f>(_image, _circles, (float)dp, (float)minDist,
                                    minRadius, maxRadius, cannyThresh,
                                    accThresh, maxCircles, kernelSize, centersOnly);
    else if (type == CV_32FC4)
        HoughCirclesGradient<Vec4f>(_image, _circles, (float)dp, (float)minDist,
                                    minRadius, maxRadius, cannyThresh,
                                    accThresh, maxCircles, kernelSize, centersOnly);
    else
        CV_Error(Error::StsError, "Internal error");
    break;
 case CV_MY_ARC_DETECTION:
    myArcDetection<Vec3f>(_image, _circles, (float)dp, (float)minDist,
                                    minRadius, maxRadius, cannyThresh,
                                    accThresh, maxCircles, kernelSize, centersOnly);
    break;

为了让编译器能识别这个入口,还需要在types_c.h中增加宏定义:

/** Variants of a Hough transform */
enum
{
    CV_HOUGH_STANDARD =0,
    CV_HOUGH_PROBABILISTIC =1,
    CV_HOUGH_MULTI_SCALE =2,
    CV_HOUGH_GRADIENT =3,
    CV_MY_ARC_DETECTION =4
};

以及在imgproc.hpp中增加Hough Modes,以便于在python中调用的时候能识别我们的模式:

enum HoughModes {

    /** classical or standard Hough transform. Every line is represented by two floating-point
    numbers \f$(\rho, \theta)\f$ , where \f$\rho\f$ is a distance between (0,0) point and the line,
    and \f$\theta\f$ is the angle between x-axis and the normal to the line. Thus, the matrix must
    be (the created sequence will be) of CV_32FC2 type */
    HOUGH_STANDARD      = 0,
    /** probabilistic Hough transform (more efficient in case if the picture contains a few long
    linear segments). It returns line segments rather than the whole line. Each segment is
    represented by starting and ending points, and the matrix must be (the created sequence will
    be) of the CV_32SC4 type. */
    HOUGH_PROBABILISTIC = 1,
    /** multi-scale variant of the classical Hough transform. The lines are encoded the same way as
    HOUGH_STANDARD. */
    HOUGH_MULTI_SCALE   = 2,
    HOUGH_GRADIENT      = 3, //!< basically *21HT*, described in @cite Yuen90
    MY_ARC_DETECTION    = 4 //!< basically *21HT*, described in @cite Yuen90
};

然后再重新编译和安装:

cd xxx/opencv-4.1.1/build

sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..  (如果以及配置过就不用这一步了)

sudo make -j4

sudo make install

然后就可以在python中调用自己的函数了,只能这么曲线救国~

circle_buf = cv.HoughCircles(ROI_U_edge, cv.MY_ARC_DETECTION, 1.5, 10, 200, 100, 10, 30)

输出:nihaomyArcD

三 增加库函数形参的方法

当使用库函数作为入口,增加其他的方法时,参数不够用,无奈只能尝试增加形参。

针对   HoughCircles 检测的方法,准备增加圆弧匹配检测算法,需要将模板传递进来。需要修改:

1. 该函数作用暂时没搞明白,但是顺道一起改了

CV_IMPL CvSeq*
cvHoughCircles( CvArr* src_image, CvArr* src_arcMap, void* circle_storage,
                int method, double dp, double min_dist,
                double param1, double param2,
                int min_radius, int max_radius )

2. 系统调用的时候,首先调用这个

void HoughCircles( InputArray _image, InputArray _arcMap, OutputArray _circles,
                   int method, double dp, double minDist,
                   double param1, double param2,
                   int minRadius, int maxRadius )

3. 然后系统再调用这个函数:

static void HoughCircles( InputArray _image, InputArray _arcMap, OutputArray _circles,
                          int method, double dp, double minDist,
                          double param1, double param2,
                          int minRadius, int maxRadius,
                          int maxCircles, double param3 )

4.最后调用这个:

template <typename CircleType>
static void HoughCirclesGradient(InputArray _image, InputArray _arcMap, OutputArray _circles,
                                 float dp, float minDist,
                                 int minRadius, int maxRadius, int cannyThreshold,
                                 int accThreshold, int maxCircles, int kernelSize, bool centersOnly)

5.声明的头文件

这里面的:

CV_EXPORTS_W void HoughCircles( InputArray image, InputArray arcMap, OutputArray circles,
                               int method, double dp, double minDist,
                               double param1 = 100, double param2 = 100,
                               int minRadius = 0, int maxRadius = 0 );

以及这里面的:

CVAPI(CvSeq*) cvHoughCircles( CvArr* image, CvArr* arcMap, void* circle_storage,
                              int method, double dp, double min_dist,
                              double param1 CV_DEFAULT(100),
                              double param2 CV_DEFAULT(100),
                              int min_radius CV_DEFAULT(0),
                              int max_radius CV_DEFAULT(0));

6 测试程序修改

test里面的函数不修改的话,编译通不过,也就是说,里面调用的函数的参数不够

很多模块的test程序中均使用了HoughCircles函数,可以在:

寻找所有的HoughCircles,增加参数即可。

四 调用测试结果

在python中调用,需要增加一个参数,其他保持原样,即可成功运行。

结果:

四 cv增加子函数一些数据变量的问题

今天终于在opencv源码的基础上,实现了在python中验证好的算法,效果非常不错。总体来讲,实现了一个圆弧检测的快速算法,我将该函数与opencv的HoughCirclesGradient函数并列声明,作为HoughCircle的另外一种方法来使用。由于C++基础薄弱,遇到很多小问题,现总结如下:

4.1 数据类型

原始的HoughCirclesGradient函数的输入只有一个image,我在函数里又加了一个输入量,类型与image一致,都是InputArray。牵一发动全身,具体修改请参考二、三节。

函数的返回值原来是template <typename CircleType>,我将其删除,返回值默认是Mat或者Vector或者其他,这个不重要。

HoughCirclesGradient使用 std::vector<CircleType> circles; 来保存最后圆的参数,我要保存的是5个量(h,w,maxRatio,iRadS,iShear),也就是一个float类型的数组,在这里卡了好久才解决,具体方法如下:

std::vector<Vec6f> arcProposal;     // 存放候选圆弧向量的列表
Vec6f tmpArcParaBuf;                // 圆弧向量的缓存

这样,圆弧的5个参数可以使用类似于C的方法存放在圆弧向量的缓存:

tmpArcParaBuf[0] = h;
tmpArcParaBuf[1] = w;
tmpArcParaBuf[2] = maxRatio;
tmpArcParaBuf[3] = iRadS;
tmpArcParaBuf[4] = iShear;
tmpArcParaBuf[5] = 1;

得到的圆弧向量,使用 arcProposal.push_back(tmpArcParaBuf); 将其存放在arcProposal中。

最后,还是套用原来函数的数据返回方式:

Mat(arcProposal.size(),6,cv::traits::Type<float>::value, &arcProposal[0]).copyTo(_circles);

这里遇到了不少问题,其中arcProposal.size()是指这个vector中有多少个圆弧,6是指每个圆弧的参数长度,cv::traits::Type<float>::value不清楚什么意思,好像是声明数据类型的,改成和Vec6f对应的float即可,&arcProposal[0]是圆弧列表的首地址,最后通过.copyTo(_circles)将候选圆弧Mat矩阵传递给_circles,用于返回数据。其他的就可以用python去处理了。

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章