opencv彩色直方图

#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include <iostream> 
#include <stdio.h> 
using namespace std; 
using namespace cv; 
/// 调用OpenCV接口求彩色图像各个通道的直方图 
void CalcHist_OpenCV(const Mat * image,Mat & b_hist,Mat & g_hist,Mat &r_hist,int histSize) 

 vector<Mat> bgr_planes; //定于一个Mat向量 
 split( *image, bgr_planes ); //将彩色图像image中的三个通道分离后,分别保存至向量bgr_planes 
 float range[] = { 0, 256 } ; //设置直方图的统计范围为0到255 
 const float* histRange = { range }; 
 bool uniform = true; bool accumulate = false; 
 /// 计算B通道直方图 
 calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, 
accumulate ); 
 /// 计算G通道直方图 
 calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, 
accumulate ); 
 /// 计算R通道直方图 
 calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, 
accumulate ); 

/// 用自定义的方法统计彩色图像各个通道直方图 
void CalcHist_ColorImg(const Mat * image,Mat & b_hist,Mat & g_hist,Mat &r_hist,int histSize) 

 int nRows = image->rows; 
 int nCols = image->cols;  if (image->isContinuous())// 若图像数据是连续存放的,将所有图像数据当作一行数据看待 
 { 
  nCols *= nRows; 
  nRows = 1; 
 }  b_hist = Mat::zeros(1,histSize, CV_32F); // 定义存放b通道直方图的数据尺寸为:1*histSize  g_hist = Mat::zeros(1,histSize, CV_32F); // 定义存放g通道直方图的数据尺寸为:1*histSize  r_hist = Mat::zeros(1,histSize, CV_32F); // 定义存放r通道直方图的数据尺寸为:1*histSize 
 int i,j; 
 const uchar* p;  for( i = 0; i < nRows; ++i) //访问第i行像素 
 { 
  p = (*image).ptr<uchar>(i); // 得到第i行像素的首地址 
  for ( j = 0; j < nCols*3; j+=3) // 访问第i行第j列像素的值,每个像素有三个字节 
  { 
/// 根据特定通道的数值在对应直方图条目上加1 
   b_hist.at<float>(p[j]/(256/histSize)) ++;// p[j]为第i行第j列像素的b通道的值 
   g_hist.at<float>(p[j+1]/(256/histSize)) ++;// p[j+1]为第i行第j列像素的g通道的值 
   r_hist.at<float>(p[j+2]/(256/histSize)) ++;// p[j+2]为第i行第j列像素的r通道的值 
  } 
 } 

/// 重载自定义方法统计彩色图像各个通道的直方图 
void CalcHist_ColorImg(unsigned char data[],float b_hist[],float g_hist[],float r_hist[],int 
dataSize,int histSize) 

 int i; 
 memset(b_hist,0,histSize*sizeof(float)); //b通道直方图数据初始化为0 
 memset(g_hist,0,histSize*sizeof(float)); //g通道直方图数据初始化为0 
 memset(r_hist,0,histSize*sizeof(float)); //r通道直方图数据初始化为0 
 for(i=0;i<dataSize;i+=3) //访问第i个像素,一共dataSize/3个像素 
 { 
//根据第i个像素的值将对应通道直方图的对应条目的值加1 
  b_hist[data[i]/(256/histSize)] ++ ; // data[i]为第i个像素的b通道的值 
  g_hist[data[i+1]/(256/histSize)] ++ ; // data[i+1]为第i个像素的g通道的值 
  r_hist[data[i+2]/(256/histSize)] ++ ; // data[i+2]为第i个像素的r通道的值 
 } 

/// 图像绘制 
void DrawHist(const string& winname,Mat & b_hist,Mat & g_hist,Mat &r_hist,int histSize) 

 int hist_w = 512; int hist_h = 400; //设置显示的直方图图像的尺寸为512*400 
 int bin_w = cvRound( (double) hist_w/histSize ); //直方图每个条目的宽度 
 Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) ); //创建一个三通道8位图像 
