python opencv图像处理对比度增强--暗变亮-各类实现方法
python opencv图像对比度增强--暗变亮
import math import numpy as np import cv2 from datetime import datetime import matplotlib.pyplot as plt from PIL import Image,ImageDraw,ImageFont from PIL import Image, ImageDraw, ImageFont def ShowHistPLt(img): ''' 显示灰度直方图 ''' grayHist = calcGrayHist(img) #画出灰度直方图 x_range = range(256) plt.plot(x_range,grayHist,'r',linewidth = 2, c ='blue') #设置坐标轴的范围 y_maxValue=np.max(grayHist) plt.axis([0,255,0,y_maxValue]) #设置坐标轴的标签 plt.xlabel('gray level') plt.ylabel('number of pixels') #显示灰度直方图 plt.show() def print_hi(str): print('hi,'+str) def print_with_datetime(str): time3 = datetime.now() time_str = time3.strftime("%Y-%m-%d %H:%M:%S") time_str+=str print(time_str) def print_3(str): print('hi3,'+str) def calcGrayHist(image): ''' 代码实现:计算灰度直方图 ''' rows,cols= image.shape grayHist = np.zeros([256],np.uint64) for r in range(rows): for c in range(cols): grayHist[image[r][c]]+=1 return grayHist def equalHist(image): ''' 直方图均衡化 ''' rows,cols = image.shape #step 1 计算灰度直方图 grayHist = calcGrayHist(image) #step 2 计算累加灰度直方图 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] #step3:根据累加灰度直方图得到输入灰度级与输出灰度级之间的映射关系 outPut_q = 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_q[p] = math.floor(q) else: outPut_q[p] = 0 #step 4:得到直方图均衡化后的图像 equalHistImage = np.zeros(image.shape,np.uint8) for r in range(rows): for c in range(cols): equalHistImage[r][c] = outPut_q[image[r][c]] return equalHistImage def cv2_chinese_text(img, text, left, top, text_color=(0, 0, 255)): text_size = 18 # 判断是否OpenCV图片类型 if (isinstance(img, np.ndarray)): img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 创建一个可以在给定图像上绘图的对象 draw = ImageDraw.Draw(img) # 字体的格式 font_style = ImageFont.truetype("simfang.ttf", text_size, encoding="utf-8") # 绘制文本 draw.text((left, top), text, text_color, font=font_style) # 转换回OpenCV格式 return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR) if __name__ == "__main__": time3 = datetime.now() time_str = time3.strftime("%Y-%m-%d %H:%M:%S") print(time3) print(time_str) print_hi(time_str+' 极坐标') print(time_str+' 坐标11,13以0,0为中心极坐标转换') I = cv2.imread(r'bus_way.png', cv2.IMREAD_GRAYSCALE) # grayHist = calcGrayHist(I) # #画出灰度直方图 # x_range = range(256) # plt.plot(x_range,grayHist,'r',linewidth = 2, c ='blue') # #设置坐标轴的范围 # y_maxValue=np.max(grayHist) # plt.axis([0,255,0,y_maxValue]) # #设置坐标轴的标签 # plt.xlabel('gray level') # plt.ylabel('number of pixels') # #显示灰度直方图 # plt.show() #matplotlib函数 hist实现计算直方图 #得到图像矩阵的高rows和宽column rows,cols = I.shape #将二维的图像矩阵变为一维的数组,便于计算灰度直方图 pixelSequence = I.reshape([rows*cols,]) #组数 numberBins = 256 #计算灰度直方图 histogram,bins,patch = plt.hist(pixelSequence,numberBins,facecolor ='blue', histtype='bar') #设置坐标轴的标签 plt.xlabel(u'gray level') plt.ylabel(u'number of pixels.') #设置坐标轴的范围 y_maxValue = np.max(histogram) plt.axis([0,255,0,y_maxValue]) #plt.show() ''' 图像对比度是通过灰度级范围来度量的,而灰度级范围可通过观察灰度直方图得 到,灰度级范围越大代表对比度越高;反之,对比度越低,低对比度的图像在视觉上给 人的感觉是看起来不够清晰,所以通过算法调整图像的灰度值,从而调整图像的对比度 是有必要的。最简单的一种对比度增强方法是通过灰度值的线性变换来实现的。 ''' #线性变换,图像增强 a = 2 Or=float(a)*I #进行数据截断,大于255的值截为255 Or[Or>255] = 255 #数据类型转换 Or = np.round(Or) Or = Or.astype(np.uint8) #显示原图盒线性变换后的效果 #cv2.imshow('yuantu',I) #cv2.imshow("Or", Or) #cv2.waitKey(0) #cv2.destroyAllWindows #直方图正规化,图像增强,增加对比度,暗的部分变亮一些,代码实现 Imax = np.max(I) Imin = np.min(I) #输出最小灰度级最大灰度级 Omin,Omax = 0, 255 #计算a和b值 a = float(Omax-Omin)/(Imax-Imin) b = Omax - a*Imin #矩阵的线性变换 Ori = a*I +b #数据类型转换 Ori=Ori.astype(np.uint8) # cv2.imshow('ori',Ori) # cv2.waitKey(0) # cv2.destroyAllWindows() ##直方图正规化,图像增强,增加对比度,暗的部分变亮一些,API实现,灰度值线性变换 I2 = I func_dst = cv2.normalize(I,I2,255,0,cv2.NORM_MINMAX,cv2.CV_8U) #图片添加中文英文显示日期 func_dst_add_text = cv2_chinese_text(func_dst,"直方图正规化"+time_str,0,0) # cv2.imshow('yuantu',I) # cv2.imshow('func_dst',func_dst_add_text) # cv2.waitKey(0) # cv2.destroyAllWindows() #增加图像对比度的非线性变换——伽马变换-伽马变换实质上是对图像矩阵中的每一个值进行幂运算 Mi = np.array([[1,2],[3,4]]) Mi_mat = np.power(Mi,2)#2是求平方,3求立方值 print_with_datetime('矩阵的平方值:\n') #print(Mi_mat) print_with_datetime('图像归一化:\n') fi= I/255.0 #伽马变换 gama = 0.5 mat_gama=np.power(fi,gama) # cv2.imshow('mat_gama',mat_gama) # cv2.waitKey(0) # cv2.destroyAllWindows() ''' 对于直方图均衡化的实现主要分四个步骤: 第一步:计算图像的灰度直方图。 第二步:计算灰度直方图的累加直方图。 第三步:根据累加直方图和直方图均衡化原理得到输入灰度级和输出灰度级之间的 映射关系。 第四步:根据第三步得到的灰度级映射关系,循环得到输出图像的每一个像素的灰 度级 ''' equal_mat=equalHist(I) #cv2.imshow('I',I) cv2.imwrite('junhenghua.jpg',equal_mat) # cv2.imshow('equal_mat',equal_mat) # cv2.waitKey(0) # cv2.destroyAllWindows() ''' 理解了直方图均衡化原理,就可以轻松掌握OpenCV实现的直方图均衡化函数 equalize-Hist,其使用方法很简单,只支持对8位图的处理。虽然全局直方图均衡化方法 对提高对比度很有效,但是均衡化处理以后暗区域的噪声可能会被放大,变得清晰可 见,而亮区域可能会损失信息。为了解决该问题,提出了自适应直方图均衡化(Aptive Histogram Equalization)方法 ''' #ShowHistPLt(equal_mat) #创建CLAHE对象 clahe = cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8)) #限制对比度的自适应阈值均衡化 dst_clahe = clahe.apply(I) dst_clahe = cv2_chinese_text(dst_clahe,"自适应直方图均衡化",0,0) cv2.imshow('dst_clahe',dst_clahe) cv2.waitKey(0) cv2.destroyAllWindows() ''' 对比度增强只是图像增强方法中的一种手段,本章中提到的对比度拉伸的方法受图 像噪声的影响会很明显,后面会介绍去除噪声的方法,去噪之后再使用对比度增 强技术效果会更好 '''
欢迎讨论,相互学习。
cdtxw@foxmail.com