OpenCV-Python教程(10、直方图均衡化)

电脑杂谈  发布时间:2019-08-04 05:01:41  来源:网络整理

opencv直方图均衡化_直方图均衡化 opencv_opencv直方图均衡化原理

现在我们要定义wndproc函数.原因是createglwindow函数会调用wndproc函数但是wndproc函数的实现在createglwindow函数后面.在c语言中,如果要在一个函数里面调用一个实现代码在其后面的函数的话,必须在该函数之前先声明要调用函数的原型.所以这里先声明wndproc函数,这样createglwindow函数就能调用它了.。 gdi32.dll 中的函数则负责 图形方面的...所以本文提供下载的所有源代 码中都包含了库工程和调用库的工程, 这二者都被...。使用此地址可以获得库中特定函数的地址,并且调用库中的相应函数。

提示:

本文内容:

在某些情况下,一副图像中大部分像素的强度都集中在某一区域,而质量较高的图像中,像素的强度应该均衡的分布。为此,可将表示像素强度的直方图进行拉伸opencv直方图均衡化,将其平坦化。如下:

图来自维基百科

本节的实验数据来自维基百科,原图如下:

其直方图为:

opencv直方图均衡化原理_opencv直方图均衡化_直方图均衡化 opencv

在图像处理中,直方图均衡化一般用来均衡图像的强度,或增加图像的对比度。在介绍使用直方图均衡化来拉伸图像的直方图之前,先介绍使用查询表的方法。

观察上图中原始图像的直方图,很容易发现大部分强度值范围都没有用到。因此先检测图像非0的最低(imin)强度值和最高(imax)强度值。将最低值imin设为0,最高值imax设为255。中间的按255.0*(i-imin)/(imax-imin)+0.5)的形式设置。

实现的任务主要集中在查询表的创建中,代码如下:

minBinNo, maxBinNo = 0, 255
#计算从左起第一个不为0的直方图位置
for binNo, binValue in enumerate(hist):
    if binValue != 0:
		minBinNo = binNo
		break
#计算从右起第一个不为0的直方图位置
for binNo, binValue in enumerate(reversed(hist)):
    if binValue != 0:
		maxBinNo = 255-binNo
		break
print minBinNo, maxBinNo
#生成查找表,方法来自参考文献1第四章第2节
for i,v in enumerate(lut):
	print i
	if i < minBinNo:
		lut[i] = 0
	elif i > maxBinNo:
		lut[i] = 255
	else:
		lut[i] = int(255.0*(i-minBinNo)/(maxBinNo-minBinNo)+0.5)

查询表创建完成后,就直接调用相应的OpenCV函数即可,这里调用的是cv2.LUT函数:

#计算
result = cv2.LUT(image, lut)

cv2.LUT函数只有两个参数,分别为输入图像和查找表,其返回处理的结果,完整代码如下:

#coding=utf-8
import cv2
import numpy as np
image = cv2.imread("D:/test/unequ.jpg", 0)
lut = np.zeros(256, dtype = image.dtype )#创建空的查找表
hist= cv2.calcHist([image], #计算图像的直方图
    [0], #使用的通道
    None, #没有使用mask
    [256], #it is a 1D histogram
    [0.0,255.0])
	
minBinNo, maxBinNo = 0, 255
#计算从左起第一个不为0的直方图柱的位置
for binNo, binValue in enumerate(hist):
    if binValue != 0:
		minBinNo = binNo
		break
#计算从右起第一个不为0的直方图柱的位置
for binNo, binValue in enumerate(reversed(hist)):
    if binValue != 0:
		maxBinNo = 255-binNo
		break
print minBinNo, maxBinNo
#生成查找表,方法来自参考文献1第四章第2节
for i,v in enumerate(lut):
	print i
	if i < minBinNo:
		lut[i] = 0
	elif i > maxBinNo:
		lut[i] = 255
	else:
		lut[i] = int(255.0*(i-minBinNo)/(maxBinNo-minBinNo)+0.5)
#计算
result = cv2.LUT(image, lut)
cv2.imshow("Result", result)
cv2.imwrite("LutImage.jpg", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

直方图均衡化 opencv_opencv直方图均衡化_opencv直方图均衡化原理

直方图结果如下,可以看到原来占的区域很小的直方图尖峰被移动了:

处理结果为:

关于直方图的绘制,请参考这篇文章。

有时图像的视觉上的缺陷并不在强度值集中在很窄的范围内。而是某些强度值的使用频率很大。比如第一幅图中,灰度图中间值的占了很大的比例。

最后,构建直方图强度映射关系m(g)=g,并采用该映射关系调整原图像每一个像素处的强度值,从而达到强度校正。因此,在所构建的强度映射关系中,被赋予新的强度值的像素个数则为 n(m, n): n(m, n) = min(n rem (m, n),n req (m, n))(2) 以图2为例,对于原始直方图i中强度值为m = 1以及目标直方图 i 中强度值为 n = 1 这一步对应的变换,有 n req (m, n) = 2,以及 n rem (m, n) = 3。首先将初值赋给控制变量,接着判断 控制变量的值是否小于或等于终值,若是opencv直方图均衡化,则执行循环体,在执行了循环体 之后,自动将控制变量的值该为它的后继值,并重新判断是否小于或等于终 值。

lut[i] = int(255.0 *p[i]) #p[i]是是强度值小于或等于i的像素的数目。

p[i]即直方图累积值,这是包含小于给点强度值的像素的直方图,以代替包含指定强度值像素的数目。比如第一幅图像的累计直方图如下图中的蓝线:

opencv直方图均衡化原理_opencv直方图均衡化_直方图均衡化 opencv

而完美均衡的直方图,其累积直方图应为一条斜线,如上图中均衡化之后的红线。

更一点,这种累积直方图应称为累积分布(cumulative distribition)。在NumPy中有一个专门的函数来计算。这在NumPy实现直方图均衡化一节中介绍。

根据熵理论可知,直方图中,当h[0],h[1]…,h[n-1]相等时,图像信息量最大-》均衡化的目的是使每个hi都相等,即把原始图的直方图变换为均匀分布的形式,这样就增加了象素值的范围,增强了图像的对比效果。 基于局部精确直方图匹配的色彩恒常算法,将实时图分成一系列子块图像,利用导航系统预测的位姿信息得到实时图与基准图的粗略对应关系,考虑平移、尺度、旋转等补偿,选取基准图中与实时图子块对应的基准图子块,对每一对实时图子块和基准图子块分别计算其红(r)、绿(g)、蓝(b)色彩直方图,求解其色彩直方图的颜色映射关系,并根据每对图像子块三个颜色通道的直方图颜色映射关系,对实时图子块的三种颜色进行变换。对原图像f(x,y)依次进行直方图均衡化和图像滤波处理,再使用8领域方向链码的方法从背景模板中提取得到全部碎片图像。

用OpenCV实现直方图均衡化很简单,只需调用一个函数即可:

img = cv2.imread('图像路径',0)
equ = cv2.equalizeHist(img)
cv2.imshow('equ',equ)

这样图像就均衡化了。可以通过直方图的计算与显示这篇文章中介绍的方法将结果绘制出来。

通过前面的介绍,可以明白直方图均衡化就是用一种特殊的查找表来实现的。所以这里用NumPy函数,以查找表的方式手动实现图像直方图的均衡化:

#coding=utf-8
import cv2
import numpy as np
image = cv2.imread("D:/test/unequ.jpg", 0)
lut = np.zeros(256, dtype = image.dtype )#创建空的查找表
hist,bins = np.histogram(image.flatten(),256,[0,256]) 
cdf = hist.cumsum() #计算累积直方图
cdf_m = np.ma.masked_equal(cdf,0) #除去直方图中的0值
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())#等同于前面介绍的lut[i] = int(255.0 *p[i])公式
cdf = np.ma.filled(cdf_m,0).astype('uint8') #将掩模处理掉的元素补为0
#计算
result2 = cdf[image]
result = cv2.LUT(image, cdf)
cv2.imshow("OpenCVLUT", result)
cv2.imshow("NumPyLUT", result2)
cv2.waitKey(0)
cv2.destroyAllWindows()

opencv直方图均衡化原理_opencv直方图均衡化_直方图均衡化 opencv

最终结果

比较查找表和OpenCV直方图均衡化生成的直方图:

可以看出,总体上来看是吻合的,但OpenCV中函数的实现可能还有一些细微的差别(有空去翻下源码,不过今天就先到这里了)。

educational background: south china university of technology. b.s. in computer science, july 1990. courses included: computer science, systems design and analysis, pascal programming, operating systems, cobol programming, d-base programming, fortran programming, systems management。i know that computers and networks are the future tools to learn the profession in the premise, i had a great interest in the computer and read a lot about books, windows98/xx, kingdee finance, uf financial and other systems, application software, foxpro, vb language and other programming languages.。i have the good computer knowledge and application ability, can grasp the basic application software skilled the use, and can use languages and so on c, assembly, vb, html carries on the programming。

2、《OpenCV References Manule》

3、

如有错误请指正,谢谢.。如有说的不对的不好的请指正谢谢。最后,我补充一下,我们平时保教工作肯定会出一些意外,有一些不足之处,请家长们谅解的同时,也请多指正、多批评,我们愿愿意聆听您的声音,愿意改正自己的错误,为了我们宝宝的未来,让我们多沟通,多交流,一起努力。


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-117993-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 程成
        程成

        我也会选择守护目前来之不易的生活

      • 曾亚飞
        曾亚飞

        已开了第一炮

      • 上原多香子
        上原多香子

        肯定不止我一个人觉得Luna变了

      热点图片
      拼命载入中...