前言
这段时间,准备复习一下OpenCV,所有就想着学习一下OpenCV的官方例子。
今天分析的是物体跟踪的方法meanshift,也叫均值漂移。
meanshift
menshift就是利用了反向投影进行检测目标,它的官方文档:
https://docs.opencv.org/4.2.0/d7/d00/tutorial_meanshift.html
文档中用下面这个图来举例子,我的理解:首先选择一圆形区域。如图中的蓝色区域,然后计算该区域的质心(蓝色圆点),与原来的圆心位置不重合,所以该圆形向着质心移动,然后再继续计算质心,继续判断质心与圆心的关系,再移动,如此迭代,最终移动到质心和中心重合的地方,即得到了最终结果。
该方法类似于基于梯度求极值,最终会得到一个局部最优解。
官方的例子程序:
#include #include #include #include #include #include using namespace cv;using namespace std;int main(int argc, char **argv){ const string about = "This sample demonstrates the meanshift algorithm.\n" "The example file can be downloaded from:\n" " https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4"; const string keys = "{ h help | | print this help message }" "{ @image || path to image file }"; CommandLineParser parser(argc, argv, keys); parser.about(about); if (parser.has("help")) { parser.printMessage(); return 0; } string filename = parser.get<string>("@image"); if (!parser.check()) { parser.printErrors(); return 0; } VideoCapture capture(filename); if (!capture.isOpened()){ //error in opening the video input cerr << "Unable to open file!" << endl; return 0; } Mat frame, roi, hsv_roi, mask; // take first frame of the video capture >> frame; // setup initial location of window Rect track_window(300, 200, 100, 50); // simply hardcoded the values // set up the ROI for tracking roi = frame(track_window); cvtColor(roi, hsv_roi, COLOR_BGR2HSV); inRange(hsv_roi, Scalar(0, 60, 32), Scalar(180, 255, 255), mask); float range_[] = {0, 180}; const float* range[] = {range_}; Mat roi_hist; int histSize[] = {180}; int channels[] = {0}; calcHist(&hsv_roi, 1, channels, mask, roi_hist, 1, histSize, range); normalize(roi_hist, roi_hist, 0, 255, NORM_MINMAX); // Setup the termination criteria, either 10 iteration or move by atleast 1 pt TermCriteria term_crit(TermCriteria::EPS | TermCriteria::COUNT, 10, 1); while(true){ Mat hsv, dst; capture >> frame; if (frame.empty()) break; cvtColor(frame, hsv, COLOR_BGR2HSV); calcBackProject(&hsv, 1, channels, roi_hist, dst, range); // apply meanshift to get the new location meanShift(dst, track_window, term_crit); // Draw it on image rectangle(frame, track_window, 255, 2); imshow("img2", frame); int keyboard = waitKey(30); if (keyboard == 'q' || keyboard == 27) break; }}
简单分析
运行一下官方例子,动画如下:
这个视频的地址在代码中。
meanshift在OprnCV中的函数原型是这样的
int cv::meanShift ( InputArray probImage,
Rect &window,
TermCriteria criteria
)
probImage:输入的反省投影的图
window:输入输出参数,输入特定的举行返回,进行计算后会返回新的矩形范围
criteria:算法的终止条件
调用的是很简单的,但是算法本身的原理我们还是要稍微理解一下的。