OpenCV图像增强:直方图拉伸和直方图均衡化
来源:互联网 发布:行知外国语是区重点吗 编辑:程序博客网 时间:2024/05/29 11:15
直方图反映了图像中像素值的分布情况,很多时候,图像的视觉缺陷可以根据图像的直方图来分析。比如直方图太窄,说明图像使用的灰度值范围太窄;比如直方图有一个很强烈的峰值,说明图像部分灰度值的使用频率比其他强度值要高得多。
所以,可以通过直方图信息来修改图像的灰度值。如果将一种灰度修改为另一种灰度,那么这意味着这种改变不是针对某些像素的,而是整体性的,新的颜色值只与当前像素的颜色值相关。这种关系,通常可以用一个映射函数来表示,称之为查找表。
对于灰度图,查找表是一个一维数组,包含256个项目。数组下标(0-255)代表当前灰度,下标对应的值代表当前灰度修改后的值。
OpenCV里的查找表函数cv::LUT(),
//Performs a look-up table transform of an array
void LUT(InputArray src, InputArray lut, OutputArray dst, int interpolation=0 )
下面介绍的直方图拉伸和直方图均衡化操作都会用到查找表。程序中直方图的计算调用了自定义的类函数,参见OpenCV计算和显示图像直方图(其实将一些算法封装为类很简单,方便了调用和扩展)
直方图拉伸
//直方图拉伸cv::Mat stretch(const cv::Mat& image,int minvalue=0){ Histogram1D h; cv::Mat hist = h.getHistogram(image); //找到直方图的左边限值 int imin = 0; for (; imin < h.getHistSize()[0];imin++) { if (hist.at<float>(imin)>minvalue) { break; } } //找到直方图的右边限值 int imax = h.getHistSize()[0]-1; for (; imax >= 0; imax--) { if (hist.at<float>(imax)>minvalue) { break; } } //创建查找表 cv::Mat lut(1, 256, CV_8U); //构建查找表 for (int i = 0; i < 256;i++) { if (i < imin) lut.at<uchar>(i) = 0; else if (i>imax) lut.at<uchar>(i) = 255; else { lut.at<uchar>(i) = cvRound(255.0*(i - imin) / (imax - imin)); } } cv::Mat result = Histogram1D::applyLookUp(image,lut); return result;}
至于Histogram1D::applyLookUp
只是cv::LUT简单的重新封装,具体如下
cv::Mat Histogram1D::applyLookUp(const cv::Mat& image, const cv::Mat& lookup){ cv::Mat result; cv::LUT(image,lookup,result); return result;}
运行效果:
源图像vs拉伸直方图后的图像
源图像直方图vs拉伸后的直方图
直方图均衡化
OpenCV提供了一个易用的函数,用于直方图均衡化处理,
//Equalizes the histogram of a grayscale image.
void equalizeHist(InputArray src, OutputArray dst)
如果只是使用,而非自己弄清楚内部的实现,阅读可以到此为止了^-^。
实现原理是:一个完全均衡的直方图,意味着所有箱子包含的像素数量是相同的。其中一个必要条件就是,50%像素的强度值小于128,25%像素的强度值小于64,依次类推。所以p%像素的强度值必须小于或等于255*p%。这条规则也是直方图均衡化算法所采用的,程序语言描述如下:
lut.at<uchar>(i) = static_cast<uchar>(p[i]*255.0/image.total());
p[i]是强度值小于或等于i的像素数量,成为累计直方图。total返回图像像素总数,p[i]/image.total代表某堆灰度值的百分比。
具体实现:
cv::Mat myequalizeHist(cv::Mat& image){ Histogram1D h; cv::Mat hist = h.getHistogram(image); cv::Mat lut(1, 256, CV_8U); float cumulate = 0;//强度值小于或等于某值的像素数量 for (int i = 0; i < 256; i++) { cumulate += hist.at<float>(i); lut.at<uchar>(i) = static_cast<uchar>(cumulate*255.0/image.total()); } cv::Mat result; cv::LUT(image, lut, result); return result;}
运行效果:
源图像vs直方图均衡化之后的图像
源图像直方图 vs均衡化之后的直方图
- OpenCV图像增强:直方图拉伸和直方图均衡化
- OpenCV 图像增强—直方图均衡化和灰度拉伸
- 直方图拉伸和图像均衡
- 图像增强-直方图均衡化
- 直方图均衡化,图像增强
- 【OpenCV笔记 14】OpenCV图像增强方法直方图均衡化
- 图像直方图均衡化和图像一般的拉伸
- 图像直方图均衡化增强opencv与C语言版
- Opencv图像识别从零到精通(10)-----直方图均衡化与直方图拉伸
- opencv直方图均衡化图像
- 图像直方图均衡和直方图规定化
- 图像指数、对数增强、直方图均衡化
- 图像增强之直方图均衡化
- [图像增强]二. 直方图均衡化
- 图像指数、对数增强、直方图均衡化
- 图像增强之直方图均衡化
- 直方图均衡化—图像增强
- 图像增强之(一)---直方图均衡化
- Scut游戏服务器引擎搭建
- Reading from client: Connection reset by peer
- Ubuntu16.04下Java环境安装与配置
- Seledium IDE脚本回放报错Element not found
- Qt vs MFC(Qt和MFC的战争)
- OpenCV图像增强:直方图拉伸和直方图均衡化
- ThreadLocal---原理解析
- HTML5新的表单元素
- 工作的一年,学到了什么?
- wait_event_timeout的理解
- K近邻算法
- C++学习笔记(八)
- JavaScript中函数参数的值传递和引用传递
- android studio 设置软件源