程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 汽車顏色識別--更新版

汽車顏色識別--更新版

編輯:C++入門知識

1、該程序是基於同事車牌定位接口上進行的;

2、為調試程序,程序中設定了鼠標選擇圖片中特定區域來進行識別;

3、程序針對汽車顏色,一共8種顏色

PS:相比剛接觸opencv就接手的半死不活的行人檢測,這個算是稍稍給了些安慰O(∩_∩)O,繼續努力撒

 

// color recognition.cpp : 定義控制台應用程序的入口點。
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include "cv.h"
#include <math.h>

using namespace cv;    
using namespace std;


Rect r;   //存儲車牌位置
CvPoint origin;
IplImage* image=NULL;
int mark = 0;  //選擇ROI標志
#define  N  12 //顏色模板的個數

// 顏色模板
//  黑、白、紅、綠、藍、黃/ 棕 、灰
#define  BLACK   0
#define  WHITE   1
#define  RED1     2
#define  RED2     3
#define  GREEN1   4
#define  GREEN2   5
#define  BLUE1    6
#define  BLUE2    7
#define  YELLOW1  8
#define  YELLOW2  9
#define  BROWN    10
#define  GRAY     11

int colorVelue[N][3]  = {{50,50,50},    //黑
      {255,255,255},  //白
      {240,80,80}, //紅小
      {240,160,160},  //紅大
      {60,180,60}, //綠小
      {160,240,160},  //綠大
      {80,80,240}, //藍小
         {160,160,240},  //藍大
      {240,190,80}, //黃小
      {240,240,160},  //黃大
      {205,133,63}};   //棕/褐
      //{162,162,162},//灰,特殊
 

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()
 * 參數:
 *   IplImage* car       - 輸入原圖像
 *   Rect r              - 源圖像中劃出的顏色識別區域
 * 返回值:
 *   int* type           - 指向顏色類型值,返回類型參數
 * 說明:
 *   該函數用來對圖像進行顏色匹配識別。
 ************************************************************************/
//int Color_difference_HSV( cv::Mat car, Rect r,int* type)
//{
// //復制ROI區域圖像
// cv::Mat roiImage = cvCreateImage(cvSize(r.width, r.height), 8, 3 );
// car(r).copyTo(roiImage); 
// //
// /*cv::imshow("roi", roiImage); 
// cv::waitKey(0); */
// //
// int hdims = 5; // 劃分直方圖bins的個數,越多越精確
// 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* tmpH1 = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);//通道的中間變量,用於膚色檢測的中間變量 
// IplImage* tmpS1 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);  
// IplImage* tmpH2 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);  
// IplImage* tmpS2 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);  
// IplImage* tmpH3 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);  
// IplImage* tmpS3 = cvCreateImage(cvGetSize(roi), IPL_DEPTH_8U, 1);  
// IplImage* H = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);  
// IplImage* S = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);  
// IplImage* V = cvCreateImage( cvGetSize(roi), IPL_DEPTH_8U, 1);    
// IplImage* src_tmp1=cvCreateImage(cvGetSize(roi),8,3);  
//
//
// //CvHistogram *hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); //分配建立直方圖空間
// //IplImage* mask = cvCreateImage( cvGetSize(hsv), 8, 1 );//分配掩膜圖像空間
// //IplImage* hue = cvCreateImage( cvGetSize(hsv), 8, 1 );
//
// // 高斯模糊  
// //cvSmooth(roi,src_tmp1,CV_GAUSSIAN,3,3); //高斯模糊  
//
// //// hue色度,saturation飽和度,value純度  
// //cvCvtColor(src_tmp1, hsv, CV_BGR2HSV );//顏色轉換  
// //cvCvtPixToPlane(hsv,H,S,V,0);//分為3個通道  
//
// //cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(20.0,0.0,0,0),tmpH1);  
// //cvInRangeS(S,cvScalar(75.0,0.0,0,0),cvScalar(200.0,0.0,0,0),tmpS1);  
// //cvAnd(tmpH1,tmpS1,tmpH1,0);  
//
//// cvCalcHist( &hue, hist, 0, mask ); // 計算直方圖
//
// if (1)
// {
//  float velue[] = {0,0,0};
//  float d = sqrt(pow(colorVelue[0][0]-velue[0],2)+pow(colorVelue[0][1]-velue[1],2)+pow(colorVelue[0][2]-velue[2],2));
// 
//  cout<<d<<endl;
//  *type = RED1;
// }
// cvNamedWindow( "hsv", 1 );
// cvShowImage("hsv",roi);
// //cvWaitKey(0);
//
// cvReleaseImage(&hsv);
// cvDestroyWindow("hsv");
// cvReleaseImage(&tmpH1);  
// cvReleaseImage(&tmpS1);  
// cvReleaseImage(&tmpH2);  
// cvReleaseImage(&tmpS2);  
// cvReleaseImage(&tmpH3);  
// cvReleaseImage(&tmpS3);  
// cvReleaseImage(&H);  
// cvReleaseImage(&S);  
// cvReleaseImage(&V);  
// 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,255};
 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>100 )&&( ridx<220 )&&( gidx>100 )&&( gidx < 220 )&&(bidx>100)&&(bidx<220)&&
  abs(ridx-gidx)<30&&abs(ridx-bidx)<30&&(gidx-bidx)<30)
 {
    type =  12;
 }
 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\\U17328_20091230235830314-2.jpg");
 
 //讀圖像//
 image = cvCreateImage( cvGetSize(src), 8, 3 );
 //cvCopy(src,image);

 cvResize(src,image);
 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(src,r);  //返回顏色類型
 cout<<"j:"<<j<<endl;
 switch (j)
 {
     case -1:
  cout<<"please select ROI first!"<<endl;
  break;
     case 0:
         cout<<"the colorof thiscar 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;
     case 11 :
     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;
}

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved