为了得到更加清晰的图像我们需要通过技术对图像进行处理, 比如使用对比度增强的方法来处理图像, 对比度增强就是对图像输出的灰度级放大到指定的程度, 获得图像质量的提升. 本文主要通过代码的方式, 通过 OpenCV 的内置函数将图像处理到我们理想的结果.
灰度直方图
灰度直方图通过描述灰度级在图像矩阵中的像素个数来展示图像灰度级的信息, 通过灰度直方图的统计我们可以看到每个灰度值的占有率. 下面是一个灰度直方图的实现:
- import cv2
- import numpy as np
- import sys
- import matplotlib.pyplot as plt
- # 计算灰度直方图
- def calcGrayHist(image):
- rows,clos = image.shape
- #创建一个矩阵用于存储灰度值
- grahHist = np.zeros([256],np.uint64)
- print('这是初始化矩阵')
- print(grahHist )
- for r in range(rows):
- for c in range(clos):
- #通过图像矩阵的遍历来将灰度值信息放入我们定义的矩阵中
- grahHist[image[r][c]] +=1
- print('这是赋值后的矩阵')
- print(grahHist)
- return grahHist
- if __name__=="__main__":
- image = cv2.imread("../img/aa.jpg",cv2.IMREAD_GRAYSCALE)
- grahHist = calcGrayHist(image)
- x_range = range(256)
- plt.plot(x_range,grahHist,'-',linewidth= 3,c='k')
- #设置坐标轴的范围
- y_maxValue = np.max(grahHist)
- plt.axis([0,255,0,y_maxValue])
- #设置标签
- plt.xlabel('gray Level')
- plt.ylabel("number of pixels")
- #显示灰度直方图
- plt.show()
运行结果
线性变换
线性变换的公式为:
\[ O(r,c)=a*I(r,c)+b,0\leq r<R\; 0\leq c<W\]
图像的线性变换无疑就是利用矩阵的乘法就行线性变换, 比如一个矩阵 I ,2I,3I (np.unt8 ndarry 类型就是 unt8 类型)就是一个矩阵的变换.
- import cv2
- import numpy as np
- import sys
- if __name__=="__main__":
- img = cv2.imread("../img/ae.jpg",cv2.IMREAD_GRAYSCALE)
- a=2
- #线性变换 定义 float 类型
- O = float(a)*img
- #数据截取 如果大于 255 取 255
- O[0>255] = 255
- #数据类型的转换
- O = np.round(O)
- O = O.astype(np.uint8)
- cv2.imshow("img",img)
- cv2.imshow('enhance',O)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
运行结果:
灰度级范围越大就代表对比度越高, 反之对比度越低视觉上清晰度就越低. 我们通过 a=2 的线性对比度拉伸将灰度级范围扩大到 [0,255] 之间, 如上图我们改变灰度级的范围后图像变的清晰.
直方图正规化
将图像 O 中的最小灰度级记为 \(O_{min}\), 最大灰度级记为 \(O_{max}\), 假如输出的图像 P 的灰度级范围为[\(P_{min},P_{max}\)], 则 O 与 P 的关系为:
\[ O(r,c)=\cfrac{P_{max}-P_{min}}{O_{max}-O_{min}}(O(r,c)-O_{min})+P_{min}\]
其中 P(r,c)就代表 P 的第 r 行第 c 列的灰度值. 这个过程就是直方图的正规化. 我们一般令 P 的范围是[0,255], 所以直方图的正规化是在求 a,b 变换的值的方法, 我们可以得到:
\[ a=\cfrac{P_{max}-P_{min}}{O_{max}-O_{min}} , b=P_{min}-\cfrac{P_{max}-P_{min}}{O_{max}-O_{min}} *O_{min}\]
下面我们使用 OpenCV 来实现上面的理论:
- import cv2
- import numpy as np
- import sys
- from enhance.GrayHist import mget
- if __name__=="__main__":
- img = cv2.imread("../img/o3.jpg",cv2.IMREAD_GRAYSCALE)
- #求出 img 的最大最小值
- Maximg = np.max(img)
- Minimg = np.min(img)
- print(Maximg, Minimg, '-----------')
- #输出最小灰度级和最大灰度级
- Omin,Omax = 0,255
- #求 a, b
- a = float(Omax - Omin)/(Maximg - Minimg)
- b = Omin - a*Minimg
- print(a,b,'-----------')
- #线性变换
- O = a*img + b
- O = O.astype(np.uint8)
- #利用灰度直方图进行比较 mget 为 GrayHist 中的写方法
- mget(img)
- mget(O)
- cv2.imshow('img',img)
- cv2.imshow('enhance',O)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
### 伽玛变换 ###
将一张图的灰度值归至 [0,1] 后, 对于 8 位图来说, 除以 255 即可. 伽玛变换就是令 O(r,c)=\(I(r,c)^\gamma\),0\(\leq r<H,0\leq\)c<W.
当 \(\gamma\)等于 1 时图像不发生变换, 而当 \(\gamma\)大于 0 且小于 1 时就可以增强图像的对比度, 相反的当 \(\gamma\)大于 1 时就可以使图像对比度降低. 以下是伽玛变换在 OpenCV 中的实现:
- import cv2
- import numpy as np
- import sys
- # 伽玛变换 power 函数实现幂函数
- if __name__ == "__main__":
- img = cv2.imread("../img/ae.jpg", cv2.IMREAD_GRAYSCALE)
- # 归 1
- Cimg = img / 255
- # 伽玛变换
- gamma = 0.5
- O = np.power(Cimg,gamma)
- #效果
- cv2.imshow('img',img)
- cv2.imshow('O',O)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
运行结果:
直方图的均衡化
计算图像的灰度直方图
计算灰度直方图的累加直方图
根据累加的直方图和直方图均衡化的原理得到输入灰度级与输出灰度级之间的映射关系
使用循环的方式得到输出图像的每一个像素的灰度级
- import cv2
- import numpy as np
- from enhance.GrayHist import calcGrayHist
- # 直方图的均衡化
- if __name__ == "__main__":
- image = cv2.imread("../img/ae.jpg", cv2.IMREAD_GRAYSCALE)
- rows,cols = image.shape
- #计算灰度直方图
- grayHist = calcGrayHist(image)
- #计算累加灰度直方图
- zeroCumuMoment = np.zeros([256], np.uint32)
- for p in range(256):
- if p == 0:
- zeroCumuMoment[p] = grayHist[0]
- else:
- zeroCumuMoment[p] = zeroCumuMoment[p-1] + grayHist[p]
- #根据累加的灰度直方图得到输入与输出灰度级之间的映射关系
- output = np.zeros([256],np.uint8)
- cofficient = 256.0/(rows*cols)
- for p in range(256):
- q = cofficient * float(zeroCumuMoment[p])-1
- if q>=0:
- output[p] = np.math.floor(q)
- else:
- output[p] = 0
- #得出均衡化图像
- equalHistimg = np.zeros(image.shape,np.uint8)
- for r in range(rows):
- for c in range(cols):
- equalHistimg[r][c] = output[image[r][c]]
- cv2.imshow('image',image)
- cv2.imshow('histimage',equalHistimg)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
运行结果:
来源: https://www.cnblogs.com/supershuai/p/12436669.html