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去處理了。

 

 

 

 

 

 

 

 

 

 

 

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