linux下实现Python调用海康威视SDK
---作者疆,未经允许,严禁转载,违权必究---
---欢迎指正,需要源码和文件可站内私信联系---
-----------点击此处链接至博客园原文-----------
功能说明:将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,类似于动态链接库,内部集成了常见的函数方法,内存比较小。