点运算: 基于直方图的对比度增强
引言
图像处理–>空间域处理–>点运算。
1、图像显示与存储原理
<center>
<img src="" width="60%" height="60%"> #更改图片大小并居中
- RGB
- CMY(K)
- HSV
- CIE-XYZ
存储原理
2、图像增强的目标
- 改善图像的视觉效果;
- 转换为更适合于人或机器分析处理的形式;
- 突出对人或机器分析有意义的信息;
- 抑制无用信息, 提高图像的使用价值;
- 包括图像锐化, 平滑、 去噪, 灰度调整(对比度增强)
图像处理方法
3、点运算(基于直方图的对比度增强)
直方图统计:
直方图均衡化:
- 直方图均衡化是指: 利用图像直方图对对比度进行调整的方法。
- 直方图均衡化通常用来增加许多图像的局部对比度, 尤其是当图像的有用数据的对比度相当接近的时候。
- 直方图均衡化以后, 亮度可以更好地在直方图上分布。 这样就可以用于增强局部的对比度而不影响整体的对比度, 直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
- 直方图均衡化,实质上是对图像进行非线性拉伸,重新分配各个灰度单位中的像素点数量, 使一定灰度范围像素点数量的值大致相等。
自适应直方图均衡(AHE):
- 直方图均衡的经典算法对整幅图像的像素使用相同的变换, 如果图像中包括明显亮的或者暗的区域, 则经典算法作用有限。
- 自适应直方图均衡(AHE) 算法通过对局部区域进行直方图均衡, 来解决上述问题。
- 移动模板在原始图片上按特定步长滑动;
- 每次移动后, 模板区域内做直方图均衡, 映射后的结果赋值给模板区域内所有点;
- 每个点会有多次赋值, 最终的取值为这些赋值的均值。
CLAHE:
CLAHE参考博客。一定要看。
-
AHE会过度放大图像中相对均匀区域的噪音, 可采用限制对比度自适应直方图均衡(CLAHE) 。
-
与普通的自适应直方图均衡相比, CLAHE的不同地方在于直方图修剪过程, 用修剪后的直方图均衡图像时, 图像对比度会更自然。
-
整体思想就是把直方图高的部分截取来将整个直方图垫高。
- 小黑点的灰度直接由映射函数计算得到;
- 粉色区域内点的灰度由映射函数计算而得;
- 绿色区域内点的灰度由由相邻2块灰度映射值线性插值而得;
- 其他区域所有点的灰度由相邻4块的灰度映射值双线性插值而得。
CLAHE算法步骤:
- 1.图像分块, 以块为单位;
- 2.先计算直方图, 然后修剪直方图, 最后均衡;
- 3.遍历操作各个图像块, 进行块间双线性插值;
- 4.与原图做图层滤色混合操作。 (可选)
4、程序
直方图均衡化(HE)
Cpp+opencv
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main( )
{
// 加载源图像
Mat srcImage, dstImage;
srcImage = imread( "1.jpg", 1 );
if(!srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); return false; }
// 转为灰度图并显示出来
cvtColor( srcImage, srcImage, CV_BGR2GRAY );
imshow( "原始图", srcImage );
// 进行直方图均衡化
equalizeHist( srcImage, dstImage );
// 显示结果
imshow( "经过直方图均衡化后的图", dstImage );
waitKey(0);
return 0;
}
其他OpenCV图像增强算法实现参考博客
自适应直方图均衡化(AHE)
限制对比度自适应直方图均衡化(CLAHE)
Python+opencv
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('timg.jpg',0) #直接读为灰度图像
res = cv2.equalizeHist(img)
clahe = cv2.createCLAHE(clipLimit=2,tileGridSize=(10,10))
cl1 = clahe.apply(img)
plt.subplot(131),plt.imshow(img,'gray')
plt.subplot(132),plt.imshow(res,'gray')
plt.subplot(133),plt.imshow(cl1,'gray')
plt.show()
cpp+opencv
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void main()
{
Mat inp_img = cv::imread("D:\\proMatlab\\vessel_edge_extration\\image\\7.jpg");
if (!inp_img.data) {
cout << "Something Wrong";
}
namedWindow("Input Image", CV_WINDOW_AUTOSIZE);
imshow("Input Image", inp_img);
Mat clahe_img;
cvtColor(inp_img, clahe_img, CV_BGR2Lab);
vector<cv::Mat> channels(3);
split(clahe_img, channels);
Ptr<cv::CLAHE> clahe = createCLAHE();
// 直方图的柱子高度大于计算后的ClipLimit的部分被裁剪掉,然后将其平均分配给整张直方图
clahe->setClipLimit(4.); // (int)(4.*(8*8)/256)
//clahe->setTilesGridSize(Size(8, 8)); // 将图像分为8*8块
Mat dst;
clahe->apply(channels[0], dst);
dst.copyTo(channels[0]);
//
clahe->apply(channels[1], dst);
dst.copyTo(channels[1]);
clahe->apply(channels[2], dst);
dst.copyTo(channels[2]);
merge(channels, clahe_img);
Mat image_clahe;
cvtColor(clahe_img, image_clahe, CV_Lab2BGR);
namedWindow("CLAHE Image", CV_WINDOW_AUTOSIZE);
imshow("CLAHE Image", image_clahe);
imwrite("out.jpg", image_clahe);
waitKey();
system("pause");
}