Meanshift and Camshift

    xiaoxiao2023-10-03  163

    Meanshift and Camshift

    一.算法原理

    1.Meanshift

    Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束.

    参考博客:

    https://www.cnblogs.com/xfzhang/p/7261172.html

    https://www.cnblogs.com/necp-zwl/p/6517092.html

    2.Camshift

    Camshift它是MeanShift算法的改进,称为连续自适应的MeanShift算法,CamShift算法的全称是"Continuously Adaptive Mean-SHIFT",它的基本思想是视频图像的所有帧作MeanShift运算,并将上一帧的结果(即Search Window的中心和大小)作为下一帧MeanShift算法的Search Window的初始值,如此迭代下去

    二.代码实现

    Meanshift:

    函数:

    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; } }

    截图:

    Camshift:

    #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 camshift 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); 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 camshift to get the new location RotatedRect rot_rect = CamShift(dst, track_window, term_crit); // Draw it on image Point2f points[4]; rot_rect.points(points); for (int i = 0; i < 4; i++) line(frame, points[i], points[(i+1)%4], 255, 2); imshow("img2", frame); int keyboard = waitKey(30); if (keyboard == 'q' || keyboard == 27) break; } }
    最新回复(0)