Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束.
参考博客:
https://www.cnblogs.com/xfzhang/p/7261172.html
https://www.cnblogs.com/necp-zwl/p/6517092.html
Camshift它是MeanShift算法的改进,称为连续自适应的MeanShift算法,CamShift算法的全称是"Continuously Adaptive Mean-SHIFT",它的基本思想是视频图像的所有帧作MeanShift运算,并将上一帧的结果(即Search Window的中心和大小)作为下一帧MeanShift算法的Search Window的初始值,如此迭代下去
函数:
C++: void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )
参数详解:
onst Mat* images:输入图像
int nimages:输入图像的个数
const int* channels:需要统计直方图的第几通道
InputArray mask:掩膜,,计算掩膜内的直方图 …Mat()
OutputArray hist:输出的直方图数组
int dims:需要统计直方图通道的个数
const int* histSize:指的是直方图分成多少个区间,就是 bin的个数
const float** ranges: 统计像素值得区间
bool uniform=true::是否对得到的直方图数组进行归一化处理
#include <iostream> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/videoio.hpp> #include <opencv2/highgui.hpp> #include <opencv2/video.hpp> 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 |<none>| 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);//根据HSV值丢弃低亮度值 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; } }截图: