在OpenCV中,也可以对三通道的图像,比如BGR,HSV等计算直方图。方法和计算单通道图像直方图相似,下面的代码描述了如何计算一个BGR三通道图像的直方图,需要注意的是,因为是三通道,每个通道取值都是[0,255],所以bin的数目达到了256*256*256,这时如果使用普通三维矩阵输出直方图结果,需要很大的空间,所以我们通常使用稀疏矩阵来保存输出结果。因为稀疏矩阵只保存非零值,这样可以节省存储空间。
int main( int argc, char** argv )
{
Mat src, dst;
/// 打开图像
src = imread( "../lenna.jpg");
if( !src.data )
{ return -1; }
/// 设定bin数目
int histSize[3];
float hranges[2];
const float* ranges[3];
int channels[3];
// BGR彩色直方图
// 准备一个color直方图数据, BGR格式
histSize[0]= histSize[1]= histSize[2]= 256;
hranges[0]= 0.0; // BGR分量的范围
hranges[1]= 255.0;
ranges[0]= hranges; // BGR三个通道都是0-255范围
ranges[1]= hranges;
ranges[2]= hranges;
channels[0]= 0; // 三通道
channels[1]= 1;
channels[2]= 2;
//结果直方图
cv::SparseMat histo(3,histSize,CV_32F);
// 计算直方图
cv::calcHist(&src,
1, // 仅一副图像的直方图
channels, // 使用的channel
cv::Mat(), // 没有使用mask
histo, // 计算的结果
3, // 3D直方图
histSize, // bin的数量
ranges // BGR像素的范围
);
SparseMatConstIterator_<float> it = histo.begin<float>(), it_end = histo.end<float>();
double s = 0;
int dims = histo.dims();
int count=0;
for(; it != it_end; ++it)
{
// 打印出稀疏矩阵的值
const SparseMat::Node* n = it.node();
printf("(");
for(int i = 0; i < dims; i++)
printf("%d%s", n->idx[i], i < dims-1 ? ", " : ")");
printf(": %g\n", it.value<float>());
s += *it;
count++;
}
printf("Element sum is %g\n", s);
printf("element num is %d\n", count);
while(1)
waitKey(0);
return 0;
}
程序运行效果如下,可以看到实际上稀疏矩阵中只存储了69579项,也就是图像只有69579种颜色。
程序代码:工程FirstOpenCV19