【图像处理OpenCV(C++版)】——4.1 对比度增强之灰度直方图

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

前言

😊😊😊欢迎来到本博客😊😊😊

🌟🌟🌟 本专栏主要结合OpenCV和C++来实现一些基本的图像处理算法并详细解释各参数含义适用于平时学习、工作快速查询等随时更新。

😊😊😊 具体食用方式可以点击本专栏【OpenCV快速查找(更新中)】–>搜索你要查询的算子名称或相关知识点或者通过这篇博客👉通俗易懂OpenCV(C++版)详细教程——OpenCV函数快速查找(不断更新中)]查阅你想知道的知识即可食用。

🎁🎁🎁支持如果觉得博主的文章还不错或者您用得到的话可以悄悄关注一下博主哈如果三连收藏支持就更好啦这就是给予我最大的支持😙😙😙


文章目录

学习目标

  • 熟悉灰度直方图概念及原理
  • C++实现获取图像灰度直方图

一、前言

  采集高质量的图像有各种各样的方法但是有的图像还是不够好需要通过图像增强技术提高其质量这里要介绍的对比度增强或者称为对比度拉伸就是图像增强技术的一种主要解决由于图像的灰度级范围较小造成的对比度较低的问题目的就是将输出图像的灰度级放大到指定的程度使得图像中的细节看起来更加清晰。对比度增强有几种常用的方法如线性变换分段线性变换伽马变换直方图正规化直方图均衡化局部自适应直方图均衡化等这些方法的计算代价较小但是却产生了较
为理想的效果。

二、灰度直方图

2.1、概念

  在数字图像处理中灰度直方图是一种计算代价非常小但却很有用的工具概括了一幅图像的灰度级信息。灰度直方图是图像灰度级的函数用来描述每个灰度级在图像矩阵中的像素个数或者占有率。举一个简单的例子假设有如下图像矩阵

  图像矩阵中我们可以看到灰度值1在I中出现的次数为1值6出现的次数为1……值20出现的次数为4……值255出现的次数为0然后将得到的每个数值按照直方图的可视化方式表示出来即可横坐标代表灰度级纵坐标代表对应的每一个灰度级出现的次数如下图所示。用占有率或称归一化直方图、概率直方图表示就是灰度值1在I中的占有率为1/16灰度值6在I中的占有率为1/16灰度值20在I中的占有率为4/16…灰度值255在I中的占有率为0/16

  了解了灰度直方图的定义后接下来介绍计算灰度直方图的C++实现。

  

2.2、实现

  OpenCV提供了函数calcHist来实现直方图的构建但是在计算8位图的灰度直方图时它使用起来略显复杂。可以定义函数calcGrayHist来计算灰度直方图其中输入参数为8位图将返回的灰度直方图存储为一个1行256列的Mat类型。代码如下

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;


Mat calcGrayHist(const  Mat & image) {
	Mat histogram = Mat::zeros(Size(256, 1), CV_32SC1);

	int rows = image.rows;
	int cols = image.cols;
	
	//计算每个灰度级个数
	for (int r = 0; r < rows; r++)
	{
		for (int c = 0; c < cols; c++)
		{
			int index = int(image.at<uchar>(r, c));
			histogram.at<int>(0, index) += 1;
		}
	}
	return histogram;

}

int main() {
	//输入原图
	Mat image = imread("D:/VSCodeFile/OpenCV_CSDN/image/logo.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	if (!image.data)
	{
		return -1;
	}

	calcGrayHist(image);

	return 0;

}

  OpenCV提供了函数

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);

其中
  images 输入的图像
  nimages输入的图像个数
  channels 统计直方图第几通道
  mask可选的操作掩码
  hist输出的直方图数组
  dims需要统计直方图通道的个数
  histSize直方图分成多少个区间
  ranges像素值区间
  uniform是否进行归一化处理
  accumulate在多个图像时是否计算像素值个数

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;
int main() {
	Mat img = imread("D:/VSCodeFile/OpenCV_CSDN/image/img2.jpg");
	if (img.empty()) {
		cout << "请确认输入的图片路径是否正确" << endl;
		return -1;
	}
	Mat gray;
	cvtColor(img, gray, COLOR_BGR2GRAY);
	
	//设置提取直方图的相关变量
	Mat hist;//用于存放直方图计算结果
	const int channels[1] = { 0 };//通道索引
	float inRanges[2] = { 0,255 };
	const float*ranges[1] = { inRanges };//像素灰度值范围
	const int bins[1] = { 256 };//直方图的维度其实就是像素灰度值的最大值
	
	calcHist(&img, 1, channels, Mat(), hist, 1, bins, ranges);//计算图像直方图
			
															  
	//准备绘制直方图
	int hist_w = 512;
	int hist_h = 400;
	int width = 2;
	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
	for (int i = 1; i <= hist.rows; ++i) {
		rectangle(histImage, Point(width*(i - 1), hist_h - 1),
			Point(width*i - 1, hist_h - cvRound(hist.at<float>(i - 1) / 20)),
			Scalar(255, 255, 255), -1);
	}
	namedWindow("histImage", WINDOW_AUTOSIZE);
	imshow("histImage", histImage);
	imshow("gray", gray);
	waitKey(0);
	return 0;
}

  图像对比度是通过灰度级范围来度量的而灰度级范围可通过观察灰度直方图得到灰度级范围越大代表对比度越高反之对比度越低低对比度的图像在视觉上给人的感觉是看起来不够清晰所以通过算法调整图像的灰度值从而调整图像的对比度是有必要的。最简单的一种对比度增强方法是通过灰度值的线性变换来实现的下一节将介绍什么是线性变换。


三、 总结

  最后长话短说大家看完就好好动手实践一下切记不能三分钟热度、三天打鱼两天晒网。OpenCV是学习图像处理理论知识比较好的一个途径大家也可以自己尝试写写博客来记录大家平时学习的进度可以和网上众多学者一起交流、探讨有什么问题希望大家可以积极评论交流我也会及时更新来督促自己学习进度。希望大家觉得不错的可以点赞、关注、收藏。


🚶🚶🚶 今天的文章就到这里啦~
喜欢的话点赞👍、收藏⭐️、关注💟哦 ~
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: c++