汽车颜色识别--HSV空间

// color recognition.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include "cv.h"
#include <math.h>
#include "color module.h"

using namespace cv;    
using namespace std;

Rect r;   //存储车牌位置
CvPoint origin;
IplImage* image=NULL;
int mark = 0;  //选择ROI标志  

void on_mouse( int event, int x, int y, int flags, void* zhang )
{
 if( !image )
  return;
 CvPoint pt;
 if( event == CV_EVENT_LBUTTONDOWN ) //开始点击选择跟踪物体
 {
  origin = cvPoint( x,y );
     r = cvRect( x,y,0,0 );//坐标
  r.x = MIN( x,origin.x );
  r.y = MIN( y,origin.y );
  r.width = r.x + CV_IABS( x - origin.x );
  r.height = r.y + CV_IABS( y - origin.y );

  r.x = MAX( r.x, 0 );
  r.y = MAX( r.y, 0 );
  r.width = MIN( r.width, image->width );
  r.height = MIN( r.height, image->height );
  r.width -= r.x;
  r.height -= r.y;
  
 }

  if( event == CV_EVENT_LBUTTONUP )
  {
    pt = cvPoint( x,y );
    mark = -1;
       r.width = pt.x - r.x;
       r.height = pt.y - r.y;
  }

}
/*************************************************************************
 * 函数名称:
 *   Color_difference_HSV()
 * 参数:
 *   IplImage* car       - 输入原图像
 *   Rect r              - 源图像中划出的颜色识别区域
 * 返回值:
 *   int* type           - 指向颜色类型值,返回类型参数
 * 说明:
 *   该函数用来对图像进行颜色匹配识别。
 ************************************************************************/
