OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 7251|回复: 17

meanshift or camshift 对小目标的追踪问题

[复制链接]
发表于 2016-6-16 16:46:25 | 显示全部楼层 |阅读模式
我试用书上的 标准 代码   遇到两种情况  会出现直接报错的问题
1 一开始就框很小的点目标 会直接报错  
2 camshift 一开始框较大(相比于后面) 后面目标越飞越远  camshift 的跟踪框越来越小 然后就会直接报错
错误提示都是同样的 ,camshift.cpp:81: error: (-5) Input window has non-positive sizes in function cvMeanShift      网上查 说是个bug  
有人了解 如何解决这个问题么 或者说 这个方法 不适合  较小点的 目标
回复

使用道具 举报

发表于 2016-6-17 00:04:44 | 显示全部楼层
應該是那個範例寫得不好,
正常來說跟蹤框是可以縮到剩一個點,
若物體再出現,那個點還是會擴大成框格的,
試試底下這個範例,
他可以打開攝影鏡頭,
然後你用滑鼠左鍵框選你的跟蹤的目標,
  1. //对运动物体的跟踪:
  2. //如果背景固定,可用帧差法 然后在计算下连通域 将面积小的去掉即可
  3. //如果背景单一,即你要跟踪的物体颜色和背景色有较大区别 可用基于颜色的跟踪 如CAMSHIFT 鲁棒性都是较好的
  4. //如果背景复杂,如背景中有和前景一样的颜色 就需要用到一些具有预测性的算法 如卡尔曼滤波等 可以和CAMSHIFT结合

  5. #ifdef _CH_
  6. #pragma package <opencv>
  7. #endif

  8. #ifndef _EiC
  9. #include "cv.h"
  10. #include "highgui.h"
  11. #include <stdio.h>
  12. #include <ctype.h>
  13. #endif

  14. IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0;
  15. //用HSV中的Hue分量进行跟踪
  16. CvHistogram *hist = 0;
  17. //直方图类
  18. int backproject_mode = 0;
  19. int select_object = 0;
  20. int track_object = 0;
  21. int show_hist = 1;
  22. CvPoint origin;
  23. CvRect selection;
  24. CvRect track_window;
  25. CvBox2D track_box;
  26. //Meanshift跟踪算法返回的Box类
  27. //typedef struct CvBox2D{
  28. //CvPoint2D32f center; /* 盒子的中心 */
  29. //CvSize2D32f size; /* 盒子的长和宽 */
  30. //float angle; /* 水平轴与第一个边的夹角,用弧度表示*/
  31. //}CvBox2D;
  32. CvConnectedComp track_comp;
  33. //连接部件
  34. //typedef struct CvConnectedComp{
  35. //double area; /* 连通域的面积 */
  36. //float value; /* 分割域的灰度缩放值 */
  37. //CvRect rect; /* 分割域的 ROI */
  38. //} CvConnectedComp;
  39. int hdims = 16;
  40. //划分直方图bins的个数,越多越精确
  41. float hranges_arr[] = {0,180};
  42. //像素值的范围
  43. float* hranges = hranges_arr;
  44. //用于初始化CvHistogram类
  45. int vmin = 10, vmax = 256, smin = 30;
  46. //用于设置滑动条

  47. void on_mouse( int event, int x, int y, int flags, void* param )
  48. //鼠标回调函数,该函数用鼠标进行跟踪目标的选择
  49. {
  50.     if( !image )
  51.         return;

  52.     if( image->origin )
  53.         y = image->height - y;
  54.     //如果图像原点坐标在左下,则将其改为左上

  55.     if( select_object )
  56.     //select_object为1,表示在用鼠标进行目标选择
  57.     //此时对矩形类selection用当前的鼠标位置进行设置
  58.     {
  59.         selection.x = MIN(x,origin.x);
  60.         selection.y = MIN(y,origin.y);
  61.         selection.width = selection.x + CV_IABS(x - origin.x);
  62.         selection.height = selection.y + CV_IABS(y - origin.y);

  63.         selection.x = MAX( selection.x, 0 );
  64.         selection.y = MAX( selection.y, 0 );
  65.         selection.width = MIN( selection.width, image->width );
  66.         selection.height = MIN( selection.height, image->height );
  67.         selection.width -= selection.x;
  68.         selection.height -= selection.y;
  69.     }

  70.     switch( event )
  71.     {
  72.     case CV_EVENT_LBUTTONDOWN:
  73.             //鼠标按下,开始点击选择跟踪物体
  74.         origin = cvPoint(x,y);
  75.         selection = cvRect(x,y,0,0);
  76.         select_object = 1;
  77.         break;
  78.     case CV_EVENT_LBUTTONUP:
  79.             //鼠标松开,完成选择跟踪物体
  80.         select_object = 0;
  81.         if( selection.width > 0 && selection.height > 0 )
  82.                 //如果选择物体有效,则打开跟踪功能
  83.             track_object = -1;
  84.         break;
  85.     }
  86. }


  87. CvScalar hsv2rgb( float hue )
  88. //用于将Hue量转换成RGB量
  89. {
  90.     int rgb[3], p, sector;
  91.     static const int sector_data[][3]=
  92.         {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
  93.     hue *= 0.033333333333333333333333333333333f;
  94.     sector = cvFloor(hue);
  95.     p = cvRound(255*(hue - sector));
  96.     p ^= sector & 1 ? 255 : 0;

  97.     rgb[sector_data[sector][0]] = 255;
  98.     rgb[sector_data[sector][1]] = 0;
  99.     rgb[sector_data[sector][2]] = p;

  100.     return cvScalar(rgb[2], rgb[1], rgb[0],0);
  101. }

  102. int main( int argc, char** argv )
  103. {
  104.     CvCapture* capture;
  105.      capture =cvCaptureFromCAM(0) ;
  106. //    if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
  107. //            //打开摄像头
  108. //        capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
  109. //    else if( argc == 2 )
  110. //            //打开avi
  111. //        capture = cvCaptureFromAVI( argv[1] );

  112.     if( !capture )
  113.     //打开视频流失败
  114.     {
  115.         fprintf(stderr,"Could not initialize capturing...\n");
  116.         return -1;
  117.     }

  118.     printf( "Hot keys: \n"
  119.         "\tESC - quit the program\n"
  120.         "\tc - stop the tracking\n"
  121.         "\tb - switch to/from backprojection view\n"
  122.         "\th - show/hide object histogram\n"
  123.         "To initialize tracking, select the object with mouse\n" );
  124.         //打印程序功能列表

  125.     cvNamedWindow( "Histogram", 1 );
  126.     //用于显示直方图
  127.     cvNamedWindow( "CamShiftDemo", 1 );
  128.     //用于显示视频
  129.     cvSetMouseCallback( "CamShiftDemo", on_mouse, 0 );
  130.     //设置鼠标回调函数
  131.     cvCreateTrackbar( "Vmin", "CamShiftDemo", &vmin, 256, 0 );
  132.     cvCreateTrackbar( "Vmax", "CamShiftDemo", &vmax, 256, 0 );
  133.     cvCreateTrackbar( "Smin", "CamShiftDemo", &smin, 256, 0 );
  134.     //设置滑动条

  135.     for(;;)
  136.     //进入视频帧处理主循环
  137.     {
  138.         IplImage* frame = 0;
  139.         int i, bin_w, c;

  140.         frame = cvQueryFrame( capture );
  141.         if( !frame )
  142.             break;

  143.         if( !image )
  144.         //image为0,表明刚开始还未对image操作过,先建立一些缓冲区
  145.         {
  146.             image = cvCreateImage( cvGetSize(frame), 8, 3 );
  147.             image->origin = frame->origin;
  148.             hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
  149.             hue = cvCreateImage( cvGetSize(frame), 8, 1 );
  150.             mask = cvCreateImage( cvGetSize(frame), 8, 1 );
  151.             //分配掩膜图像空间
  152.             backproject = cvCreateImage( cvGetSize(frame), 8, 1 );
  153.             //分配反向投影图空间,大小一样,单通道
  154.             hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );
  155.             //分配直方图空间
  156.             histimg = cvCreateImage( cvSize(320,200), 8, 3 );
  157.             //分配用于直方图显示的空间
  158.             cvZero( histimg );
  159.             //置背景为黑色
  160.         }

  161.         cvCopy( frame, image, 0 );
  162.         cvCvtColor( image, hsv, CV_BGR2HSV );
  163.         //把图像从RGB表色系转为HSV表色系

  164.         if( track_object )
  165.         //track_object非零,表示有需要跟踪的物体
  166.         {
  167.             int _vmin = vmin, _vmax = vmax;

  168.             cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
  169.                         cvScalar(180,256,MAX(_vmin,_vmax),0), mask );
  170.             //制作掩膜板,只处理像素值为H:0~180,S:smin~256,V:vmin~vmax之间的部分
  171.             cvSplit( hsv, hue, 0, 0, 0 );
  172.                         //分离H分量

  173.             if( track_object < 0 )
  174.             //如果需要跟踪的物体还没有进行属性提取,则进行选取框类的图像属性提取
  175.             {
  176.                 float max_val = 0.f;
  177.                 cvSetImageROI( hue, selection );
  178.                 //设置原选择框为ROI
  179.                 cvSetImageROI( mask, selection );
  180.                 //设置掩膜板选择框为ROI
  181.                 cvCalcHist( &hue, hist, 0, mask );
  182.                 //得到选择框内且满足掩膜板内的直方图
  183.                 cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
  184.                 cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
  185.                 // 对直方图的数值转为0~255
  186.                 cvResetImageROI( hue );
  187.                 //去除ROI
  188.                 cvResetImageROI( mask );
  189.                 //去除ROI
  190.                 track_window = selection;
  191.                 track_object = 1;
  192.                                 //置track_object为1,表明属性提取完成
  193.                 cvZero( histimg );
  194.                 bin_w = histimg->width / hdims;
  195.                 for( i = 0; i < hdims; i++ )
  196.                 //画直方图到图像空间
  197.                 {
  198.                     int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
  199.                     CvScalar color = hsv2rgb(i*180.f/hdims);
  200.                     cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
  201.                                  cvPoint((i+1)*bin_w,histimg->height - val),
  202.                                  color, -1, 8, 0 );
  203.                 }
  204.             }

  205.             cvCalcBackProject( &hue, backproject, hist );
  206.             //计算hue的反向投影图
  207.             cvAnd( backproject, mask, backproject, 0 );
  208.             //得到掩膜内的反向投影
  209.             cvCamShift( backproject, track_window,
  210.                         cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
  211.                         &track_comp, &track_box );
  212.             //使用MeanShift算法对backproject中的内容进行搜索,返回跟踪结果
  213.             track_window = track_comp.rect;
  214.             //得到跟踪结果的矩形框

  215.             if( backproject_mode )
  216.                 cvCvtColor( backproject, image, CV_GRAY2BGR );

  217.             if( image->origin )
  218.                 track_box.angle = -track_box.angle;
  219.             cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );
  220.             //画出跟踪结果的位置
  221.         }

  222.         if( select_object && selection.width > 0 && selection.height > 0 )
  223.         //如果正处于物体选择,画出选择框
  224.         {
  225.             cvSetImageROI( image, selection );
  226.             cvXorS( image, cvScalarAll(255), image, 0 );
  227.             cvResetImageROI( image );
  228.         }

  229.         cvShowImage( "CamShiftDemo", image );
  230.         cvShowImage( "Histogram", histimg );

  231.         c = cvWaitKey(10);
  232.         if( (char) c == 27 )
  233.             break;
  234.         switch( (char) c )
  235.         //按键切换功能
  236.         {
  237.         case 'b':
  238.             backproject_mode ^= 1;
  239.             break;
  240.         case 'c':
  241.             track_object = 0;
  242.             cvZero( histimg );
  243.             break;
  244.         case 'h':
  245.             show_hist ^= 1;
  246.             if( !show_hist )
  247.                 cvDestroyWindow( "Histogram" );
  248.             else
  249.                 cvNamedWindow( "Histogram", 1 );
  250.             break;
  251.         default:
  252.             ;
  253.         }
  254.     }

  255.     cvReleaseCapture( &capture );
  256.     cvDestroyWindow("CamShiftDemo");

  257.     return 0;
  258. }

  259. #ifdef _EiC
  260. main(1,"camshiftdemo.c");
  261. #endif
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-17 15:38:22 | 显示全部楼层
smallyouyou 发表于 2016-6-17 00:04
應該是那個範例寫得不好,
正常來說跟蹤框是可以縮到剩一個點,
若物體再出現,那個點還是會擴大成框格的, ...

