---作者疆,未經允許,嚴禁轉載,違權必究---
---歡迎指正,需要源碼和文件可站內私信聯系---
-----------點擊此處鏈接至博客園原文-----------
功能說明:將C++版的海康威視官方SDK封裝、編譯成動態共享對象(linux中稱為DSO,Dynamic Shared Objects,windows中稱動態鏈接庫),供Python調用實現相關功能
運行環境:ubuntu14.04或ubuntu16.04、opencv2.4.13.5或opencv2.4.13.6、swig3.0.8、codeblocks16.01、Python2.7.6(僅在上述運行環境中驗證過該博客有效性)
一、相關介紹
參考鏈接:swig擴展opencv Python調用C++(極重要參考)
本節主要介紹在linux系統下將C++源文件封裝、編譯為.so動態共享對象的大致流程和細節。swig是simplified wrapper and interface generator的縮寫,是一個非常優秀的開源工具,支持將 C/C++代碼與任何主流腳本語言相集成。其中,必須編寫一個額外的接口文件(.i文件)來作為swig(終端工具)的入口。這里引用上文中(未調用opencv的簡單)例子對該流程進行敘述。(若調用了opencv函數,則需利用opencv-swig接口文件,將在“四”中以例子形式介紹)
//example.hpp #ifndef example_hpp #define example_hpp #include <iostream> #include <vector> class Test{ public: Test(){ for(int i=0;i<10;i++) v.push_back(i); } void see(); private: std::vector<int> v; }; #endif
//example.cpp #include "example.hpp" #include <stdio.h> using namespace std; void Test::see(){ for(int i=0;i<(this->v).size();i++) printf("%d ",v[i]); }
example.i文件如下:
%module example %include "std_vector.i" %{ #include "example.hpp" %} %include "example.hpp"
其中,example.cpp為C++源文件,定義了相關函數方法;example.hpp是對應的頭文件,里面還定義了要封裝的函數方法;為了實現封裝,編寫了對應接口文件example.i。
example.i中第一行 %module后面的名字(example)是被封裝的模塊名稱,Python通過這個名稱來加載程序;第二行是該.i文件依賴的頭文件,vector本來是STL里面的,但是swig已經有對應的"std_vector.i"寫好了,所以可以直接include "std_vector.i";第三行至第五行大括號中包含了該.i文件需要的一些函數聲明和頭文件;最后一行是聲明了要封裝的函數和變量,由於函數聲明寫在了頭文件里,如果需要全部封裝可以直接%include 頭文件名(example.hpp)。
現在,就可以利用swig封裝代碼,生成預編譯C++文件.cxx和.py文件 執行命令 swig -python -c++ example.i (#將對應生成example.cxx :編譯c++時用;example.py:python import包時使用)
接着,可以使用python內置的distutils庫編譯上述.cxx文件,該python腳本(setup.py)如下:
from distutils.core import setup,Extension setup(name = "example", version = "1.0", ext_modules = [Extension("_example", ["example_wrap.cxx", "example.cpp"], extra_compile_args = ['-std=c++11'])], py_modules=['example'])
執行命令 sudo python setup.py install (#注意模塊名稱_example前面一定要加下划線、這會將生成的_example.so 和 example.py 送到python對應的package文件夾),接着可以執行:
In [1]: from example import * In [2]: x = Test() In [3]: x.see() 0 1 2 3 4 5 6 7 8 9
大致上,封裝C++函數、編譯動態共享對象供Python調用就是這個過程,若涉及調用opencv等函數庫,情況和處理更為復雜一些,將在后文“四”中以例子形式敘述。上述文件(百度雲盤備份不對外提供)。
二、環境搭建之opencv安裝方法
參考鏈接:linux下Python調用海康SDK實時顯示網絡攝像頭、linux設置opencv環境變量、linux下QT環境搭建及opencv交叉編譯(可不參考)
opencv通常采用源碼編譯安裝,常見的可利用cmake-qt-gui交叉編譯或cmake編譯安裝。本人ubuntu14.04工作站很早就利用cmake-qt-gui預裝了opencv2.4.13.6,在這里敘述利用cmake編譯安裝opencv2.4.13的方法(在ubuntu16.04上驗證過)。如果在安裝opencv之前機器預裝了高版本的cuda9.0(cuda9.0不再支持2.0架構),照此方法會出錯,將在后文“五”中敘述報錯內容及解決方法,沒有安裝過cuda或安裝cuda8.0等低版本可以參考本節opencv安裝方法。
首先,安裝依賴包,執行以下命令:
#更新軟件源
sudo apt-get update
#-y表示yes,build-essential、cmake等為一系列依賴包 sudo apt-get install -y build-essential cmake git libopencv-dev libgtk2.0-dev pkg-config libavcodec-dev libpng12-dev libavformat-dev libswscale-dev yasm libxine2 libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev libqt4-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils sudo apt-get install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff5-dev libjasper-dev libdc1394-22-dev
然后,網上下載opencv2.4.13壓縮包文件(以opencv-2.4.13.6.zip為例),將壓縮包拷貝到主文件夾(/home/rcnn ,rcnn為本人機器用戶名),執行以下命令:
unzip opencv-2.4.13.6.zip cd opencv-2.4.13.6
#mkdir命令新建opencv-debug目錄,用於存放編譯后的文件
mkdir opencv-debug cd opencv-debug #精簡版編譯安裝 cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local .. #或選擇cuda版安裝 cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_CUDA=ON -D ENABLE_FAST_MATH=ON -D CUDA_FAST_MATH=ON -D WITH_CUBLAS=1 -D WITH_NVCUVID=on -D CUDA_GENERATION=Auto .. make sudo make install
以上推薦使用精簡版編譯安裝,安裝路徑設置為/usr/local(實際上編譯安裝后文件存在於opencv-debug下,但會復制頭文件、庫文件等到上述指定的路徑中,如/usr/local/include/opencv2、 /usr/local/include/opencv、 /usr/include/opencv、 /usr/include/opencv2、 /usr/local/share/opencv、 /usr/local/share/OpenCV、 /usr/share/opencv、 /usr/share/OpenCV、 /usr/local/bin/opencv*、 /usr/local/lib/libopencv*
)。然后,配置環境變量:
#新建opencv配置文件,gedit與vim均為文本編輯工具 sudo gedit /etc/ld.so.conf.d/opencv.conf #在該文件中輸入下句(依賴庫路徑)並保存關閉 /usr/local/lib #使配置生效 sudo ldconfig #打開bash並配置 sudo gedit /etc/bash.bashrc #在該文件中輸入下句(opencv.pc路徑,該文件維護了opencv的相關信息,包含libs、cflags等)並保存 PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig export PKG_CONFIG_PATH #更新系統庫緩存 #source /etc/bash.bashrc
#更新數據庫索引 #sudo updatedb
最后,可通過例子驗證安裝是否成功,具體可參考以上兩個博客。上述文件(百度雲盤備份不對外提供)。
三、環境搭建之swig和codeblocks
參考鏈接:linux下Python調用海康SDK實時顯示網絡攝像頭、ubuntu源碼安裝swig(博客一)、ubuntu源碼安裝swig(博客二)
swig在上文“一”中已經介紹過,而codeblocks是一款集成開發環境,在此使用主要是考慮到其方便添加各種庫路徑,執行以下命令:
#添加源,獲取個人軟件包檔案源(ppa:personal package archives),將其添加至當前apt庫中,並自動導入公鑰
sudo add-apt-repository ppa:damien-moore/codeblocks-stable
#更新源 sudo apt update
#安裝codeblocks(該源默認版本為16.01)和build-essential sudo apt install codeblocks build-essential
在上述參考博客中,執行命令sudo apt-get install swig安裝swig,可能會在最后編譯.so動態鏈接庫階段產生如下報錯:error:a comma operator cannot appear in a constant-expression...error:template argument 2 is invalid In function'cv::Vec<unsigned char,2>'*new_cv_Vec_Sl_uint8_t_Sc_2_Sg_SWIG_4(std::vec...。經過反復驗證,發現是swig在封裝得到的.cxx文件(6萬行)中多余了很多小括號,若一行行去掉小括號該行不再報錯。考慮到這主要是swig版本的問題(可能是軟件源導致的問題,但又沒找到合適的軟件源),在ubuntu16.04上按上述更新源並安裝的swig版本為swig3.0.8,而在ubuntu14.04卻是swig2.0.11,若想安裝swig3.0,需要執行sudo apt-get install swig3.0,但源中的版本是swig3.0.2,仍然會在最后編譯時產生如上報錯。這里,個人推薦先按sudo apt-get install swig或swig3.0安裝,然后執行swig -version查看swig版本,若不是swig3.0.8建議執行sudo apt-get remove swig刪除swig,並采用以下編譯安裝方法:(附swig下載地址),首先將swig-3.0.8壓縮包拷貝至工程所在目錄(本文中為/home/rcnn/HK_Double_Camera),執行以下命令:
cd /home/rcnn/HK_Double_Camera #解壓 tar -xzvf swig-3.0.8.tar.gz #新建swigtool目錄,用於存放swig編譯文件 mkdir swigtool cd swig-3.0.8 ./configure --prefix=/home/rcnn/HK_Double_Camera/swigtool
#編譯
make
#安裝
make install sudo gedit /etc/profile #輸入以下兩句並保存退出,即可在其他路徑下也能執行swig命令 export SWIG_PATH=/home/rcnn/HK_Double_Camera/swigtool/bin export PATH=$SWIG_PATH:$PATH
#使配置生效
source /etc/profile
#若接着執行swig -version顯示swig3.0.8則說明安裝成功
此外,還需安裝boost庫(參考博客中未提及),執行以下命令:上述文件(百度雲盤備份不對外提供)。
#搜索軟件包
sudo apt-cache search boost
#安裝 sudo apt-get install libboost-dev
四、上手實驗
參考鏈接:linux下Python調用海康SDK實時顯示網絡攝像頭(唯一參考)
首先下載opencv-swig接口文件,點擊下載。(在編寫接口文件的時候,需要將依賴的頭文件都添加進來,而opencv里面的文件繁多,在Github上面有人已經寫好了)
然后,將接口文件lib文件夾下的文件(opencv文件夾和opencv.i)復制到工程目錄下,與下面三個待封裝編譯的源文件處於同一目錄下(本文中為/home/rcnn/HK_Double_Camera/)。其中,HKIPcamera.cpp文件將在以后博客中做專門注釋解讀。
//HKIPcamera.cpp #include <opencv2/opencv.hpp> #include <iostream> #include <time.h> #include <cstdio> #include <cstring> #include <iostream> #include <list> #include "HCNetSDK.h" #include "LinuxPlayM4.h" #include <unistd.h> #include <pthread.h> #define USECOLOR 1 #define WINAPI using namespace cv; using namespace std; //-------------------------------------------- int iPicNum = 0;//Set channel NO. LONG nPort = -1; HWND hWnd = NULL; pthread_mutex_t g_cs_frameList; list<Mat> g_frameList; LONG lUserID; NET_DVR_DEVICEINFO_V30 struDeviceInfo; LONG lRealPlayHandle = -1; void yv12toYUV(char *outYuv, char *inYv12, int width, int height, int widthStep) { int col, row; unsigned int Y, U, V; int tmp; int idx; //printf("widthStep=%d.\n",widthStep); for (row = 0; row<height; row++) { idx = row * widthStep; int rowptr = row*width; for (col = 0; col<width; col++) { //int colhalf=col>>1; tmp = (row / 2)*(width / 2) + (col / 2); // if((row==1)&&( col>=1400 &&col<=1600)) // { // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp); // printf("row*width+col=%d,width*height+width*height/4+tmp=%d,width*height+tmp=%d.\n",row*width+col,width*height+width*height/4+tmp,width*height+tmp); // } Y = (unsigned int)inYv12[row*width + col]; U = (unsigned int)inYv12[width*height + width*height / 4 + tmp]; V = (unsigned int)inYv12[width*height + tmp]; // if ((col==200)) // { // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp); // printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp); // return ; // } if ((idx + col * 3 + 2)> (1200 * widthStep)) { //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2); } outYuv[idx + col * 3] = Y; outYuv[idx + col * 3 + 1] = U; outYuv[idx + col * 3 + 2] = V; } } //printf("col=%d,row=%d.\n",col,row); } //解碼回調 視頻為YUV數據(YV12),音頻為PCM數據 void CALLBACK DecCBFun(int nPort, char * pBuf, int nSize, FRAME_INFO * pFrameInfo, void * nReserved1, int nReserved2) { long lFrameType = pFrameInfo->nType; if (lFrameType == T_YV12) { #if USECOLOR //int start = clock(); static IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 3);//???????????????????Y???????????? yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth, pFrameInfo->nHeight, pImgYCrCb->widthStep);//????????????????RGB???????? static IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 3); cvCvtColor(pImgYCrCb, pImg, CV_YCrCb2RGB); //int end = clock(); #else static IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth, pFrameInfo->nHeight), 8, 1); memcpy(pImg->imageData, pBuf, pFrameInfo->nWidth*pFrameInfo->nHeight); #endif //printf("%d\n",end-start); //Mat frametemp(pImg), frame; //frametemp.copyTo(frame); // cvShowImage("IPCamera",pImg); // cvWaitKey(1); pthread_mutex_lock(&g_cs_frameList); Mat mat=cvarrToMat(pImg); g_frameList.push_back(mat); pthread_mutex_unlock(&g_cs_frameList); #if USECOLOR // cvReleaseImage(&pImgYCrCb); // cvReleaseImage(&pImg); #else /*cvReleaseImage(&pImg);*/ #endif //此時是YV12格式的視頻數據,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile); //fwrite(pBuf,nSize,1,fp); } /*************** else if (lFrameType ==T_AUDIO16) { //此時是音頻數據,數據保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile); } else { } *******************/ } ///實時流回調 void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser) { DWORD dRet; switch (dwDataType) { case NET_DVR_SYSHEAD: //系統頭 if (!PlayM4_GetPort(&nPort)) //獲取播放庫未使用的通道號 { break; } if (dwBufSize > 0) { if (!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024 * 1024)) { dRet = PlayM4_GetLastError(nPort); break; } //設置解碼回調函數 只解碼不顯示 if (!PlayM4_SetDecCallBack(nPort, DecCBFun)) { dRet = PlayM4_GetLastError(nPort); break; } //設置解碼回調函數 解碼且顯示 //if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL)) //{ // dRet=PlayM4_GetLastError(nPort); // break; //} //打開視頻解碼 if (!PlayM4_Play(nPort, hWnd)) { dRet = PlayM4_GetLastError(nPort); break; } //打開音頻解碼, 需要碼流是復合流 // if (!PlayM4_PlaySound(nPort)) // { // dRet=PlayM4_GetLastError(nPort); // break; // } } break; case NET_DVR_STREAMDATA: //碼流數據 if (dwBufSize > 0 && nPort != -1) { BOOL inData = PlayM4_InputData(nPort, pBuffer, dwBufSize); while (!inData) { sleep(10); inData = PlayM4_InputData(nPort, pBuffer, dwBufSize); cout << (L"PlayM4_InputData failed \n") << endl; } } break; } } void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser) { char tempbuf[256] = { 0 }; switch (dwType) { case EXCEPTION_RECONNECT: //預覽時重連 printf("----------reconnect--------%d\n", time(NULL)); break; default: break; } } bool OpenCamera(char* ip, char* usr, char* password) { lUserID = NET_DVR_Login_V30(ip, 8000, usr, password, &struDeviceInfo); if (lUserID == 0) { cout << "Log in success!" << endl; return TRUE; } else { printf("Login error, %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return FALSE; } } void * ReadCamera(void* IpParameter) { //--------------------------------------- //設置異常消息回調函數 NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL); //cvNamedWindow("Mywindow", 0); //cvNamedWindow("IPCamera", 0); //HWND h = (HWND)cvGetWindowHandle("Mywindow"); //h = cvNamedWindow("IPCamera"); //--------------------------------------- //啟動預覽並設置回調數據流 NET_DVR_CLIENTINFO ClientInfo; ClientInfo.lChannel = 1; //Channel number 設備通道號 ClientInfo.hPlayWnd = NULL; //窗口為空,設備SDK不解碼只取流 ClientInfo.lLinkMode = 1; //Main Stream ClientInfo.sMultiCastIP = NULL; LONG lRealPlayHandle; lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, fRealDataCallBack, NULL, TRUE); if (lRealPlayHandle<0) { printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n", NET_DVR_GetLastError()); //return -1; } else cout << "碼流回調成功!" << endl; sleep(-1); //fclose(fp); //--------------------------------------- //關閉預覽 if (!NET_DVR_StopRealPlay(lRealPlayHandle)) { printf("NET_DVR_StopRealPlay error! Error number: %d\n", NET_DVR_GetLastError()); return 0; } //注銷用戶 NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); //return 0; } void init(char* ip, char* usr, char* password){ pthread_t hThread; cout << "IP:" << ip << " UserName:" << usr << " PassWord:" << password << endl; NET_DVR_Init(); NET_DVR_SetConnectTime(2000, 1); NET_DVR_SetReconnect(10000, true); OpenCamera(ip, usr, password); pthread_mutex_init(&g_cs_frameList, NULL); //hThread = ::CreateThread(NULL, 0, ReadCamera, NULL, 0, 0); pthread_create(&hThread, NULL, ReadCamera, NULL); } Mat getframe(){ Mat frame1; pthread_mutex_lock(&g_cs_frameList); while (!g_frameList.size()){ pthread_mutex_unlock(&g_cs_frameList); pthread_mutex_lock(&g_cs_frameList); } list<Mat>::iterator it; it = g_frameList.end(); it--; Mat dbgframe = (*(it)); (*g_frameList.begin()).copyTo(frame1); frame1 = dbgframe; g_frameList.pop_front(); //imshow("camera", frame1); //waitKey(1); g_frameList.clear(); pthread_mutex_unlock(&g_cs_frameList); return(frame1); } void release(){ //close(hThread); NET_DVR_StopRealPlay(lRealPlayHandle); //注銷用戶 NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); }
//HKIPcamera.h #include <opencv2/opencv.hpp> using namespace cv; void init(char* ip, char* usr, char* password); Mat getframe(); void release();
// HKIPcamera.i /* Example of wrapping a C function that takes a C double array as input using * numpy typemaps for SWIG. */ %module HKIPcamera %include <opencv/mat.i> %cv_mat__instantiate_defaults %header %{ /* Includes the header in the wrapper code */ #include "HKIPcamera.h" %} %include "HKIPcamera.h"
有了“一”中的理解,這里看起來可能不那么費勁了,執行以下命令:
#進入.i文件所在目錄 cd /home/rcnn/HK_Double_Camera #封裝,-I與opencv的core文件夾、core.hpp路徑中間無空格 swig -I/home/rcnn/opencv-2.4.13.6/modules/core/include -python -c++ HKIPcamera.i
將能在同級目錄得到HKIPcamera.cxx和HKIPcamera.py文件。
然后,利用codeblocks進行編譯(實際上也可用命令行編譯,但由於依賴庫、頭文件太多、命令行比較長...),在codeblocks中新建shared library工程,依此選擇GO---Next---C++----工程名取為“HKIPcamera”(路徑為 /home/rcnn/HK_Double_Camera/HKIPcamera)---next---finish,刪除新建工程的main.cpp,右鍵工程名Add files----選擇文件----確定,依此添加HKIPcamera.cpp,HKIPcamera.h,HKIPcamera_wrap.cxx文件
在codeblocks中進行如下配置時,(右鍵工程名---Build options)左邊任選debug或release模式,與最后編譯方式一致即可
Build options---Linker settings---Linker libraries中添加opencv和海康威視SDK的所有庫文件路徑,如下圖所示,分別進入/home/rcnn/opencv-2.4.13.6/opencv-debug/lib/、
/home/rcnn/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib和/home/rcnn/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib/HCNetSDKCom路徑下選擇所有.so和.a文件。(建議不選擇相對路徑)
Build options---Search directories – Compiler中添加所有頭文件路徑:/usr/local/include/ 、/usr/local/include/opencv、/usr/local/include/opencv2、
/home/rcnn/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/include、/usr/include/python2.7、/usr/include/boost(一共5個路徑,其中3個是opencv頭文件路徑,1個是Python.h,1個是boost庫頭文件路徑)
Build options---Search directories---Linker添加/usr/local/lib路徑(一系列有關的庫文件)
Build options---Compiler settings---Other compiler options添加 -fPIC(-fPIC表明使用地址無關代碼,Linux下編譯共享庫時,必須加上-fPIC參數,否則在鏈接時會有錯誤提示,點擊這里了解fPIC更多知識)
主界面---Settings---Compiler settings---Linker settings---左邊Linker libraries 添加 /usr/lib/x86_64-linux-gnu/libpthread.a 右邊 Other linker options 添加 -lpthread,如下圖所示: (與海康威視源文件中多線程有關,cpp文件中含頭文件 pthread.h)
將海康威視SDK動態鏈接庫地址添加進系統路徑,執行以下命令:
sudo gedit /etc/ld.so.conf #末尾添加 /home/rcnn/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib /home/rcnn/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib/HCNetSDKCom #保存退出 sudo ldconfig
對應於上述設置,選擇debug或release模式,點擊build或rebuild,可見如下編譯命令,將在工程目錄(/home/rcnn/HK_Double_Camera/HKIPcamera/bin/Debug)下生成libHKIPcamera.so動態共享對象。
注意:若以后再次打開codeblocks工程,出現死機現象,刪除工程下的.layout文件即可解決。
最后,工程目錄下新建test文件夾,將libHKIPcamera.so改名為_HKIPcamera.so,與swig封裝時產生的HKIPcamera.py文件一同放置在test目錄(/home/rcnn/HK_Double_Camera/test)下,新建如下test.py文件。
import HKIPcamera import time import numpy as np import matplotlib.pyplot as plt import cv2 ip = str('192.168.1.64') #攝像頭IP地址,要和本機IP在同一局域網 name = str('admin') #管理員用戶名 pw = str('12345678') #管理員密碼 HKIPcamera.init(ip, name, pw) while True: fram = HKIPcamera.getframe() cv2.imshow('show_img', np.array(fram)) cv2.waitKey(1) #HKIPcamera.release() #time.sleep(5)
若之前未安裝Python常用第三方庫(cv2等)和配置本機IP,還需按下述處理:
sudo apt-get update sudo apt-get install cython python-opencv python-tk python-scipy python-yaml sudo pip install easydict sudo python -m pip install Pillow sudo apt-get install python-matplotlib
配置IP(右上角扇形符號---以太網有線連接---編輯---IPv4設置---手動---填寫地址192.168.1.XXX、子網掩碼255.255.255.0、網關0.0.0.0----保存),保證本機與攝像頭IP在同一網段即可,最后執行test.py,大功告成!上述文件(百度雲盤備份不對外提供)。
五、遇到的一些坑
(1)預裝cuda9.0再安裝opencv遇到的問題(以下解決辦法摘錄自參考鏈接)
若在編譯安裝opencv前機器預裝了cuda9.0,直接按上文“二”中編譯安裝方式將會報錯如下:
CMake Error:The following variables are used in this project, but they are set to NOTFOUND...
linked by target "opencv_cudev"in directory .../opencv/sources/modules/dudev...
因此,需要先修改相關腳本文件,再按“二”中進行編譯安裝。修改如下:
find_cuda_helper_libs(nppial) find_cuda_helper_libs(nppicc) find_cuda_helper_libs(nppicom) find_cuda_helper_libs(nppidei) find_cuda_helper_libs(nppif) find_cuda_helper_libs(nppig) find_cuda_helper_libs(nppim) find_cuda_helper_libs(nppist) find_cuda_helper_libs(nppisu) find_cuda_helper_libs(nppitc) set(CUDA_npp_LIBRARY "${CUDA_nppc_LIBRARY};${CUDA_nppial_LIBRARY};${CUDA_nppicc_LIBRARY};${CUDA_nppicom_LIBRARY};${CUDA_nppidei_LIBRARY};${CUDA_nppif_LIBRARY};${CUDA_nppig_LIBRARY};${CUDA_nppim_LIBRARY};${CUDA_nppist_LIBRARY};${CUDA_nppisu_LIBRARY};${CUDA_nppitc_LIBRARY};${CUDA_npps_LIBRARY}")
個人經驗:將有關compute20腳本刪除(文本中搜索2.0 2.X 1.X之類的均可刪除,保留3.X)
(2)swig版本的問題
嘗試過swig2.0.11、swig3.0.2和swig3.0.8,只在swig3.0.8下編譯成功,其余版本均報錯如下,具體解決辦法可參見上文“三”。
六、其他
(1)如何卸載opencv
參考鏈接:ubuntu卸載opencv(僅參考“一”)
若是按上文“二”中編譯安裝opencv,可執行以下命令卸載opencv(注意做好文件備份)
cd /home/rcnn/opencv-2.4.13.6/opencv-debug sudo make uninstall cd .. sudo rm -r build sudo rm -r /usr/local/include/opencv2 /usr/local/include/opencv /usr/include/opencv /usr/include/opencv2 /usr/local/share/opencv /usr/local/share/OpenCV /usr/share/opencv /usr/share/OpenCV /usr/local/bin/opencv* /usr/local/lib/libopencv*
(2)如何卸載swig等ubuntu軟件
參考鏈接:linux中卸載軟件的幾種命令、ubuntu系統中默認安裝路徑、安裝、卸載方法總結
由於swig是用apt-get安裝的,可用sudo apt-get remove swig進行卸載,其余可能用到的卸載命令如下:
(3)源是什么
參考鏈接:ubuntu中的PPA源是什么?、ubuntu添加PPA源
PPA源(Personal Package Archives)個人軟件包文檔,只有Ubuntu用戶可以用,而所有的PPA都是寄存在launchpad.net網站上。Launchpad(啟動器)是Canonical公司所架設的網站,是一個提供維護、支援或連絡Ubuntu開發者的平台。其中Launchpad提供了線上翻譯軟件的功能,可以自由的參與Ubuntu或相關自由軟件的開發或翻譯工作。也可以利用該網站的回報機制來回報相關軟件的Bug,或者進一步提供建議。使用PPA的好處是Ubuntu系統中使用PPA源的軟件可以讓你在第一時間體驗到最新版本的軟件。有很多PPA軟件源提供多個版本,包括正式穩定版、每日創建版,開發版、測試版等。一個完整的通過PPA源安裝軟件的命令,例如添加chromium穩定版源(其網址為https://launchpad.net/~chromium-daily/+archive/stable)並安裝的命令:(上文“三”中安裝codeblocks與之類似)
#添加源,自動導入密鑰等內容 sudo add-apt-repository ppa:chromium-daily/stable#更新源 sudo apt-get update #安裝chromium軟件 sudo apt-get install chromium
實際上,執行命令sudo add-apt-repository ppa:chromium-daily/stable,即向/etc/apt/sources.list 源文件列表自動添加了(以下兩行)兩個軟件源:(下圖為chromium頁面相關介紹)
deb http://ppa.launchpad.net/chromium-daily/stable/ubuntu YOUR_UBUNTU_VERSION_HERE main
deb-src http://ppa.launchpad.net/chromium-daily/stable/ubuntu YOUR_UBUNTU_VERSION_HERE main
對於“源”,有時候還會遇見一些問題,比如網速慢,比如“W 無法下載,無法發起與cn.archive.ubuntu.com...”的連接,這主要是由於被牆了原因,可以切換到國內源解決,即將/etc/apt/sources.list內cn.archive.ubuntu.com改為mirrors.aliyun.com,替換完成后再sudo apt update,記住備份原來的/etc/apt/sources.list。
(4)環境變量
參考鏈接:ubuntu12.04添加環境變量、linux環境變量及其設置、/etc/ld.so.conf詳解
環境變量分為系統級和用戶級
系統級變量設置環境為/etc/environment、/etc/profile等,不要輕易修改,易造成系統錯誤。
用戶級變量設置路徑為~/.bashrc、~/.bash_profile等(用戶主目錄~下隱藏文件),bashrc負責控制台調用的環境變量,profile負責本用戶所有環境變量的設置。
(5)多版本opencv共存
之前懷疑是opencv版本的問題,差點就入坑了,多版本並存問題盡量避免吧,易混亂,可參考博客一、博客二。
(6)C++版的opencv與python-opencv的不同
個人總結一句:opencv本身就是C++寫的,功能十分齊全,編譯安裝后內存很大;python-opencv對應的貌似是cv2.pyd,類似於動態鏈接庫,內部集成了常見的函數方法,內存比較小。