int Color_difference_HSV( cv::Mat car, Rect r)
{
 int type = 0;
 //复制ROI区域图像
 if ( r.width==0 || r.height==0 )
 {
  return -1;
 }
 cv::Mat roiImage = cvCreateImage(cvSize(r.width, r.height), 8, 3 );
 car(r).copyTo(roiImage); 

 float hranges_arr[] = {0,180};//像素值的范围
 float* hranges = hranges_arr;//用于初始化CvHistogram类

 IplImage* roi = &roiImage.operator IplImage();  
 IplImage* hsv = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 3);//用于存图像的一个中间变量,是用来分通道用的,分成hsv通道  
 IplImage* h_plane = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);  
 IplImage* s_plane = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);  
 IplImage* v_plane = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);    
 IplImage* planes[] = { h_plane, s_plane };
 IplImage* src_tmp1=cvCreateImage(cvGetSize(roi),8,3);  
 
 /** H 分量划分为16个等级,S分量划分为8个等级 */
 int h_bins = 15, s_bins = 8, v_bins = 8;
 int hist_size[] = {h_bins, s_bins};

 /** H 分量的变化范围 */
 float h_range[] = { 0, 180 };

 /** S 分量的变化范围*/
 float s_range[] = { 0, 255 };
 float* ranges[] = { h_range, s_range };

 float* h_ranges[] = { h_range };
 float* s_ranges[] = { s_range };

 /** 输入图像转换到HSV颜色空间 */
 cvCvtColor( roi, hsv, CV_BGR2HSV );
 cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );
 /** 创建直方图,二维, 每个维度上均分 */
 CvHistogram * hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 );
 
 增加部分/
 CvHistogram* h_hist = cvCreateHist(1,&h_bins,CV_HIST_ARRAY,h_ranges,1);
 CvHistogram* s_hist = cvCreateHist(1,&s_bins,CV_HIST_ARRAY,s_ranges,1);
 CvHistogram* v_hist = cvCreateHist(1,&v_bins,CV_HIST_ARRAY,ranges,1);


 /** 根据H,S两个平面数据统计直方图 */
 cvCalcHist( planes, hist, 0, 0 );

 //增加部分//
    cvCalcHist( &h_plane, h_hist, 0, 0 );  //统计H方向直方图
 cvCalcHist( &s_plane, s_hist, 0, 0 ); //统计S方向直方图
 cvCalcHist( &v_plane, v_hist, 0, 0 ); //统计v方向直方图

 /** 获取直方图统计的最大值,用于动态显示直方图 */
 float max_value,hmax,smax,vmax;
 cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 );
 cvGetMinMaxHistValue( h_hist, 0, &hmax, 0, 0 );
 cvGetMinMaxHistValue( s_hist, 0, &smax, 0, 0 );
 cvGetMinMaxHistValue( v_hist, 0, &vmax, 0, 0 );


 /** 设置直方图显示图像 */
 int height = 240;
 int width = (h_bins*s_bins*6);
 IplImage* hist_img = cvCreateImage( cvSize(width,height), 8, 3 );
 cvZero( hist_img );

 /** 用来进行HSV到RGB颜色转换的临时单位图像 */
 IplImage * hsv_color = cvCreateImage(cvSize(1,1),8,3);
 IplImage * rgb_color = cvCreateImage(cvSize(1,1),8,3);
 int bin_w = width / (h_bins * s_bins);
 int n = 0;
 
 //显示一:综合H,S显示直方图,宽为h_bins*s_bins,并显示相应直方图颜色//

 for(int h = 0; h < h_bins; h++)
 {
  for(int s = 0; s < s_bins; s++)
  {
   int i = h*s_bins + s;
   /** 获得直方图中的统计次数,计算显示在图像中的高度 */
   float bin_val = cvQueryHistValue_2D( hist, h, s );
   int intensity = cvRound(bin_val*height/max_value);  //转化为在显示直方图上的合适高度
   cout<<intensity<<endl;

   /** 获得当前直方图代表的颜色,转换成RGB用于绘制 */
   cvSet2D(hsv_color,0,0,cvScalar(h*180.f / h_bins,s*255.f/s_bins,255,0));
   cvCvtColor(hsv_color,rgb_color,CV_HSV2BGR);
   CvScalar color = cvGet2D(rgb_color,0,0);

   cvRectangle( hist_img, cvPoint(i*bin_w,height),
    cvPoint((i+1)*bin_w,height - intensity),
    color, -1, 8, 0 );
   n++;   
  }
 }
 cout<<n<<endl;

   //
   //显示二: 分别显示H、S、V三通道直方图/
 
 int hist_height = 100;//显示直方图高度
 int hist_width = 150;
 IplImage* hist_image = cvCreateImage( cvSize(hist_width,hist_height*3),8,3 );
 float hidx=0,sidx=0,vidx=0; //保存最高峰值的元素值
 for(int i = 0;i < h_bins; i++)
 {
  float bin_val = cvQueryHistValue_1D(h_hist,i);
  int intensity = cvRound(bin_val*hist_height/hmax); 
  int hbin_w = hist_width/h_bins;
  cvRectangle(hist_image,cvPoint(i*hbin_w,hist_height),cvPoint((i+1)*hbin_w - 1, hist_height - intensity),CV_RGB(0,255,0));
  float k = i*180.f/h_bins;
  if (hmax<=bin_val)
  {
   hmax = bin_val;
   hidx = k;
  }  
 }
 cout<<"统计出现最多H的次数:"<<hmax<<" ,H元素的值为:"<<hidx<<endl;

 for(int i = 0;i < s_bins; i++)
 {
  float bin_val = cvQueryHistValue_1D(s_hist,i);
  int intensity = cvRound(bin_val*hist_height/smax); 
  int sbin_w = hist_width/s_bins;
  cvRectangle(hist_image,cvPoint(i*sbin_w,2*hist_height),cvPoint((i+1)*sbin_w - 1, 2*hist_height - intensity),CV_RGB(0,255,0));
  float k = i*255.f/s_bins;
  if (smax<=bin_val)
  {
   smax = bin_val;
   sidx = k;
  }  
 }
 cout<<"统计出现最多S的次数:"<<smax<<" ,S元素的值为:"<<sidx<<endl;

 for(int i = 0;i < v_bins; i++)
 {
  float bin_val = cvQueryHistValue_1D(v_hist,i);
  int intensity = cvRound(bin_val*hist_height/vmax); 
  int vbin_w = hist_width/v_bins;
  cvRectangle(hist_image,cvPoint(i*vbin_w,3*hist_height),cvPoint((i+1)*vbin_w - 1, 3*hist_height - intensity),CV_RGB(0,255,0));
  float k = i*255.f/v_bins;
  if (vmax<=bin_val)
  {
   vmax = bin_val;
   vidx = k;
  }  
 }
 cout<<"统计出现最多V的次数:"<<vmax<<" ,V元素的值为:"<<vidx<<endl;

 cvNamedWindow( "Source", 1 );
 cvShowImage( "Source", roi );

 cvNamedWindow( "H-S Histogram", 1 );
 cvShowImage( "H-S Histogram", hist_img );

 cvNamedWindow( "H-S-V Histogram", 1 );
 cvShowImage( "H-S-V Histogram", hist_image );
 
 cvReleaseImage(&hsv);
 cvDestroyWindow("hsv"); 
 cvReleaseImage(&h_plane);  
 cvReleaseImage(&s_plane);  
 cvReleaseImage(&v_plane);  
 cvReleaseImage(&src_tmp1);
   return type;
}

