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,類似於動態鏈接庫,內部集成了常見的函數方法,內存比較小。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM