版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huayunhualuo/article/details/81868014
1.概述
直方图广泛的应用于很多计算机视觉当中,通过标记帧与帧之间显著的边缘和颜色的统计变化,来检测视频场景的变化。
直方图就是对数据进行统计的一种方法,并且将统计值组织到一系列事先定义好的bin当中。bin其数值就是从数据中计算出的特征统计量,这些数据可以是诸如梯度,方向,色彩或者其他特征。
图像直方图(Image Histogram)是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数,可以用来观察直方图了解需要如何调整亮度分布。
直方图的意义:
- 直方图是图像中像素强度分布的图形表达方式
- 它统计了每一个强度值所具有的像素个数
具体的术语和细节
- dims:需要统计的特征的数目
- bins:每个特征空间子区段的数目
- range:每个特征空间的取值范围
2. 直方图的计算与绘制
2.1 计算直方图:calcHist()函数
函数原型
void calcHist(const Mat * images,int nimages,const int * channels, InputArray mask, OutputArray hist,int dims,const int * histSize, const float ** ranges,bool uniform=true, bool accumulate = false)
2.2 找寻最值:minMaxLoc()函数
在数组中找到全局的最大值和最小值。
函数原型
void minMaxLoc(InputArray src, double * minVal,double * maxVal = 0,Point * minLoc= 0,Point maxLoc = 0, InputArray mask = noArray())
2.3 示例程序:H-S直方图
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
//main()函数
int main()
{
//载入源图
Mat srcImage, hsvImage;
srcImage = imread("1.jpg");
cvtColor(srcImage, hsvImage, COLOR_BGR2HSV);
//参数准备
//将色调量化为30个等级,将饱和度量化为32个等级
//色调的直方图直条数量
int hueBindim = 30;
//饱和度的直方图直条数量
int saturationBindim = 32;
int histSize[] = { hueBindim,saturationBindim };
//定义色调的变化范围
float hueRanges[] = { 0,180 };
//定义饱和度的变化范围为0到255
float saturationRanges[] = { 0,256 };
const float * ranges[] = { hueRanges,saturationRanges };
MatND dstHist;
//参数准备,calcHist 函数中将计算0通道和1通道的直方图
int channels[] = { 0,1 };
//正式调用calcHist进行直方图计算
calcHist(&hsvImage, 1, channels, Mat(), dstHist, 2, histSize, ranges, true, false);
//绘制直方图的参数
double maxValue = 0;
minMaxLoc(dstHist, 0, &maxValue, 0, 0);//查找数组和子数组的全局最小值和最大值存入maxValue中
int scale = 10;
Mat histImg = Mat::zeros(saturationBindim*scale, hueBindim * 10, CV_8UC3);
//双层循环,进行直方图绘制
for (int hue = 0; hue < hueBindim; hue++)
{
for (int saturation = 0; saturation < saturationBindim; saturation++)
{
float binValue = dstHist.at<float>(hue, saturation);
int intensity = cvRound(binValue * 255 / maxValue);
rectangle(histImg, Point(hue*scale, saturation
*scale), Point((hue + 1)*scale - 1, (saturation + 1)*scale - 1), Scalar::all(intensity), FILLED);
}
}
imshow("素材图", srcImage);
imshow("H-S直方图", histImg);
waitKey(0);
return 0;
}
2.3 示例程序:计算并绘制图像一维直方图
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
//main()函数
int main()
{
//载入原图并显示
Mat srcImage = imread("1.jpg", 0);
imshow("原图", srcImage);
if (!srcImage.data)
{
printf("读取图片错误~!\n");
return false;
}
//定义变量
MatND dstHist;
int dims = 1;
float hrange[] = { 0,255 };
const float * ranges[] = { hrange };
int size = 256;
int channels = 0;
//计算图像的直方图
calcHist(&srcImage, 1, &channels, Mat(), dstHist, dims, &size, ranges);
int scale = 1;
Mat dstImage(size*scale, size, CV_8U, Scalar(0));
//获取最大值和最小值
double minValue = 0;
double maxValue = 0;
minMaxLoc(dstHist, &minValue, &maxValue, 0, 0);
//绘制出直方图
int hpt = saturate_cast<int>(0.9*size);
for (int i = 0; i < 256; i++)
{
float binValue = dstHist.at<float>(i);
int realValue = saturate_cast<int>(binValue*hpt / maxValue);
rectangle(dstImage, Point(i*scale, size - 1), Point((i + 1)*scale - 1, size - realValue), Scalar(255));
}
imshow("一维直方图", dstImage);
waitKey(0);
return 0;
}
2.4示例程序:RGB三色直方图
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{
//载入素材图并显示
Mat srcImage;
srcImage = imread("1.jpg");
imshow("素材图", srcImage);
//参数准备
int bins = 256;
int hist_size[] = { bins };
float range[] = { 0,256 };
const float * ranges[] = { range };
MatND redHist, grayHist, blueHist;
int channels_r[] = { 0 };
//进行直方图计算,红色部分计算
calcHist(&srcImage, 1, channels_r, Mat(), redHist, 1, hist_size, ranges, true, false);
//进行直方图计算,绿色部分计算
int channels_g[] = { 1 };
calcHist(&srcImage, 1, channels_g, Mat(), grayHist, 1, hist_size, ranges, true, false);
//进行直方图计算,蓝色部分计算
int channels_b[] = { 2 };
calcHist(&srcImage, 1, channels_b, Mat(), blueHist, 1, hist_size, ranges, true, false);
//绘制出三色直方图
//参数准别
double maxValue_red, maxValue_green, maxValue_blue;
minMaxLoc(redHist, 0, &maxValue_red, 0, 0);
minMaxLoc(grayHist, 0, &maxValue_green, 0, 0);
minMaxLoc(blueHist, 0, &maxValue_blue, 0, 0);
int scale = 1;
int histHeight = 256;
Mat histImage = Mat::zeros(histHeight, bins * 3, CV_8UC3);
//开始绘制
for (int i = 0; i < bins; i++)
{
//参数准备
float binValue_red = redHist.at<float>(i);
float binValue_green = grayHist.at<float>(i);
float binValue_blue = blueHist.at<float>(i);
int intensity_red = cvRound(binValue_red*histHeight / maxValue_red);
int intensity_green = cvRound(binValue_green*histHeight / maxValue_green);
int intensity_blue = cvRound(binValue_blue*histHeight / maxValue_blue);
//绘制红色分量的直方图
rectangle(histImage, Point(i*scale, histHeight - 1), Point((i + 1)*scale - 1, histHeight - intensity_red), Scalar(255, 0, 0));
//绘制绿色分量的直方图
rectangle(histImage, Point((i + bins)*scale, histHeight - 1), Point((i + bins + 1)*scale - 1, histHeight - intensity_green), Scalar(0, 255, 0));
//绘制蓝色分量的直方图
rectangle(histImage, Point((i + bins * 2)*scale, histHeight - 1), Point((i + bins * 2 + 1)*scale - 1, histHeight - intensity_blue), Scalar(0, 0, 255));
}
//在窗口显示出绘制好的直方图
imshow("图像的RGB直方图", histImage);
waitKey(0);
return 0;
}