int Color_difference_RGB( cv::Mat car, Rect r )
{
 int type = 0;
 //复制ROI区域图像
 if ( r.width==0 || r.height==0 )
 {
  return -1;
 }
 cv::Mat roiImage = cvCreateImage( cvSize(r.width, r.height), 8, 3 );
 car(r).copyTo(roiImage); 

 IplImage* roi = &roiImage.operator IplImage();  
   IplImage* R = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);  
 IplImage* G = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);  
 IplImage* B = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);      
  
 // 高斯模糊  
 //cvSmooth(roi,roi,CV_GAUSSIAN,3,3); //高斯模糊 ,作用   
 cvCvtPixToPlane(roi,B,G,R,0);//分为3个通道,OpenCV中不管是Windows中Load的还是摄像头取得的都是BGR顺序排列的
 
 cvShowImage("R",R);
 cvShowImage("hsv",roi); 
 cvShowImage("G",G);
 cvShowImage("B",B);
 
 //为这四幅图创建对应的直方图结构。
 int hist_size = 28; //划分bin的个数
 int hist_height = 100;
 float range[] = {0,256};
 float* ranges[]={range};
 CvHistogram* r_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
 CvHistogram* g_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
 CvHistogram* b_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
 
 //计算直方图,创建用于显示直方图的图像
 cvCalcHist( &R, r_hist, 0, 0 );
 cvCalcHist( &G, g_hist, 0, 0 );
 cvCalcHist( &B, b_hist, 0, 0 );
 cvNormalizeHist(r_hist,1.0);
 cvNormalizeHist(g_hist,1.0);
 cvNormalizeHist(b_hist,1.0);
 
 //开始显示,这里对直方图进行了标准化处理,不然的话无法观察到明显的变化
 int scale = 256/hist_size;
 IplImage* hist_image = cvCreateImage( cvSize(hist_size*scale,hist_height*3),8,3 );
 cvZero(hist_image);
 float bmax_value = 0,rmax_value=0,gmax_value=0;
 float min_value; 
 int rmin_idx, rmax_idx,gmin_idx, gmax_idx,bmin_idx,bmax_idx; 
 float rmax=0,gmax=0,bmax=0; //保存最高峰值
 float ridx=0,gidx=0,bidx=0; //保存最高峰值的元素值

 cvGetMinMaxHistValue( r_hist, 0,&rmax_value,0,&rmax_idx );
 cvGetMinMaxHistValue(g_hist, 0,&gmax_value,0,0);
 cvGetMinMaxHistValue(b_hist, 0,&bmax_value,0,0);
 //cout<<"R最大值"<<(1-rmax_value)*255<<" "<<rmax_idx<<",G最大值"<<(1-gmax_value)*255<<",B最大值"<<(1-bmax_value)*255<<endl; 
 
  for(int i=0;i<hist_size;i++)
 {
  float bin_val = cvQueryHistValue_1D(r_hist,i);//返回相应bin中的统计值
  int intensity = cvRound(bin_val*hist_height/rmax_value);
  cvRectangle(hist_image,cvPoint(i*scale,hist_height),cvPoint((i+1)*scale - 1, hist_height - intensity),CV_RGB(255,0,0));  
  float k = (i+1)*255.f/hist_size;
  if (rmax<bin_val)
  {
   rmax = bin_val;
   ridx = k;
  }
 }
  cout<<rmax<<" "<<ridx<<endl;
 for(int i=0;i<hist_size;i++)
 {
  float bin_val = cvQueryHistValue_1D(g_hist,i);
  int intensity = cvRound(bin_val*hist_height/gmax_value); 
  cvRectangle(hist_image,cvPoint(i*scale,2*hist_height),cvPoint((i+1)*scale - 1, 2*hist_height - intensity),CV_RGB(0,255,0));
  float k = i*255.f/hist_size;
  if (gmax<bin_val)
  {
   gmax = bin_val;
   gidx = k;
  }  
 }
 cout<<gmax<<" "<<gidx<<endl;
 for(int i=0;i<hist_size;i++)
 {
  float bin_val = cvQueryHistValue_1D(b_hist,i);
  int intensity = cvRound(bin_val*hist_height/bmax_value);
        cvRectangle(hist_image,cvPoint(i*scale,3*hist_height),cvPoint((i+1)*scale - 1, 3*hist_height - intensity),CV_RGB(0,0,255));
  float k = i*255.f/hist_size;
  if (bmax<bin_val)
  {
   bmax = bin_val;
   bidx = k;
  }
 }
 cout<<bmax<<" "<<bidx<<endl;
 cvShowImage("ZHIFANGTUr",hist_image);

 //颜色判断及匹配
 float velue[] = {ridx,gidx,bidx};
 float dmin = 100000; //保存最小的距离
 int colorIdx = 0;
 for(int i=0 ; i <N ; i++)
 {
       float d = sqrt(pow(colorVelue[i][0]-velue[0],2)+pow(colorVelue[i][1]-velue[1],2)+pow(colorVelue[i][2]-velue[2],2));
   if (dmin > d)
   {
            dmin = d;
         colorIdx = i;
   }
 }
  cout<<"colorIdx:"<<colorIdx<<endl;
 if (( ridx>150 )&&( ridx<200 )&&( gidx>150 )&&( gidx < 200 )&&(bidx>150)&&(bidx<200)&&
  abs(ridx-gidx)<30&&abs(ridx-bidx)<30&&(gidx-bidx)<30)
 {
    type =  10;
 }
 else if (( ridx>0 )&&( ridx<150 )&&( gidx>0 )&&( gidx < 150 )&&(bidx>0)&&(bidx<150)&&
  abs(ridx-gidx)<30&&abs(ridx-bidx)<30&&(gidx-bidx)<30)
 {
  type =  0;
 }
 else if (( ridx>200 )&&( gidx>200 )&&(bidx>200)&&
  abs(ridx-gidx)<30&&abs(ridx-bidx)<30&&(gidx-bidx)<30)
 {
  type = 1 ;
 }
 else
  type = colorIdx;

 //cvDestroyWindow("hsv");
 cvReleaseImage(&R);  
 cvReleaseImage(&G);  
 cvReleaseImage(&B);
 cvReleaseImage(&hist_image);
 cvReleaseHist(&r_hist);
 cvReleaseHist(&g_hist);
 cvReleaseHist(&b_hist);
   return type;
}

