1、用直方图统计像素
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<iostream>
using namespace cv;
class Histogram1D
{
private:
int histSize[1]; //直方图项目数
float hranges[2]; //值范围
const float* ranges[1]; //这是指向常量的指针,值范围的指针
int channels[1];
public:
Histogram1D()
{
histSize[0] = 256;
hranges[0] = 0.0;
hranges[1] = 256.0;
ranges[0] = hranges;
channels[0] = 0;
}
Mat getHistogrm(const Mat& image) //计算函数
{
Mat hist;
//比较特殊,这个函数的参数有好多指针
calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
return hist; //这个返回值是一个一维数组,但以Mat形式存储
}
//这个函数按照hist数组和zoom直方图高度放大倍数来生成直方图
static Mat getImageOfHistogram(Mat& hist, int zoom)
{
/*一共有255个灰度,每一个灰度都对应有不同数量的像素数,
这两个最大值与最小值是指这255个像素数中的最大值与最小值
hist数组当中就存储着这255个值*/
double maxVal = 0.0;
double minVal = 0.0;
minMaxLoc(hist, &minVal, &maxVal, 0, 0);//获取一维数组hist中的最大值和最小值
int histSize = hist.rows; //求灰度数组的长度
//生成一个图像,尺寸按照:灰度的个数(255)*直方图高度放大倍数
Mat histImg(histSize*zoom, histSize*zoom, CV_8U, Scalar(0));//背景白色
int hpt = static_cast<int>(0.9*histSize);//确定直方图的高度,是实际灰度数的90%,防止触顶
for (int h = 0; h < histSize; h++) //注意,原点在左上角
{
float binVal = hist.at<float>(h);//获取每个灰度对应的像素数
if (binVal > 0) //如果该该灰度对应的像素数不为零,就需要划线
{
/*intensity是每个灰度值对应的直方图高度,计算方式为:
求这个数量占最大值的百分比,然后映射到高度上,emmm,有点归一化的味道*/
int intensity = static_cast<int>(binVal/ maxVal*hpt);
/*这里需要注意,背景是黑色的,绘制的线是白色的,而且直线起点在图像框的顶部
相当于从黑色背景中腐蚀掉一部分从而得到白底黑线的直方图*/
line(histImg, Point(h*zoom, 0),
Point(h*zoom, (histSize - intensity)*zoom), Scalar(255), zoom);
}
}
return histImg;
}
Mat getHistogramImage(const Mat& image, int zoom = 2)
{
Mat hist = getHistogrm(image);
return getImageOfHistogram(hist, zoom);
}
};
int main(void)
{
Mat image = imread("1.jpg", 0);
Histogram1D h;
Mat histo = h.getHistogrm(image);
for (int i = 0; i < 256; i++)
{
std::cout << "Value" << i << "=" << histo.at<float>(i) << std::endl;
}
getchar();
imshow("Hisrtogram", h.getHistogramImage(image));
waitKey(0);
}
2、利用查找表修改图像外观
实际是原像素到新像素的一个映射,利用的关系式为:newIntensity = lookup[oldIntensity],过程再不写了,昨天写了以后忘了保存了,很自闭。这种扩展可以提高图片质量
3、直方图均衡化
就是让图像直方图变得更平缓,可以提高图像的质量。
4、反向投影直方图检测特定图像内容
5、用均值平移算法查找目标
当我们已识别出一个感兴趣的物体,利用这个过程可以在新的图像中识别出这个物体。本节使用的是HSV色彩空间。注意低饱和度下色调信息会不稳定。均值偏移算法是一个迭代过程。
6、比较直方图搜索相似图像
这属于基于内容的图像检索
7、用积分图像统计像素
所谓积分图像就是取图像左上方的全部像素计算累加和,并用这个累加和替换图像中的每一个像素,所以图像的像素值会呈现出左上角的值最小,右下角的值最大的现象,然后需要计算某个区域的像素之和时,就可以进行几次加减法求出像素值之和。
自适应阈值化会用到积分图像,由于自适应阈值化时需要不断计算像素周围的像素值和,会有很大的运算量,当使用积分图像时,计算周围像素之和就会变简单,四次加减运算就可以实现,
8、总结
直方图表示物体外观的全局特征。另外使用积分图像也可以实现5中的内容,5使用的是均值平移算法。