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;
}