CAMShift camshiftdemo.cpp代码思路

参考博客

1.opencv3中camshift详解(一)camshiftdemo代码详解
https://blog.csdn.net/qq_37775990/article/details/82558110
2.目标跟踪学习笔记_1(opencv中meanshift和camshift例子的应用)
https://www.cnblogs.com/tornadomeet/archive/2012/03/15/2398769.html
3.OpenCV自带的CamShift算法解读
https://www.baidu.com/link?url=w-xSSIYB7vdZOayE2pSl-PflMYadtvXr_A8PVipFnuq_ySiwhq0TbuKCWapwobJJHUSRmw91qe9gkFpqlIkhIHjSjPbfHMHFbteoI_0MgjW&wd=&eqid=c48098ba0004bcc9000000035cd148fc

我具体参考的博客就是以上三个。其他大神的注释网上也都能搜到,也很全面,就不一一列举了,还请见谅。

程序标志位及变量汇总

在这里插入图片描述

camshiftdemo程序思路

定义鼠标操作

		void onMouse(int event, int x, int y, int, void*)

从鼠标左键按下、拖拽选择区域到鼠标左键松开,该函数得到selection(选择的跟踪区域)及trackObject = -1这一标志位。而后者将决定下边对选中区域H直方图的计算。

打开摄像头,如不成功则提示

	    CommandLineParser parser(argc, argv, keys);
	    int camNum = parser.get<int>("1");
	    cap.open(camNum);		

OpenCV中CommandLineParse类主要是命令行解析类。

初始化窗口、鼠标操作及滑动条

 		namedWindow( "Histogram", 0 );
        namedWindow( "CamShift Demo", 0 );
        setMouseCallback( "CamShift Demo", onMouse, 0 );
        createTrackbar( "Vmin", "CamShift Demo", &vmin, 256, 0 );
        createTrackbar( "Vmax", "CamShift Demo", &vmax, 256, 0 );
        createTrackbar( "Smin", "CamShift Demo", &smin, 256, 0 );

由于HSV模型的缺陷,故而要限制过低的饱和度(saturation)和亮度(value)
将hsv图像中hue值在0到180,saturation值在smin到256,value值在_vmin到_vmax之间

  		int vmin = 10, vmax = 256, smin = 30;

for循环

trackObject = -1,即目标区域选择完成

1.满足

		if (trackObject)`

for循环中将当前帧转换为HSV颜色模型并提取Hue(色调)分量。
2.满足

	   if (trackObject < 0)

计算Hue分量的直方图,并归一化到[0,255]
trackObject =1,表示目标区域的直方图只计算一次,除非再次重新选择跟踪区域。此后,for循环只计算当前帧的H分量,即只满足

		if (trackObject)`

将目标特征直方图绘制于histimg

	    rectangle(histimg, Point(i*binW, histimg.rows),    
	   					 Point((i + 1)*binW, histimg.rows - val),
	    				Scalar(buf.at<Vec3b>(i)), -1, 8);

注:
值得注意的是矩阵的坐标系以左上角为原点,y轴是向下的,而需要展示给人看的直方图图案是左下角为原点,y轴向上的。

对当前帧H分量反投影,并进行CAMShift跟踪

		calcBackProject(&hue, 1, 0, hist, backproj, &phranges);
        backproj &= mask;
        RotatedRect trackBox = CamShift(backproj, trackWindow,
                                    TermCriteria( TermCriteria::EPS | TermCriteria::COUNT, 10, 1 ));

返回的跟踪结果在trackBox中,该椭圆框代表了目标在当前帧上的位置和大小。

   		if( trackWindow.area() <= 1 )
            {
                int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6;
                trackWindow = Rect(trackWindow.x - r, trackWindow.y - r,
                                   trackWindow.x + r, trackWindow.y + r) &
                              Rect(0, 0, cols, rows);
            }

如果跟踪窗口的面积小于1,说明搜索窗口的长和宽都小于等于1个像素点了,强制调整窗口的大小。

	    ellipse(image, trackBox, Scalar(0, 0, 255), 3, CV_AA);

trackBox显示在当前帧上。

	     if( selectObject && selection.width > 0 && selection.height > 0 )
	      {
	      		Mat roi(image, selection);
	            bitwise_not(roi, roi);
	     }  
		imshow( "CamShift Demo", image );

只有在选定目标时才会被执行。在按下鼠标左键和抬起鼠标左键之间的这段时间,selectObject为真,selection会随着鼠标的移动不断变化,直到抬起鼠标左键后,
selectObject为假,selection就是选中的目标矩形框。显示选择的目标区域。

热键解释

Esc- 退出程序
c - 清零跟踪目标对象
b - 反向投影模型交替
h - 显示/隐藏直方图
p - 启动/暂停

camshiftdemo程序修改及仿真

将调用摄像头改为调用工程路径下名为"vtest.avi"的视频文件

		VideoCapture capture("vtest.avi");

并将cap替换为capture.

		CommandLineParser parser(argc, argv, keys);

相关内容屏蔽掉。

仿真图如下:
在这里插入图片描述
在这里插入图片描述
但当背景较为复杂,或者有许多与目标颜色相似像素干扰的情况下,会导致跟踪失败。
仿真失败的图就不放上了。

致谢

至此,VS环境下的CAMShift算法理解告一段落。至于MATLAB下的CAMShift算法,如果毕业前时间允许,会继续补充~
可算把导师指定的四种基本算法大致过了一遍,接下来就是毕设的攻坚战了!!!

菜鸡解读必有不妥之处,欢迎各位大神批评指正!
同时,感谢浅墨大神在《OpenCV3 编程入门》中给出的源码camshiftdemo.cpp,同时感谢各个博客平台上各位大神给出的思路及注释,感激不尽~

发布了24 篇原创文章 · 获赞 15 · 访问量 5391

猜你喜欢

转载自blog.csdn.net/qq_34122861/article/details/89924822