我们在处理彩色图像时。特别是在做局部图像的阈值切割时,须要一个直观的RGB统计图。
接下来開始实现。
代码:
void CalcHistRGB()
{
IplImage* img_source;
if (img_source = cvLoadImage("101.jpg",1))
{
IplImage* RedChannel = cvCreateImage( cvGetSize(img_source), 8, 1);
IplImage* GreenChannel = cvCreateImage( cvGetSize(img_source), 8, 1);
IplImage* BlueChannel = cvCreateImage( cvGetSize(img_source), 8, 1);
IplImage* alphaChannel = cvCreateImage( cvGetSize(img_source), 8, 1);
IplImage* gray_plane = cvCreateImage(cvGetSize(img_source),8,1);
//切割为单通道图像
cvSplit(img_source,BlueChannel,GreenChannel,RedChannel,0);
// 显示图像
cvNamedWindow( "RedChannel", 1 );
cvNamedWindow( "GreenChannel", 1 );
cvNamedWindow( "BlueChannel", 1 );
cvNamedWindow( "lphaChannel", 1 );
cvShowImage( "RedChannel", RedChannel );
cvShowImage( "GreenChannel", GreenChannel );
cvShowImage( "BlueChannel", BlueChannel );
cvShowImage( "lphaChannel", alphaChannel );
cvCvtColor(img_source,gray_plane,CV_BGR2GRAY);
cvNamedWindow("GrayPlane",1);
cvShowImage("GrayPlane",gray_plane);
//OpenCV中无论是Windows中Load的还是摄像头取得的都是BGR顺序排列的
//然后为这四幅图创建相应的直方图结构。
int hist_size = 100;
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);
CvHistogram* gray_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
//接下来计算直方图,创建用于显示直方图的图像,略去了一部分反复代码,下面也是
cvCalcHist(&RedChannel,r_hist,0,0);
cvCalcHist(&GreenChannel,g_hist,0,0);
cvCalcHist(&BlueChannel,b_hist,0,0);
cvCalcHist(&gray_plane,gray_hist,0,0);
cvNormalizeHist(gray_hist,1.0);
cvNormalizeHist(r_hist,1.0);
cvNormalizeHist(g_hist,1.0);
cvNormalizeHist(b_hist,1.0);
int scale = 2;
IplImage* hist_image = cvCreateImage(cvSize(hist_size*scale,hist_height*4),8,3);
cvZero(hist_image);
//然后開始显示,这里对直方图进行了标准化处理。不然的话无法观察到明显的变化。
float r_max_value = 0;
float g_max_value = 0;
float b_max_value = 0;
float gray_max_value = 0;
cvGetMinMaxHistValue(r_hist, 0,&r_max_value,0,0);
cvGetMinMaxHistValue(g_hist, 0,&g_max_value,0,0);
cvGetMinMaxHistValue(b_hist, 0,&b_max_value,0,0);
cvGetMinMaxHistValue(b_hist, 0,&gray_max_value,0,0);
for(int i=0;i<hist_size;i++)
{
float r_bin_val = cvQueryHistValue_1D(r_hist,i);
int r_intensity = cvRound(r_bin_val*hist_height/r_max_value);
cvRectangle(
hist_image,
cvPoint(i*scale,hist_height-1),
cvPoint((i+1)*scale - 1, hist_height - r_intensity),
CV_RGB(255,0,0));
float g_bin_val=cvQueryHistValue_1D(g_hist,i);
int g_intensity = cvRound(g_bin_val*hist_height/g_max_value);
cvRectangle(
hist_image,
cvPoint(i*scale,2*hist_height-1),
cvPoint((i+1)*scale - 1, 2*hist_height - g_intensity),
CV_RGB(0,255,0));
float b_bin_val = cvQueryHistValue_1D(b_hist,i);
int b_intensity = cvRound(b_bin_val*hist_height/b_max_value);
cvRectangle(
hist_image,
cvPoint(i*scale,3*hist_height-1),
cvPoint((i+1)*scale - 1, 3*hist_height - b_intensity),
CV_RGB(0,0,255));
float gray_bin_val = cvQueryHistValue_1D(gray_hist,i);
int gray_intensity = cvRound(gray_bin_val*hist_height/gray_max_value);
cvRectangle(
hist_image,
cvPoint(i*scale,4*hist_height-1),
cvPoint((i+1)*scale - 1, 4*hist_height - gray_intensity),
CV_RGB(100,100,100));
}
cvNamedWindow( "Source", 1 );
cvShowImage( "Source", img_source );
cvNamedWindow( "RGB_Histogram", 1 );
cvShowImage( "RGB_Histogram", hist_image );
}
}
计算结果例如以下: