摄像头方案设计
- 功能介绍
- 初始化模式采用霍夫圆检测模式,寻求画面内符合条件的最佳圆形;
- 按下功能按键1(该程序设计为‘R’)选定当前圆所在的矩形范围为感兴趣区域;
- 采用camshift方式进入图形描边模式;
- 按下功能键2(该程序设计为‘a’)停止记录小球运动轨迹;
- 调用预处理模式,并返回容器储存的一系列坐标点。
- 思路分析
- 调用VideoCapture video(0),打开本机摄像头;
- 采用标志位的方式判定当前状态(ROI选择模式/轨迹记录模式),其中标志位判定为0时进入ROI选择模式,为1时进入轨迹模式,为其他值时退出循环:
- ROI选择模式:调用HoughCircles检测圆(pretreat),并以圆心为矩阵中心,直径为矩形的长和宽进行区域选定,同时完成ROI区域的calchist计算,为记录模式做准备;
- 轨迹记录模式:利用camshift算法(对当前页面进行直方图统计,获取最接近的ROI模式中直方图统计的区域)进行当前画面上目标的轨迹跟踪,并调用line函数在黑色背景上进行轨迹记录。
- 调用waitKey判断功能按键‘a’是否按下,若按下则在销毁实时显示窗口,并进行后续预处理操作.
- 代码介绍
bool video_record(std::vector<cv::Point2i> &ptdata)
{
using namespace cv;
using namespace std;
VideoCapture video(0);
//VideoCapture video("nvcamerasrc ! video/x-raw(memory:NVMM), width=(int)640, height=(int)360,format=(string)I420, framerate=(fraction)25/1 ! nvvidconv flip-method=0 ! video/x-raw, format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink");
Mat Circle_frame,frame;
Mat roi,maskroi;
Mat hsv, hue, mask, hist, histimg = Mat::zeros(200, 320, CV_8UC3), backproj;
int hsize = 16;
int calc_flag = 0;
int point_flag = 1;
int slection_flag =0;
int vmin = 10, vmax = 256, smin = 30;
float hranges[] = {0,180};
const float* phranges = hranges;
vector<Vec3f> circles;
Point start,end;
Rect trackWindow,selection;
vector<Mat> maskroi_channels;
video.read(Circle_frame);
Mat Back_Ground= Mat::zeros(Circle_frame.size(),Circle_frame.type());
Mask = cv::Mat::zeros(Circle_frame.size(),Circle_frame.type());
while(true)
{
video.read(Circle_frame);
imshow("src",Circle_frame);
if (waitKey(5) == 'q')
break;
Circle_frame.copyTo(frame);
cvtColor(Circle_frame,hsv,COLOR_BGR2HSV);
int _vmin = vmin, _vmax = vmax;
inRange(hsv, Scalar(0, smin, MIN(_vmin,_vmax)),Scalar(180, 256, MAX(_vmin, _vmax)), mask);
int ch[] = {0, 0};
hue.create(hsv.size(), hsv.depth());
mixChannels(&hsv, 1, &hue, 1, ch, 1);
//calc_flag = 0时,进行霍夫圆检测
if(calc_flag == 0)
{
cvtColor(frame,frame,COLOR_BGR2GRAY);
GaussianBlur(frame,frame,Size(5,5),2,2);
HoughCircles(frame,circles,HOUGH_GRADIENT,1,frame.rows/4,150,40);
if(circles.size() != 0)
{
int cir_x = circles[0][0];
int cir_y = circles[0][1];
int r = circles[0][2];
if((cir_x - r > 0) && (cir_y - r > 0) && (cir_x + r < Circle_frame.cols)&& (cir_y + r < Circle_frame.rows))
{
selection = Rect(cir_x - r,cir_y - r,2*r,2*r);
maskroi = Circle_frame(Rect(cir_x - r,cir_y - r,2*r,2*r));
imshow("roi",maskroi);
if (waitKey(5) == 'r' && !maskroi.empty())
{
calc_flag = 1;
frame.release();
destroyWindow("roi");
}
Mat roi(hue, selection), maskroi(mask, selection);
calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges);
normalize(hist, hist, 0, 255, NORM_MINMAX);
trackWindow = selection;
histimg = Scalar::all(0);
int binW = histimg.cols / hsize;
Mat buf(1, hsize, CV_8UC3);
for( int i = 0; i < hsize; i++ )
buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180./hsize), 255, 255);
cvtColor(buf, buf, COLOR_HSV2BGR);
for( int i = 0; i < hsize; i++ )
{
int val = saturate_cast<int>(hist.at<float>(i)*histimg.rows/255);
rectangle( histimg, Point(i*binW,histimg.rows),Point((i+1)*binW,histimg.rows - val),Scalar(buf.at<Vec3b>(i)), -1, 8 );
imshow("histimg",histimg);
}
}
}
}
else if(calc_flag == 1)
{
calcBackProject(&hue, 1, 0, hist, backproj, &phranges);
backproj &= mask;
RotatedRect trackBox = CamShift(backproj, trackWindow,TermCriteria( TermCriteria::EPS | TermCriteria::COUNT, 10, 1 ));
cout<<trackBox.center<<endl;
if(point_flag == 1)
{
start = trackBox.center;
end = start;
point_flag = 2;
}
if(point_flag > 1)
{
end = trackBox.center;
line(Back_Ground,start,end,Scalar(255,255,255),3,LINE_AA,0);
imshow("Back_Ground",Back_Ground);
start = end;
}
if (waitKey(5) == 'a' && !Back_Ground.empty())
{
calc_flag = 2;
}
}
else
break;
}
Circle_frame.release();
pretreat_record(Back_Ground , ptdata);
Back_Ground.release();
return true;
}
- 待改进问题
- 霍夫圆检测存在不稳定性,参数调节需要依据环境情况进行调节,具有经验性.主要问题如下:
- 最大值最小值参数设定存在问题,无法确定理想的参数来应对所有的圆检测
- camshift算法依赖于颜色进行判定跟踪,易受目标近似颜色背景的干扰;
- 实际测试过程中易出现检测过程产生不完全封闭图像的情况,干扰后续判断.
- 优势
- 不需要鼠标选定ROI区域,提高了系统的自动化程度和鲁棒性;
- 仅采用霍夫圆检测进行前期ROI选定,因此可以在最理想情况下进行目标区域选定,不需要反复调节参数,在一定程度以上提高了圆检测的准确定;
- 在ROI模式中若存在多个圆形目标,可以自主选择最佳感兴趣区域。