图像处理之其他杂项(一)之MeanShift的目标跟踪算法opencv c++代码 VS2015+opencv3.2
2017-05-29 23:04
801 查看
MeanShift的目标跟踪算法
这几天在学meanshift跟踪的原理和实现,虽然还不是特别明白,但总想先找个程序跑一下试一下效果,网上的程序多是基于c接口的老的opencv程序,在借鉴大神思路的基础上,对其代码进行了一些小的改动升级,变成了c++接口。大神‘taotao1233’的原meanshift讲解与源代码网址:http://blog.csdn.net/jinshengtao/article/details/30258833。ps:虽然代码可用,但对于代码算法具体原理及实现还未掌握透彻,有待进一步学习。
1.这是根据原有作者的c接口opencv升级的c++接口程序,适用于opencv 接口2.0版本,开发环境为VS2015+opencv3.2。
2.程序视频的默认路径为”E\\dd4.mp4“。”
3.视频启动后按 s 键进行暂停,然后用鼠标选取需要跟踪的矩形框,再次按 s 视频启动进行跟踪。
4.程序有个bug,视频播放完毕会报错。
5.程序中有imwrite函数,opencv本身bug存在,建议编译时选择release选项。
//#include "stdafx.h" //#include "cv.h" //#include "highgui.h" #include<opencv.hpp> #define u_char unsigned char #define DIST 0.5 #define NUM 20 using namespace std; using namespace cv; //全局变量 bool pause = false; bool is_tracking = false; Rect drawing_box; Mat current; double *hist1, *hist2; double *m_wei; double C = 0.0; bool xx = false; bool g_bDrawingBox = false; Mat tempImage; void ShowHelpText(); void init_target(double *hist1, double *m_wei, Mat current) { int t_h, t_w, t_x, t_y; double h, dist; int i, j; int q_r, q_g, q_b, q_temp; t_h = drawing_box.height; t_w = drawing_box.width; t_x = drawing_box.x; t_y = drawing_box.y; h = pow(((double)t_w) / 2, 2) + pow(((double)t_h) / 2, 2); //带宽 Mat pic_hist = Mat(300, 200, CV_8UC3); //生成直方图图像 for (i = 0; i < t_w*t_h; i++) { m_wei[i] = 0.0; } for (i = 0; i < 4096; i++) { hist1[i] = 0.0; } for (i = 0; i < t_h; i++) { for (j = 0; j < t_w; j++) { dist = pow(i - (double)t_h / 2, 2) + pow(j - (double)t_w / 2, 2); m_wei[i * t_w + j] = 1 - dist / h; //printf("%f\n",m_wei[i * t_w + j]); C += m_wei[i * t_w + j]; } } //计算目标权值直方 for (i = t_y; i < t_y + t_h; i++) { for (j = t_x; j < t_x + t_w; j++) { //rgb颜色空间量化为16*16*16 bins /*q_r = ((u_char)current.at(i + j * 3 + 2) / 16; q_g = ((u_char)current->imageData[i * current->widthStep + j * 3 + 1]) / 16; q_b = ((u_char)current->imageData[i * current->widthStep + j * 3 + 0]) / 16;*/ q_r = current.at<Vec3b>(i, j)[2] / 16; q_g = current.at<Vec3b>(i, j)[1] / 16; q_b = current.at<Vec3b>(i, j)[0] / 16; q_temp = q_r * 256 + q_g * 16 + q_b; hist1[q_temp] = hist1[q_temp] + m_wei[(i - t_y) * t_w + (j - t_x)]; } } //归一化直方图 for (i = 0; i < 4096; i++) { hist1[i] = hist1[i] / C; //printf("%f\n",hist1[i]); } //生成目标直方图 double temp_max = 0.0; for (i = 0; i < 4096; i++) //求直方图最大值,为了归一化 { //printf("%f\n",val_hist[i]); if (temp_max < hist1[i]) { temp_max = hist1[i]; } } //画直方图 Point p1, p2; double bin_width = pic_hist.cols / 4096; double bin_unith = pic_hist.rows / temp_max; for (i = 0; i < 4096; i++) { p1.x = i * bin_width; p1.y = pic_hist.rows; p2.x = (i + 1)*bin_width; p2.y = pic_hist.rows - hist1[i] * bin_unith; //printf("%d,%d,%d,%d\n",p1.x,p1.y,p2.x,p2.y); rectangle(pic_hist, p1, p2, Scalar(0, 255, 0), -1, 8, 0); } imwrite("hist1.jpg", pic_hist); //cvReleaseImage(&pic_hist); } void MeanShift_Tracking(Mat current) { int num = 0, i = 0, j = 0; int t_w = 0, t_h = 0, t_x = 0, t_y = 0; double *w = 0, *hist2 = 0; double sum_w = 0, x1 = 0, x2 = 0, y1 = 2.0, y2 = 2.0; int q_r, q_g, q_b; int *q_temp; //Mat pic_hist; t_w = drawing_box.width; t_h = drawing_box.height; Mat pic_hist = Mat(300, 200, CV_8UC3); //生成直方图图像 hist2 = (double *)malloc(sizeof(double) * 4096); w = (double *)malloc(sizeof(double) * 4096); q_temp = (int *)malloc(sizeof(int)*t_w*t_h); while ((pow(y2, 2) + pow(y1, 2) > 0.5) && (num < NUM)) { num++; t_x = drawing_box.x; t_y = drawing_box.y; memset(q_temp, 0, sizeof(int)*t_w*t_h); for (i = 0; i < 4096; i++) { w[i] = 0.0; hist2[i] = 0.0; } for (i = t_y; i < t_h + t_y; i++) { for (j = t_x; j < t_w + t_x; j++) { //rgb颜色空间量化为16*16*16 bins /*q_r = ((u_char)current->imageData[i * current->widthStep + j * 3 + 2]) / 16; q_g = ((u_char)current->imageData[i * current->widthStep + j * 3 + 1]) / 16; q_b = ((u_char)current->imageData[i * current->widthStep + j * 3 + 0]) / 16;*/ q_r = current.at<Vec3b>(i, j)[2] / 16; q_g = current.at<Vec3b>(i, j)[1] / 16; q_b = current.at<Vec3b>(i, j)[0] / 16; q_temp[(i - t_y) *t_w + j - t_x] = q_r * 256 + q_g * 16 + q_b; hist2[q_temp[(i - t_y) *t_w + j - t_x]] = hist2[q_temp[(i - t_y) *t_w + j - t_x]] + m_wei[(i - t_y) * t_w + j - t_x]; } } //归一化直方图 for (i = 0; i < 4096; i++) { hist2[i] = hist2[i] / C; //printf("%f\n",hist2[i]); } //生成目标直方图 double temp_max = 0.0; for (i = 0; i < 4096; i++) //求直方图最大值,为了归一化 { if (temp_max < hist2[i]) { temp_max = hist2[i]; } } //画直方图 Point p1, p2; double bin_width = pic_hist.cols / (4368); double bin_unith = pic_hist.rows / temp_max; for (i = 0; i < 4096; i++) { p1.x = i * bin_width; p1.y = pic_hist.cols; p2.x = (i + 1)*bin_width; p2.y = pic_hist.rows - hist2[i] * bin_unith; rectangle(pic_hist, p1, p2, Scalar(0, 255, 0), -1, 8, 0); } imwrite("hist2.jpg", pic_hist); for (i = 0; i < 4096; i++) { if (hist2[i] != 0) { w[i] = sqrt(hist1[i] / hist2[i]); } else { w[i] = 0; } } sum_w = 0.0; x1 = 0.0; x2 = 0.0; for (i = 0; i < t_h; i++) { for (j = 0; j < t_w; j++) { //printf("%d\n",q_temp[i * t_w + j]); sum_w = sum_w + w[q_temp[i * t_w + j]]; x1 = x1 + w[q_temp[i * t_w + j]] * (i - t_h / 2); x2 = x2 + w[q_temp[i * t_w + j]] * (j - t_w / 2); } } y1 = x1 / sum_w; y2 = x2 / sum_w; //中心点位置更新 drawing_box.x += y2; drawing_box.y += y1; } rectangle(current, Point(drawing_box.x, drawing_box.y), Point(drawing_box.x + drawing_box.width, drawing_box.y + drawing_box.height), Scalar(255, 0, 0), 2); imshow("Meanshift", current); } void onMouse(int eve 4000 nt, int x, int y, int flags, void *param) { if (pause) { switch (event) { case EVENT_MOUSEMOVE: if (g_bDrawingBox) { drawing_box.width = x - drawing_box.x; drawing_box.height = y - drawing_box.y; } break; case CV_EVENT_LBUTTONDOWN: g_bDrawingBox = true; drawing_box = Rect(x, y, 0, 0);//记录起始点//the left up point of the rect //drawing_box.x = x; //drawing_box.y = y; break; case CV_EVENT_LBUTTONUP: //finish drawing the rect (use color green for finish) g_bDrawingBox = false; xx = true; drawing_box.width = x - drawing_box.x; drawing_box.height = y - drawing_box.y; rectangle(current, drawing_box.tl(), drawing_box.br(), Scalar(255, 0, 0), 2); //目标初始化 hist1 = (double *)malloc(sizeof(double) * 16 * 16 * 16); m_wei = (double *)malloc(sizeof(double)*drawing_box.height*drawing_box.width); init_target(hist1, m_wei, current); is_tracking = true; //imshow("Meanshift", current); break; } imshow("Meanshift", current); return; } } int main() { ShowHelpText(); VideoCapture capture("E://dd4.mp4"); capture.grab(); //从视频文件或捕获设备获取下一帧 capture.retrieve(current);//解码并返回抓取了的视频帧 while (1) { if (is_tracking) { MeanShift_Tracking(current); } int c = waitKey(1); //暂停 if (c == 's') { while (1) { pause = true; setMouseCallback("Meanshift", onMouse, 0); current.copyTo(tempImage); if (g_bDrawingBox) rectangle(tempImage, drawing_box.tl(), drawing_box.br(), Scalar(255, 0, 0), 2); if (xx == true) break; waitKey(2); imshow("Meanshift", tempImage); } } while (pause) { if (waitKey(0) == 's') pause = false; } //if (current.size != 0) try { imshow("Meanshift", current); } catch (exception& e) { cout << "视频播放完毕"; return 0; } //else //break; capture.grab(); //从视频文件或捕获设备获取下一帧 capture.retrieve(current);//解码并返回抓取了的视频帧 } namedWindow("Meanshift", 1); return 0; } void ShowHelpText() { //输出欢迎信息和OpenCV版本 printf("\n1.这是根据原有作者的c接口opencv升级的c++接口程序,适用于opencv2.0版本,开发环境为VS2015+opencv3.2\n"); printf("\n2.程序视频的默认路径为(E\\dd4.mp4)\n"); printf("\n3.视频启动后按 s 键进行暂停,然后用鼠标选取需要跟踪的矩形框,再次按 s 视频启动进行跟踪\n"); printf("\n4.程序有个bug,视频播放完毕会报错"); //printf("\n\n ----------------------------------------------------------------------------\n"); //输出一些帮助信息 //printf("\n\n\n\t欢迎来到【鼠标交互演示】示例程序\n"); //printf("\n\n\t请在窗口中点击鼠标左键并拖动以绘制矩形\n"); }
相关文章推荐
- 图像处理之其他杂项(五)之水平集 LevelSet 代码实现 opencv c++ (转载)
- 图像处理之其他杂项(四)之cvSnakeImage()函数代码升级,从C接口到C++接口:snakeImage()
- 图像处理之其他杂项(二)之 opencv vs中断内存等问题解决策略 不定时更新
- Python OpenCV学习笔记之:Meanshift算法目标跟踪
- VS2015+QT5.7+opencv3.10图像处理
- Opencv目标跟踪—CamShift和meanshift算法
- 基于MeanShift的视频目标跟踪算法及代码实现
- 【转载】【图像处理】Haar Adaboost 检测自定义目标(视频车辆检测算法代码)
- meanshift算法图解以及在图像聚类、目标跟踪中的应用
- 【图像特征提取12】OpenCv的SIFT图像局部特征提取描述算法C++代码的实现
- Matlab实现meanshift算法,目标跟踪代码实现
- 图像处理之其他杂项(三)之cvSnakeImage改进升级兼容 适用于opencv2,,在opencv3.0以上版本中测试通过
- C#调用C++图像处理算法(opencv)
- 【图像处理】Haar Adaboost 检测自定义目标(视频车辆检测算法代码)
- 【图像处理】Haar Adaboost 检测自定义目标(视频车辆检测算法代码)
- 【图像处理】Haar Adaboost 检测自定义目标(视频车辆检测算法代码)
- opencv学习-模板匹配算法(单图像模板匹配和基于模板匹配的目标跟踪)
- 图像跟踪与识别-kcf-c++代码解读,算法主流程
- 【图像处理】Haar Adaboost 检测自定义目标(视频车辆检测算法代码)
- c++ opencv 3.2 +Mfc VS2015窗体显示图片方法