基於海康監控的圖像識別設計
一、基本知識和背景
目前,安防行業正從網絡化向智能化升級;從簡單的視頻獲取、圖像截獲向內容分析、自動跟蹤進化。借助監控攝像頭,進行圖像識別或機器視覺設計的需求,變得越來越強烈。這里分享一些自己的研究。
我選用海康監控,因為目前只能接觸到這種監控,其他的品牌應該差不多。關鍵是思路。
在這篇文章里面,實現1)控制監控攝像頭獲取圖像2)用opencv進行簡單處理3)獲得量化數據一個過程。需要注意的一點是,我這里沒有直接對視頻流進行操作,因為目前我還沒有這個需求。而是對截獲的圖片進行操作,進行處理,達到內容分析的目的。
二、主要步驟
1)獲取並利用海康SDK,得到輸入圖像
官網獲得CH-HCNetSDK(Windows32)V4.3.0.6.zip,里面有文檔和java/mfc/csharp的demo.基於我目前的需求,采用csharp編寫圖像獲取界面,改寫“1-實時預覽示例代碼一”相關內容。

代碼內容清晰完整,是標准的調用dll的模式。其中獲取圖片部分為
private void btnJPEG_Click(object sender, EventArgs e)
{
string sJpegPicFileName;
//圖片保存路徑和文件名 the path and file name to save
sJpegPicFileName = "JPEG_test.jpg";
int lChannel = Int16.Parse(textBoxChannel.Text); //通道號 Channel number
CHCNetSDK.NET_DVR_JPEGPARA lpJpegPara = new CHCNetSDK.NET_DVR_JPEGPARA();
lpJpegPara.wPicQuality = 0; //圖像質量 Image quality
lpJpegPara.wPicSize = 0xff; //抓圖分辨率 Picture size: 2- 4CIF,0xff- Auto(使用當前碼流分辨率),抓圖分辨率需要設備支持,更多取值請參考SDK文檔
//JPEG抓圖 Capture a JPEG picture
if (!CHCNetSDK.NET_DVR_CaptureJPEGPicture(m_lUserID, lChannel, ref lpJpegPara, sJpegPicFileName))
{
iLastErr = CHCNetSDK.NET_DVR_GetLastError();
str = "NET_DVR_CaptureJPEGPicture failed, error code= " + iLastErr;
MessageBox.Show(str);
return;
}
else
{
str = "Successful to capture the JPEG file and the saved file is " + sJpegPicFileName;
MessageBox.Show(str);
}
return;
}
添加Timer事件,每5秒運行一次,自動獲取圖像,文件名為當前時間,並對原代碼略作修改
//將時間補足兩位
OK經過觀察,沒有出現內存溢出,可以使用。如果是多個監控一起使用的話可能會有新的問題,希望有相關經驗的高手能夠指導。
如果是實際使用的話,還需要添加對圖片進行相關的刪除操作,保障硬盤不要溢出。
2)編寫opencv服務,對圖像進行分析
我是這樣理解“服務”的。所謂服務,就是運行在后台,能夠自動處理輸入的數據,得到用戶想要的結果的。如果監控要想能夠“智能”起來,所獲得的就不只是圖片,而是包含圖片相關內容的分析,是一個量化的過程。。
這里就是簡單地獲取最新的圖片,尋找輪廓數目,並且將其打印出來這樣一個過程。
// HelicopterStitching.cpp : 定義控制台應用程序的入口點。
// 2015年1月22日20:29:38 jsxyhelu
# include "stdafx.h"
# include <cv.h >
# include <cxcore.h >
# include <highgui.h >
# include "opencv2/highgui/highgui.hpp"
# include "opencv2/imgproc/imgproc.hpp"
# include "Prehelper.h"
# include "GOFunction.h"
# include "LaplacianBlend.h"
int _tmain( int argc, _TCHAR * argv[])
{
vector <Mat > inputmat;
vector <Mat > outputmat;
vector <cv : :Point2f > points1;
vector <cv : :Point2f > points2;
vector <Point > locmat1;
vector <Point > locmat2;
int i;
//讀入參數
FILE *stream;
int numread, numwritten;
//定義文件路徑
char * cur_dir = "F:\\test";
int iimagesize = 0;
Mat src;
Mat src_gray;
vector <pair < char *,Mat >> imgs;
Mat canny_output;
vector <vector <Point > > contours;
vector <Vec4i > hierarchy;
int thresh = 50;
while( true)
{
imgs = read_img(cur_dir);
if (imgs.size() > 0)
{
src = imgs[imgs.size() - 1].second; //獲得最新的圖片
imshow( "src",src);
cvtColor(src,src_gray,CV_RGB2GRAY);
Canny( src_gray, canny_output, thresh, thresh * 2, 3 );
/// Find contours
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point( 0, 0) );
imshow( "canny_output",canny_output);
printf( "找到輪廓%d個\n",contours.size());
}
cv : :waitKey( 3000); //等待3秒
}
cv : :waitKey();
return 0;
}

三、小結反思
這樣一個項目,原理並不復雜。其魯棒性如何,在高並發的情況下是否會出現新的問題,都需要進一步驗證。但是的確是一種引入監控圖像的方法,並且得到了“智能分析”的結果。
感謝閱讀到此,希望有經驗者能夠提出寶貴意見,希望對你有所幫助。