还是报错了  同样的问题     刚开始画框  框的小 就直接报错了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-17 15:40:11 | 显示全部楼层
就这个目标  甚至更小的

就这个小飞机 我最后要做的 比这个还小啊

就这个小飞机   我最后要做的 比这个还小啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-17 15:41:56 | 显示全部楼层
有一个 用角点 和 光流的方法  可以跟上  但是  只要遇到相交  或者 相似背景 就GG  直接就停了
回复 支持 反对

使用道具 举报

发表于 2016-6-17 18:10:51 | 显示全部楼层
独乐乐 发表于 2016-6-17 15:40
就这个目标  甚至更小的






上面是我測試的結果,是可行的
不過建議初始框格在抓的時候不要抓到背景,
甚至可以抓機身的一部分就好,
如果太小,甚至可以將它飛機圖片放大在取直方圖,
以上建議
回复 支持 反对

使用道具 举报

发表于 2016-6-17 18:13:12 | 显示全部楼层
独乐乐 发表于 2016-6-17 15:38
还是报错了  同样的问题     刚开始画框  框的小 就直接报错了

我這邊執行的狀況,
不管框格框多小都不會報錯
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-19 13:27:37 | 显示全部楼层
smallyouyou 发表于 2016-6-17 18:13
我這邊執行的狀況,
不管框格框多小都不會報錯

