本次环境为Python3
目的:
- 掌握OPENCV中空域图像增强的一些基本方法
- 理解图像基于空域像素的处理:图像像素灰度级、点运算、逻辑运算、几何运算
- 理解图像直方图均衡化空域增强的基本原理
- 理解图像的空间滤波增强的基本原理和方法:平滑空间滤波、锐化空间滤波处理;比较不同滤波器处理的效果和优缺点
原理:
图像的点运算:
是图像处理中相对处理基础的技术,主要用于改变一幅图像的灰度分布范围,点运算通过变换函数将图像的像素一一转换,最终构成一副新的图像。
代数运算:
指对两幅或两幅以上的输入图像的对应像元逐个地进行和、差、积、商的四则运算,以产生有增强效果的图像。作为一种比较简单和有效的增强处理,是遥感图像增强处理中常用的一种方法。
几何运算:
改变图像中物体对象之间的空间关系,可分为位置变换、形状变换及复合变换。
直方图增强:
直方图均衡化:利用直方图统计的结果,通过使图像的直方图均衡把原始图像的直方图变换成均匀分布的样式,增加了像素灰度值的动态范围,从而增强图像整体对比度的效果。
直方图规定化:使原始图像灰度直方图变成规定形状的直方图,是对直方图均衡化的一种扩展,来增强特定灰度级别分布范围内的图像。
空域平滑滤波:
基于邻域处理的增强来减弱或消除图像中高频率的分量,但不影响低频率的分量。因为高频分量对应图像中的区域边缘等灰度值具有较大、变化较快的部分,平滑滤波将这个分量滤除可以减少局部灰度的起伏,使图像变得平滑。经常用于模糊处理和减小噪声。
空域锐化滤波:
基于邻域处理的增强来减弱或消除图像中的低频分量,但不影响高频分量。因为低频分量对应图像中灰度值变化缓慢区域,因而与图像的整体特性如整体对比度和平均灰度值有关。锐化滤波能使图像反差增加,边缘明显,可用于增强图像中被模糊的细节或景物边缘。
内容或步骤:
对“lena.jpg”变换后的灰度图像进行如下操作:
1.统计每个灰度级(0-255)的像素点数,并打印显示;
思路:把处理好的图像的每个像素点的灰度级存入一个列表中,统计这个列表里不同元素的个数值即可(list.count()函数),中间用到了集合进行转换。
2.实现幂律变换,并显示;(s=crγ )将其封装为一个函数,公式中的参数(c, g)作为函数参数传入)
思路:输入c, g的值传入转换函数,在函数内利用np.zeros()创建一个和原图像大小相同的行列矩阵,原图像经过数学变换后的值依次放入矩阵中,矩阵经过归一化(cv2.normalize())与类型转化(cv2.convertScaleAbs())后,传回主函数并显示。
3.用双线性插值将图像放大1.5倍和缩小0.8倍,并显示
思路: img_big=cv2.resize(img,None,fx=1.5,fy=1.5)#将图片放大1.5倍
利用resize()函数,将图像x,y方向要变换的参数如上所示传入函数,默认插值方式为双线性插值,None处也可变为(0,0)
4.将图像进行直方图均衡化处理,显示图像及其直方图;
思路:先通过equalizeHist()函数将灰度图进行直方图均衡化处理,再利用calcHist()计算处理后图像的直方图,最后利用pyplot模块作图
5.分别以3x3、7x7模板进行均值滤波(或中值滤波)处理,并显示;
思路:img_3=cv2.blur(img,(3,3))
利用cv2.blur()函数对图像进行均值滤波处理,其中(3,3)为进行均值滤波的方框大小
6.分别使用拉普拉斯算子和Sobel算子对图像进行锐化处理,并显示。
思路:img_L=cv2.Laplacian(img,-1)
img_s=cv2.Sobel(img,cv2.CV_16S,1,0)
img_S=cv2.convertScaleAbs(img_s)
利用Laplacian()函数对图像进行拉普拉斯算子处理,-1表示采用与原图像相同的深度。
利用Sobel()函数对图像进行Sobel算子处理。cv2.CV_16S是因为函数求完导后用8位无符号数无法完全表示,因此采用16位有符号的数据类型。处理后利用convertScaleAbs()转化为原来的uint8形式。
源码:
1.
import cv2
def main():
img_gray=cv2.imread(r'.\lena.jpg',cv2.IMREAD_GRAYSCALE)#在读取图像的时候直接处理成灰度图
list_all = []
set_all=()
sum=0
for i in range(img_gray.shape[0]):#图片的行
for j in range(img_gray.shape[1]):#图片的列
list_all.append(img_gray[i][j])
set_all=set(list_all)
for i in set_all:
print('灰度级为 {} 的像素点个数为:{}'.format(i,list_all.count(i)))
if __name__ == '__main__':
main()
2.
import math
import numpy as np
import cv2
def gammaTranform(c,y,image):
h, w = image.shape[0], image.shape[1]
new_img = np.zeros((h,w),dtype=float)#numpy.zeros创建一个行列矩阵,填充为int类型
for i in range(h):
for j in range(w):
new_img[i,j] = c*math.pow(image[i, j], y)#math.pow用来求幂
cv2.normalize(new_img, new_img, 0, 255, cv2.NORM_MINMAX)#归一化处理,将计算后的值重新归到(0,255)之间
new_img = cv2.convertScaleAbs(new_img)#将原图像的像素值均转化成类型为np.uint8
return new_img
def main():
c = float(input("请输入c的值:"))#此处输入的是字符串,切记转化为整型
y = float(input("请输入y(伽马)的值:"))#y值小于1时,会拉伸图像中灰度级较低的区域,同时会压缩灰度级较高的部分
#y值大于1时,会拉伸图像中灰度级较高的区域,同时会压缩灰度级较低的部分
img_gray= cv2.imread(r'.\lena.jpg', cv2.IMREAD_GRAYSCALE)
new_img = gammaTranform(c,y, img_gray)
cv2.imshow("orignalLena", img_gray)
cv2.imshow("changedLena",new_img)
cv2.waitKey(0)
if __name__ == '__main__':
main()
3.
import cv2
def main():
img = cv2.imread(r'.\lena.jpg', cv2.IMREAD_GRAYSCALE)
img_big=cv2.resize(img,None,fx=1.5,fy=1.5)#默认interpolation=INTER_LINEAR即双线性插值
img_small=cv2.resize(img,None,fx=0.8,fy=0.8)#None也可填(0,0)
cv2.imshow("img_big",img_big)
cv2.imshow("img_small",img_small)
cv2.imshow("orignal",img)
cv2.waitKey(0)
if __name__ == '__main__':
main()
4.
import cv2
from matplotlib import pyplot as plt
def main():
img = cv2.imread(r'.\lena.jpg', cv2.IMREAD_GRAYSCALE)
histImg = cv2.equalizeHist(img)
cv2.imshow("histImg",histImg)#直方图均衡化处理后的图
hist=cv2.calcHist([histImg],[0],None,[256],[0,256])#计算图像直方图
plt.figure()#新建一个图像
plt.title("HistImage after equallizeHist")#图像的标题
plt.xlabel("Bins")#X轴标签
plt.ylabel("#of Pixels")#Y轴标签
plt.plot(hist)#画图
plt.xlim([0, 256])#设置x坐标轴范围
plt.show()#显示图像
cv2.waitKey()
if __name__ == '__main__':
main()
5.
import cv2
def main():
img = cv2.imread(r'.\lena.jpg', cv2.IMREAD_GRAYSCALE)
img_3=cv2.blur(img,(3,3))
img_7=cv2.blur(img,(7,7))
cv2.imshow("orignal",img)
cv2.imshow("3*3",img_3)
cv2.imshow("7*7",img_7)
cv2.waitKey()
if __name__ == '__main__':
main()
6.
import cv2
def main():
img = cv2.imread(r'.\lena.jpg', cv2.IMREAD_GRAYSCALE)
img_L=cv2.Laplacian(img,-1)#拉普拉斯算子 -1表示采用与原图像相同的深度
img_s=cv2.Sobel(img,cv2.CV_16S,1,0)
#Sobel函数求完导数后会有负值,还会有大于255的值。
# 而原图像是uint8,即8位无符号数,Sobel建立的图像位数不够,会有截断。
# 因此要使用16位有符号的数据类型,即cv2.CV_16S。
img_S=cv2.convertScaleAbs(img_s)
#将转回原来的uint8形式img_s
cv2.imshow("orignal",img)
cv2.imshow("Laplacian",img_L)
cv2.imshow("Sobel",img_S)
cv2.waitKey()
if __name__ == '__main__':
main()
总结:
对于图像的增强有了比较直观的认识,掌握了python环境下的图像增强方法。实验在有了思路后并不难,但是涉及到一些知识点的查找与深入会使得实验所花时间较多。