zoukankan      html  css  js  c++  java
  • 困扰我4天的问题:三通道的camshift调试不过

      #第一篇日志啊~#

      最近要弄一个跟踪视频中车辆的算法。虽说是弄算法,但是opencv里面封装好了camshift,基本上拿出来用就行了。

      网络上流传的比较广的camshiftdemo,大多使用hsv通道的h通道来进行跟踪。但是路上的车辆黑白颜色居多,路面大致也是深色的,只用h通道跟踪的效果不理想。因此希望通过统计hsv三个通道的值来进行跟踪,这样的话无论遇上黑色车白色车还是彩色车性能都应该能够得到改善。

      想象是这个样子的。可是代码打出来之后,calchist过的histogram所有值都是0。多方调试四天未果,无奈只好把程序放上这个满地牛人之地,祈求牛人们多多指教。

      因为才刚入门opencv,程序中那些可能的可疑的地方都被我改动过了,可能会有各种小问题,不过目前希望各位帮忙看看CalDrawhist这个函数里面为何histogram的数据出不来。

      1 #include <iostream>
      2 #include <string>
      3 #include <io.h>
      4 #include <opencv2/opencv.hpp>
      5 #include<math.h>
      6 #include<cv.h>
      7 
      8 using namespace std;
      9 using namespace cv;
     10 
     11 
     12 
     13  //整体标志
     14     int object=0;//0:未进行初始化,1:已进行特征提取,-1:从新选定区域后未进行特征提取
     15 
     16  //第一部分常量
     17     //数据类
     18     CvCapture *capture;
     19     IplImage *frame,       //原图像
     20              *frame_hsv,    //hsv颜色空间预想
     21              *frame_h,        //h通道图像
     22              *frame_s,        //s通道图像
     23              *frame_v,
     24              *planes[]={frame_h,frame_s,frame_v};
     25              
     26     //直方图类
     27     /** H 分量划分为16个等级,S分量划分为4个等级,v通道分为4个登记 */
     28     int h_bins = 8, s_bins = 4, v_bins=4;
     29     int hist_size[] = {h_bins, s_bins, v_bins};
     30  
     31     //hsv范围
     32     float h_ranges[] = { 0, 180 }; 
     33     float s_ranges[] = { 0, 255 };
     34     float v_ranges[] = { 0, 255 };
     35     float* ranges[] = { h_ranges, s_ranges, v_ranges };
     36     float histmax,histmin,scale;
     37     
     38     //直方图
     39     CvHistogram *histogram=cvCreateHist(3,hist_size,CV_HIST_ARRAY,ranges,1);
     40 
     41 
     42 
     43  //第二部分常量
     44     IplImage *backproject,*mask;//mask为掩膜,但是调试不成功程序中没使用
     45     CvBox2D box;
     46     Rect track_window;
     47     CvConnectedComp track_comp;
     48  
     49  //鼠标部分常量
     50     Rect select;
     51     bool select_flag=false;
     52     Point origin;
     53     
     54  void onMouse(int event,int x,int y,int,void*)
     55  {
     56      //Point origin;//不能在这个地方进行定义,因为这是基于消息响应的函数,执行完后origin就释放了,所以达不到效果。
     57      if(!frame)return ;
     58      if( frame->origin )
     59      y = frame->height - y;
     60     //如果图像原点坐标在左下,则将其改为左上
     61      if(select_flag)
     62      {
     63          select.x=MIN(origin.x,x);//不一定要等鼠标弹起才计算矩形框,而应该在鼠标按下开始到弹起这段时间实时计算所选矩形框
     64          select.y=MIN(origin.y,y);//这两行保证了鼠标可以任意方向选择,因为select永远是最小的一个
     65          select.width=abs(x-origin.x);//算矩形宽度和高度
     66          select.height=abs(y-origin.y);
     67          select&=Rect(0,0,frame->width,frame->height);//保证所选矩形框在视频显示区域之内
     68      }
     69      if(event==CV_EVENT_LBUTTONDOWN)
     70      {
     71          select_flag=1;//鼠标按下的标志赋真值
     72          origin=Point(x,y);//保存下来单击是捕捉到的点
     73          select&=Rect(x,y,0,0);//这里一定要初始化,宽和高为(0,0)是因为在opencv中Rect矩形框类内的点是包含左上角那个点的,但是不含右下角那个点
     74      }
     75      else if(event==CV_EVENT_LBUTTONUP)
     76      {
     77          select_flag=0;
     78          object=1;
     79      }
     80  }
     81 
     82  void CalDrawHist(void)
     83 {
     84     
     85     frame=cvQueryFrame(capture);
     86 
     87     
     88     /** 输入图像转换到HSV颜色空间 */
     89     cvCvtColor( frame, frame_hsv, CV_BGR2HSV );
     90     cvCvtPixToPlane( frame_hsv, frame_h, frame_s, frame_v, 0 );
     91     
     92     /** 根据H,S,V三个平面数据统计直方图 */
     93 
     94     cvCalcHist( planes, histogram, 0, 0 );
     95     cvNormalizeHist(histogram,1);
     96 
     97     /** 获取直方图统计的最大值,用于动态显示直方图 */
     98     
     99     cvGetMinMaxHistValue( histogram, &histmin, &histmax, 0, 0 );
    100  
    101     cout<<histmax;
    102 
    103     /** 设置直方图显示图像 */
    104     int height = 180;
    105     int width = (h_bins*s_bins*v_bins*6);
    106     IplImage* frame_hist = cvCreateImage( cvSize(width,height), 8, 3 );
    107     cvZero( frame_hist );
    108  
    109     /** 用来进行HSV到RGB颜色转换的临时单位图像 */
    110     IplImage * hsv_color = cvCreateImage(cvSize(1,1),8,3);
    111     IplImage * rgb_color = cvCreateImage(cvSize(1,1),8,3);
    112     int bin_w = width / (h_bins * s_bins*v_bins);
    113     for(int h = 0; h < h_bins; h++)
    114     {
    115         for(int s = 0; s < s_bins; s++)
    116         {
    117             
    118             for(int v = 0; v < v_bins; v++)
    119             {
    120                 int i = h*s_bins*v_bins + s*v_bins + v;
    121                 /** 获得直方图中的统计次数,计算显示在图像中的高度 */
    122                 float bin_val = cvQueryHistValue_3D( histogram, h, s, v );
    123                 int intensity = cvRound(bin_val*height/histmax);
    124  
    125                 /** 获得当前直方图代表的颜色,转换成RGB用于绘制 */
    126                 cvSet2D(hsv_color,0,0,cvScalar(h*180.f / h_bins,s*255.f/s_bins,v*255.f/v_bins,0));//获得一幅临时HSV图像
    127                 cvCvtColor(hsv_color,rgb_color,CV_HSV2BGR);//转换为RGB
    128                 CvScalar color = cvGet2D(rgb_color,0,0);//再从RGB中提取出色彩通道用于绘制
    129  
    130                 cvRectangle( frame_hist, cvPoint(i*bin_w,height),
    131                             cvPoint((i+1)*bin_w,height - intensity),
    132                              color, -1, 8, 0 );
    133             }
    134         }
    135     }
    136  
    137     cvNamedWindow( "Source", 1 );
    138     cvShowImage( "Source", frame );
    139 
    140 
    141 
    142 }
    143  
    144 void main(int argc, char** argv)
    145 {
    146     
    147     //载入文件
    148         char name[40];
    149         cout<<"输入文件";
    150         cin>>name;
    151 
    152     //建立窗口
    153         cvNamedWindow("camera",CV_WINDOW_AUTOSIZE);//显示视频原图像的窗口
    154     //载入第一帧
    155         capture=cvCreateFileCapture(name);
    156          frame=cvQueryFrame(capture);
    157     //捕捉鼠标
    158          setMouseCallback("camera",onMouse,0);
    159 
    160     //进入视频循环
    161         for(;;)
    162         {
    163             frame=cvQueryFrame(capture);
    164             if(!frame)break;
    165 
    166             if(object==0)//初运行程序,进行初始化
    167             {
    168                 frame_hsv=cvCreateImage(cvGetSize(frame),8,3);
    169                 frame_h  =cvCreateImage(cvGetSize(frame),8,1);
    170                 frame_s  =cvCreateImage(cvGetSize(frame),8,1);
    171                 frame_v  =cvCreateImage(cvGetSize(frame),8,1);
    172                 backproject=cvCreateImage(cvGetSize(frame),8,1);
    173                 mask=cvCreateImage(cvGetSize(frame),8,1);
    174 
    175                 //初始化完毕,标志置1
    176                 object=-2;
    177             }
    178             
    179 
    180                 
    181             //如果没有进行特征提取,进行特征提取
    182             if(object==1)
    183             {
    184 
    185                 histogram = cvCreateHist( 3,hist_size, CV_HIST_ARRAY, ranges, 1 );
    186                 
    187 
    188                 CalDrawHist();
    189 
    190 
    191                 //特征提取完毕,置标志位1
    192                 object=-1;
    193             }
    194 
    195             //如果已经特征处理,则进行camshift
    196              if(object==-1)
    197             {
    198             //计算直方图反向投影
    199             cvCalcBackProject(planes,backproject,histogram);
    200             cvAnd(backproject,mask,backproject,0);
    201 
    202             //camshift
    203              cvCamShift(backproject, track_window,cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),&track_comp, &box );
    204             
    205             //设置下一帧track_window
    206             track_comp.rect.height=abs(track_comp.rect.height);
    207             track_comp.rect.width=abs(track_comp.rect.width);
    208             track_window=track_comp.rect;
    209             
    210             cvEllipseBox(frame,box, CV_RGB(255,0,0), 3, CV_AA, 0 );
    211             
    212             }
    213             
    214             
    215              cvShowImage("camera1",backproject);
    216              cvShowImage("camera",frame);
    217 
    218             //如果鼠标按下,则绘出鼠标画出的矩
    219                 if(select_flag)
    220                 {
    221                     frame=cvQueryFrame(capture);
    222                     if(!frame)break;
    223                     cvRectangleR(frame,select,Scalar(225,0,0),2,8,0);
    224                     cvShowImage("camera",frame);
    225                 }
    226 
    227             //退出功能
    228             if(cvWaitKey(50)==27)break;
    229             if(!frame)break;
    230         }
    231         
    232         //程序结束,各种release
    233         cvDestroyAllWindows();
    234 
    235         cvReleaseCapture(&capture);
    236         cvReleaseImage(&frame_hsv);
    237         cvReleaseImage(&frame_h);
    238         cvReleaseImage(&frame_s);
    239 
    240 
    241 
    242 }
  • 相关阅读:
    【Java学习笔记】java.lang包学习
    winform的md5加密
    地铁线路图的设计与实现
    asp.net的jQuery 表格展开伸缩
    关于批量数据更新的问题(C#高性能)
    JQuery用户名无刷新验证
    Linq分页
    用jQuery写的好的动态显示本机时间的代码
    asp.net防止页面刷新弹出“需要重新发送您以前提交的信息”
    aspx中的html代码调用CS文件中的方法
  • 原文地址:https://www.cnblogs.com/Ponys/p/3045370.html
Copyright © 2011-2022 走看看