OpenCV直方图计算学习
环境:Visual studio 2012 + opencv 2.4.5
统计彩色图像的指定区域的rgb通道的直方图分布
// HistogramCalculate.cpp : 定义控制台应用程序的入口点。
//计算给定图像区域的直方图
#include "stdafx.h"
#include
#include
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
string filename = "meinv1.jpg";
string winname = "MainWindow";
namedWindow(winname,1);
Mat src, dst;//声明原始图像和目标图像
/// 装载图像
src = imread( filename, 1 );
if( !src.data ) //判断图像是否成功读取
{ return -1; }
///显示读入的图像
imshow(winname,src);
///将原图像分割成三个单通道图像
vector
rgb_planes; //图像数组
//给定图像中的某个矩形区域
Rect roi(0,0,src.cols,src.rows);
dst = src(roi);//提取矩形区域中的图像块
split(dst,rgb_planes);//split函数将三通道图像分割成单通道图像
//设定直方图中bin的数目
int histSize = 128;
//设定取值范围
float range[] = {0,256};//R、G、B三个特征的范围都是0到255
const float* histRange = {range};
bool uniform = true; bool accumulate = false;//均匀分布,无累加
Mat r_hist, g_hist, b_hist; //直方图
///计算直方图
calcHist(&rgb_planes[0],1,0,Mat(),r_hist,1,&histSize,&histRange,uniform,accumulate);
calcHist(&rgb_planes[1],1,0,Mat(),g_hist,1,&histSize,&histRange,uniform,accumulate);
calcHist(&rgb_planes[2],1,0,Mat(),b_hist,1,&histSize,&histRange,uniform,accumulate);
// 创建直方图画布
int hist_w = 400; int hist_h = 400;//直方图图像的宽度和高度
int bin_w = cvRound( (double) hist_w/histSize );//直方图中一个矩形条纹的宽度
Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );//创建画布图像
/// 将直方图归一化到范围 [ 0, histImage.rows ]
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
/// 在直方图画布上画出直方图
for(int i=1;i<=histSize;i++)
{
//矩形图表示
rectangle( histImage,Point((i-1)*bin_w,hist_h),Point(i*bin_w,hist_h-cvRound(r_hist.at
(i-1))),Scalar(0,0,255),1,8,0);
rectangle( histImage,Point((i-1)*bin_w,hist_h),Point(i*bin_w,hist_h-cvRound(g_hist.at
(i-1))),Scalar(0,255,0),1,8,0); rectangle( histImage,Point((i-1)*bin_w,hist_h),Point(i*bin_w,hist_h-cvRound(b_hist.at
(i-1))),Scalar(255,0,0),1,8,0); //折线表示 line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at
(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(r_hist.at
(i)) ), Scalar( 0, 0, 255), 1, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at
(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(g_hist.at
(i)) ), Scalar( 0, 255, 0), 1, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at
(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(b_hist.at
(i)) ), Scalar( 255, 0, 0), 1, 8, 0 ); } /// 显示直方图 namedWindow("calcHist Demo",0); imshow("calcHist Demo", histImage ); waitKey(0); return 0; }
下面的程序用了inRange函数,生成mask模板将r,g,b值限制在某一个区间内,然后调用calcHist函数
// HistogramCalculate2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
string filename = "E:\\素材\\flower1.jpg";
string winname = "MainWindow";
namedWindow(winname,1);
Mat src, dst;//声明原始图像和目标图像
/// 装载图像
src = imread( filename, 1 );
if( !src.data ) //判断图像是否成功读取
{ return -1; }
///显示读入的图像
imshow(winname,src);
///将原图像分割成三个单通道图像
vector
rgb_planes; //图像数组
split(src,rgb_planes);//split函数将三通道图像分割成单通道图像
//将数值低于min大于max的像素点排除在统计之外
int r_min = 10,r_max = 256; //红色通道的统计范围
int g_min = 20,g_max = 256; //绿色通道的统计范围
int b_min = 30,b_max = 256; //蓝色通道的统计范围
Mat red_mask,green_mask,blue_mask,mask;
//调用inRange函数生成掩膜矩阵
inRange(rgb_planes[0],r_min,r_max,red_mask);
//cvtColor(red_mask,mask,CV_GRAY2RGB); imshow("red mask",red_mask);waitKey(0);
inRange(rgb_planes[1],g_min,g_max,green_mask);
//cvtColor(green_mask,mask,CV_GRAY2RGB); imshow("green mask",green_mask);waitKey(0);
inRange(rgb_planes[2],b_min,b_max,blue_mask);
//cvtColor(blue_mask,mask,CV_GRAY2RGB); imshow("blue mask",blue_mask);waitKey(0);
//设定直方图中bin的数目
int histSize = 256;
//设定取值范围
float range[] = {0,256};//R、G、B三个特征的范围都是0到255
const float* histRange = {range};
bool uniform = true; bool accumulate = false;//均匀分布,无累加
Mat r_hist, g_hist, b_hist; //直方图
///计算直方图
calcHist(&rgb_planes[0],1,0,red_mask,r_hist,1,&histSize,&histRange,uniform,accumulate);
calcHist(&rgb_planes[1],1,0,green_mask,g_hist,1,&histSize,&histRange,uniform,accumulate);
calcHist(&rgb_planes[2],1,0,blue_mask,b_hist,1,&histSize,&histRange,uniform,accumulate);
// 创建直方图画布
int hist_w = 400; int hist_h = 400;//直方图图像的宽度和高度
int bin_w = cvRound( (double) hist_w/histSize );//直方图中一个矩形条纹的宽度
Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );//创建画布图像
/// 将直方图归一化到范围 [ 0, histImage.rows ]
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
/// 在直方图画布上画出直方图
for(int i=1;i<=histSize;i++)
{
//矩形图表示
/*rectangle( histImage,Point((i-1)*bin_w,hist_h),Point(i*bin_w,hist_h-cvRound(r_hist.at
(i-1))),Scalar(0,0,255),1,8,0);
rectangle( histImage,Point((i-1)*bin_w,hist_h),Point(i*bin_w,hist_h-cvRound(g_hist.at
(i-1))),Scalar(0,255,0),1,8,0); rectangle( histImage,Point((i-1)*bin_w,hist_h),Point(i*bin_w,hist_h-cvRound(b_hist.at
(i-1))),Scalar(255,0,0),1,8,0);*/ //折线表示 line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at
(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(r_hist.at
(i)) ), Scalar( 0, 0, 255), 1, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at
(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(g_hist.at
(i)) ), Scalar( 0, 255, 0), 1, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at
(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(b_hist.at
(i)) ), Scalar( 255, 0, 0), 1, 8, 0 ); } /// 显示直方图 namedWindow("calcHist Demo",0); imshow("calcHist Demo", histImage ); waitKey(0); return 0; }
运行结果:
由于代码段
的作用,使得RGB各个通道的直方图起始位置各不相同//将数值低于min大于max的像素点排除在统计之外int r_min = 10 , r_max = 256 ; //红色通道的统计范围int g_min = 20 , g_max = 256 ; //绿色通道的统计范围int b_min = 30 , b_max = 256 ; //蓝色通道的统计范围Mat red_mask , green_mask , blue_mask , mask ;//调用inRange函数生成掩膜矩阵inRange ( rgb_planes [ 0 ], r_min , r_max , red_mask );//cvtColor(red_mask,mask,CV_GRAY2RGB); imshow("red mask",red_mask);waitKey(0);inRange ( rgb_planes [ 1 ], g_min , g_max , green_mask );//cvtColor(green_mask,mask,CV_GRAY2RGB); imshow("green mask",green_mask);waitKey(0);inRange ( rgb_planes [ 2 ], b_min , b_max , blue_mask );//cvtColor(blue_mask,mask,CV_GRAY2RGB); imshow("blue mask",blue_mask);waitKey(0);