int main(int argc, _TCHAR* argv[])
{
 cvNamedWindow( "color recognition", 1 ); //建立视频窗口
 IplImage* src = cvLoadImage( "D:\\tu\\2005422443840696.jpg" ); 
 float scale = 0.5;
 
 CvSize img_cvsize;
 img_cvsize.width = src->width * scale;
 img_cvsize.height = src->height * scale;
 image = cvCreateImage( img_cvsize,src->depth,src->nChannels );
 
 //读图像//
 //image = cvCreateImage( cvGetSize(src), 8, 3 );
 cvResize(src,image,CV_INTER_LINEAR);
 cvShowImage( "color recognition", image );//显示视频和直方图
 cvWaitKey(1000);
 cvSetMouseCallback( "color recognition", on_mouse ); // 设置鼠标回调函数 
 
 //车牌区域选择函数// 
 for ( int i=0;i<4;i++ )
 {
  if ( mark )
    {
     cout<<"区域坐标:"<<"x:"<<r.x<<", y:"<<r.y<<", width:"<<r.width<<", height:"<<r.height<<endl;
     cout<<"ok"<<endl;
    } 
 cvWaitKey(1000);
 cvRectangle( image,cvPoint( r.x,r.y ),cvPoint( r.x+r.width,r.y+r.height ),cvScalar(255,0,255) ,2, 8, 0);
 cvShowImage( "color recognition", image );
  
 }
 cvShowImage( "color recognition", image );
 cout<<"selection is ok"<<endl;
    //cvWaitKey(0);
 
    //颜色匹配识别// 
 int j;
 //j = Color_difference_RGB(image,r);  //返回颜色类型
 j = Color_difference_HSV(image,r);
 cout<<"j:"<<j<<endl;
 switch (j)
 {
     case -1:
      cout<<"please select ROI first!"<<endl;
  break;
     case 0:
         cout<<"the colorof this car is:黑"<<endl;
      break;
  case 1:
   cout<<"the colorof thiscar is:白"<<endl;
   break;
  case 2:
   cout<<"the colorof thiscar is:红"<<endl;
   break;
  case 3:
   cout<<"the colorof thiscar is:红"<<endl;
   break;
  case 4:
   cout<<"the colorof thiscar is:绿"<<endl;
   break;
  case 5:
   cout<<"the colorof thiscar is:绿"<<endl;
   break;
  case 6:
   cout<<"the colorof thiscar is:蓝"<<endl;
   break;
  case 7:
   cout<<"the colorof thiscar is:蓝"<<endl;
   break;
  case 8:
   cout<<"the colorof thiscar is:黄"<<endl;
   break;
  case 9:
   cout<<"the colorof thiscar is:黄"<<endl;
   break;
     case 10 :
     cout<<"the colorof thiscar is:灰"<<endl;
     break;
  default:
     cout<<"the colorof thiscar is:其他"<<endl;
 }
     cvWaitKey(0); 
 cvReleaseImage(&image);
 cvReleaseImage(&src);
 cvDestroyWindow("color recognition");
 return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值