/// 将三个直方图数据线性映射到[ 0, histImage.rows ]区间内,最小值映射为0,最大值映射为
//histImage.rows 
 normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); 
 normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); 
 normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); 
 for( int i = 1; i < histSize; i++ ) //绘制各个通道直方图的相邻两个柱状体最高点之间的连线 
 { 
  line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) , 
      Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ), 
      Scalar( 255, 0, 0), 2, 8, 0  ); 
  line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) , 
      Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ), 
      Scalar( 0, 255, 0), 2, 8, 0  ); 
  line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
 
      Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ), 
      Scalar( 0, 0, 255), 2, 8, 0  ); 
 } 
 /// Display 
 namedWindow(winname, CV_WINDOW_AUTOSIZE ); 
 imshow(winname, histImage ); 

int main( int argc, char** argv ) 

 Mat src, dst; 
 /// 载入图像,以灰度图像的方式载入 
 src = imread( argv[1], CV_LOAD_IMAGE_COLOR );  if( !src.data ) // 检查是否读文件成功 
 { return -1; } 
  
 int histSize = 256; //直方图条目为256 
 Mat b_hist, g_hist, r_hist; //定义Mat类型的三个直方图数据 
/// 用opencv的接口函数求直方图,然后绘制该直方图 
 CalcHist_OpenCV(&src,b_hist,g_hist,r_hist,histSize); 
 DrawHist("calcColorImgHistogram1",b_hist,g_hist,r_hist,histSize); 
 /// 用自定义的彩色图像三个通道直方图统计函数求直方图,然后绘制该直方图 
 CalcHist_ColorImg(&src,b_hist,g_hist,r_hist,histSize); 
 DrawHist("calcColorImgHistogram2",b_hist,g_hist,r_hist,histSize); 
 /// 用另外一种自定义的彩色图像三个通道直方图统计函数求直方图,然后绘制该直方图 
 if (src.isContinuous())// 检查像素矩阵中的数据是否是连续存放的 
 { 
  b_hist = Mat::zeros(1,histSize, CV_32F); 
  g_hist = Mat::zeros(1,histSize, CV_32F); 
  r_hist = Mat::zeros(1,histSize, CV_32F); 
  CalcHist_ColorImg(src.data, 
(float*)(b_hist.data),(float*)(g_hist.data),(float*)(r_hist.data),src.cols*src.rows*3,histSize); 
  DrawHist("calcColorImgHistogram3",b_hist,g_hist,r_hist,histSize); 
 } 
 //装箱直方图的条目设置为32 
 histSize = 32; 
///用opencv的接口函数求装箱直方图,然后绘制该装箱直方图 
 CalcHist_OpenCV(&src,b_hist,g_hist,r_hist,histSize); 
 DrawHist("calcBinnedColorImgHistogram1",b_hist,g_hist,r_hist,histSize); 
 /// 用自定义的彩色图像三个通道直方图统计函数求装箱直方图,然后绘制该装箱直方图 
 CalcHist_ColorImg(&src,b_hist,g_hist,r_hist,histSize); 
 DrawHist("calcBinnedColorImgHistogram2",b_hist,g_hist,r_hist,histSize); 
 /// 用另外一种自定义的彩色图像三个通道直方图统计函数求装箱直方图,然后绘制该装箱直方图 
 if (src.isContinuous())// 检查像素矩阵中的数据是否是连续存放的 
 { 
  b_hist = Mat::zeros(1,histSize, CV_32F); 
  g_hist = Mat::zeros(1,histSize, CV_32F); 
  r_hist = Mat::zeros(1,histSize, CV_32F); 
  CalcHist_ColorImg(src.data, 
(float*)(b_hist.data),(float*)(g_hist.data),(float*)(r_hist.data),src.cols*src.rows*3,histSize); 
  DrawHist("calcBinnedColorImgHistogram3",b_hist,g_hist,r_hist,histSize); 
 } 
 waitKey(0); 
 return 0; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值