参考书目:《OpenCV计算机视觉编程攻略》(第3版)
计算灰度图像的直方图并进行阈值化操作:
引入查找表:
//用直方图统计像素
/*
1.计算图像直方图
2.利用查找表修改图像外观
3.直方图均衡化
4.反向投影直方图检测特定图像内容
5.用均值平移法查找目标
6.比较直方图搜索相似图像
7.用积分图像统计像素
*/
#include<opencv2/opencv.hpp>
#include<iostream>
//创建灰度图像的直方图
class Histogram2D {
private:
int histSize[1]; //直方图中箱子的数量
float hranges[2];//值范围
const float* ranges[1];//值范围的指针
int chanels[1]; //要检查的通道数
public:
//准备一维直方图的默认参数
Histogram2D() {
histSize[0] = 256;
hranges[0] = 0.0;
hranges[1] = 256.0;
ranges[0] = hranges;
chanels[0] = 0;
}
cv::Mat getHistogram(const cv::Mat& image) {
cv::Mat hist;
//用calchist函数计算一维直方图
cv::calcHist(&image,
1,//1幅图像的直方图
chanels,//使用的通道
cv::Mat(),//不使用掩码
hist,//作为结果的直方图
1,//这是一维的直方图
histSize,
ranges);
return hist;
}
//计算一维直方图,并返回它的图像
cv::Mat getHistogramImage(const cv::Mat& image, int zoom = 1) {
//先计算直方图
cv::Mat hist = getHistogram(image);
//创建图像
return getImageOfHistogram(hist, zoom);
}
//
static cv::Mat getImageOfHistogram(const cv::Mat& hist, int zoom) {
//取得箱子值的最大值和最小值
double maxVal = 0;
double minVal = 0;
cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);
//取得直方图的大小
int histSize = hist.rows;
//用于显示直方图的方形图像
cv::Mat histImg(histSize * zoom, histSize * zoom, CV_8U, cv::Scalar(255));
//设置最高点为90%(即图像高度)的箱子个数
int hpt = static_cast<int>(0.9 * histSize);
//为每个箱子画垂线
for (int h = 0; h < histSize; h++)
{
float binVal = hist.at<float>(h);
if (binVal > 0) {
int intensity = static_cast<int>(binVal * hpt / maxVal);
cv::line(histImg, cv::Point(h * zoom, histSize * zoom),
cv::Point(h * zoom, (histSize - intensity) * zoom),
cv::Scalar(0), zoom);
}
}
return histImg;
}
static cv::Mat applyLookUp(const cv::Mat& image,
const cv::Mat& lookup)
{
cv::Mat result;
cv::LUT(image, lookup, result);
return result;
}
};
int main()
{
cv::Mat image = cv::imread("group.jpg", 0);//以黑白方式打开
//直方图对象
Histogram2D h;
//以图像形式显示直方图
cv::namedWindow("Histogram");
cv::imshow("Histogram", h.getHistogramImage(image));
//阈值化处理
cv::Mat thresholded;
cv::threshold(image, thresholded, 70, 255, cv::THRESH_BINARY);
cv::namedWindow("Thresholded");
cv::imshow("Thresholded", thresholded);
//创建一个图像反转的查找表
cv::Mat lut(1, 256, CV_8U);
for (int i = 0; i < 256; i++)
{
lut.at<uchar>(i) = 255 - i;
}
cv::Mat result = h.applyLookUp(image, lut);
cv::namedWindow("lut");
cv::imshow("lut", result);
cv::waitKey(0);
return 0;
}