你好  你运行的 就是上面给出的代码么?为啥我就跑错呢  2013+2.4.9  这个配置的  例如行人目标  就不会跑错  non_positivr window   我查原因 有的说   框框太小  算M00 0阶矩  的时候 不满足一个条件 就会break
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-19 13:28:42 | 显示全部楼层
独乐乐 发表于 2016-6-19 13:27
你好  你运行的 就是上面给出的代码么?为啥我就跑错呢  2013+2.4.9  这个配置的  例如行人目标  就不会 ...

这个是我毕设 最简单的环境了  如果这个都跑不同 后面真不知道咋办了
回复 支持 反对

使用道具 举报

发表于 2016-6-19 17:05:58 | 显示全部楼层
独乐乐 发表于 2016-6-19 13:27
你好  你运行的 就是上面给出的代码么?为啥我就跑错呢  2013+2.4.9  这个配置的  例如行人目标  就不会 ...

它裡面的條件式是if( fabs(M00) < FLT_EPSILON )   
就是說當M00小於一個極小值就會return -1

你可以去看camshift.cpp的原代碼是怎麼實現的,
甚至可以自己寫一個,基本上不難,


我是用自己改寫的code去跑的,
基本上是將camshift源代碼拉出來改寫而已,
因為目前寫的系統有一部分會用到camshift




回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-4-27 11:10 , Processed in 0.011251 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表