困扰我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 }

 

posted @ 2013-04-26 17:48  Pony_s  阅读(507)  评论(0编辑  收藏  举报