·对于部分图像,会出现整体较暗或较亮的情况,这是由于图片的灰度值范围较小,即对比度低。实际应用中,通过绘制图片的灰度直方图,可以很明显的判断图片的灰度值分布,区分其对比度高低。对于对比度较低的图片,可以通过一定的算法来增强其对比度。常用的方法有线性变换,伽马变换,直方图均衡化,局部自适应直方图均衡化等。

1. 灰度直方图及绘制

  灰度直方图用来描述每个像素在图像矩阵中出现的次数或概率。其横坐标一般为0-255个像素值,纵坐标为该像素值对应的像素点个数。如下图所示的图像矩阵(单通道灰度图,三通道时可以分别绘制),可以统计每个像素值出现的次数,也可以统计概率,统计像素值出现次数的灰度直方图如下所示。

        

    

  

  灰度直方图绘制

    a, 可以利用opencv的calcHist()统计像素值出现次数,通过matploblib的plot()绘制

    b, 可以直接利用matploblib的hist()方法     

cv2.calcHist()
参数:
img:输入图像,为列表,如[img]
channels: 计算的通道,为列表,如[]表示单通道,[,]统计两个通道
mask: 掩模,和输入图像大小一样的矩阵,为1的地方会进行统计(与图像逻辑与后再统计);无掩模时为None
histSize: 每一个channel对应的bins个数,为列表,如[]表示256个像素值
ranges: bins的边界,为列表,如[,]表示像素值范围在0-256之间
accumulate: Accumulation flag. If it is set, the histogram is not cleared in the beginning when it is allocated. This feature enables you to compute a single histogram from several sets of arrays, or to update the histogram in time.

  如下图所示,分别绘制了灰度分布曲线图,灰度分布直方图和两者叠加图形,代码如下:

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np img = cv.imread(r"C:\Users\Administrator\Desktop\maze.png",) hist = cv.calcHist([img],[],None,[],[,]) plt.subplot(,,),plt.plot(hist,color="r"),plt.axis([,,,np.max(hist)])
plt.xlabel("gray level")
plt.ylabel("number of pixels") plt.subplot(,,),plt.hist(img.ravel(),bins=,range=[,]),plt.xlim([,])
plt.xlabel("gray level")
plt.ylabel("number of pixels") plt.subplot(,,)
plt.plot(hist,color="r"),plt.axis([,,,np.max(hist)])
plt.hist(img.ravel(),bins=,range=[,]),plt.xlim([,])
plt.xlabel("gray level")
plt.ylabel("number of pixels") plt.show()

    

  c.通过np.histogram()和plt.hist()也可以计算出灰度值分布

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np img = cv.imread(r"C:\Users\Administrator\Desktop\maze.png",)
histogram,bins = np.histogram(img,bins=,range=[,])
print(histogram)
plt.plot(histogram,color="g")
plt.axis([,,,np.max(histogram)])
plt.xlabel("gray level")
plt.ylabel("number of pixels")
plt.show()

np.histogram()

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np img = cv.imread(r"C:\Users\Administrator\Desktop\maze.png",)
rows,cols = img.shape
hist = img.reshape(rows*cols)
histogram,bins,patch = plt.hist(hist,,facecolor="green",histtype="bar") #histogram即为统计出的灰度值分布
plt.xlabel("gray level")
plt.ylabel("number of pixels")
plt.axis([,,,np.max(histogram)])
plt.show()

plt.hist()

2. 对比度增强

  对比度增强,即将图片的灰度范围拉宽,如图片灰度分布范围在[50,150]之间,将其范围拉升到[0,256]之间。这里介绍下 线性变换,直方图正规化,伽马变换,全局直方图均衡化,限制对比度自适应直方图均衡化等算法。

  2.1 线性变换

    通过函数y=ax+b对灰度值进行处理,例如对于过暗的图片,其灰度分布在[0,100], 选择a=2,b=10能将灰度范围拉伸到[10, 210]。可以通过np或者opencv的convertScaleAbs()函数来实现,对应参数列表如下:   

cv2.convertScaleAbs(src,alpha,beta)
src: 图像对象矩阵
   dst:输出图像矩阵
alpha:y=ax+b中的a值
beta:y=ax+b中的b值
(对于计算后大于255的像素值会截断为255)

    使用示例代码和效果图如下:

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
print(img)
img_bright = cv.convertScaleAbs(img,alpha=1.5,beta=)
print(img_bright) cv.imshow("img",img)
cv.imshow("img_bright",img_bright)
cv.waitKey()
cv.destroyAllWindows()

convertScaleAbs()

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
a=1.5
b=
y = np.float(a)*img+b
y[y>]=
y = np.round(y)
img_bright= y.astype(np.uint8) cv.imshow("img",img)
cv.imshow("img_bright",img_bright)
cv.waitKey()
cv.destroyAllWindows()

numpy实现

(实用性:numpy自定义实现时,可以针对不同区间像素点,采用不同系数a,b来动态改变像素值) 

   

  2.2 直方图正规化

    对于上述线性变换,系数a,b需要自己摸索设置。直方图正规化的系数固定,一般将原图片的像素值范围映射到[0,255]范围内。假设原图片的像素值分布范围为Input:[min, max], 映射后的范围为Output:[0,255], 则对应的系数a=(255-0)/(max-min),  系数b=0。即计算公式:

                

    opencv提供了normalize()函数来实现灰度正规化,对应参数列表如下:

cv2.normalize(src,dst,alpha,beta,normType,dtype,mask)
参数:
src: 图像对象矩阵
dst:输出图像矩阵(和src的shape一样)
alpha:正规化的值,如果是范围值,为范围的下限 (alpha – norm value to normalize to or the lower range boundary in case of the range normalization.)
beta:如果是范围值,为范围的上限;正规化中不用到 ( upper range boundary in case of the range normalization; it is not used for the norm normalization.)
norm_type:normalize的类型
cv2.NORM_L1:将像素矩阵的1-范数做为最大值(矩阵中值的绝对值的和)
cv2.NORM_L2:将像素矩阵的2-范数做为最大值(矩阵中值的平方和的开方)
cv2.NORM_MINMAX:将像素矩阵的∞-范数做为最大值 (矩阵中值的绝对值的最大值) dtype: 输出图像矩阵的数据类型,默认为-,即和src一样
mask:掩模矩阵,只对感兴趣的地方归一化

    (对于alpha的值,不是很清楚含义,经过试验,应该是一个锚点,用像素矩阵中的范数计算出来的比例和alpha相乘,当dtype为cv2.NORM_MINMAX时,其计算公式类似如下:

            

    使用示例代码和效果图如下:

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
img_norm=cv.normalize(img,dst=None,alpha=,beta=,norm_type=cv.NORM_MINMAX)
cv.imshow("img",img)
cv.imshow("img_norm",img_norm)
cv.waitKey()
cv.destroyAllWindows()

cv.normalize()

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
out_min=
out_max= in_min = np.min(img)
in_max = np.max(img) a=float(out_max-out_min)/(in_max-in_min)
b=out_min-a*in_min
img_norm = img*a+b
img_norm = img_norm.astype(np.uint8)
cv.imshow("img",img)
cv.imshow("img_norm",img_norm)
cv.waitKey()
cv.destroyAllWindows()

numpy实现类似normalize

  2.3 伽马变换

    将输入图像的像素值除以255,归一化到[0,1]区间,然后计算其γ次方值,用公式表示如下,其中I(r,c)为归一化后的像素值,当γ=1时原像素值不影响,当0<γ<1时,增大像素值,提高图片对比度;反之γ>1时能降低图片对比度。

            

     实现代码和示例如下:

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
img_norm = img/255.0 #注意255.0得采用浮点数
img_gamma = np.power(img_norm,0.4)*255.0
img_gamma = img_gamma.astype(np.uint8) cv.imshow("img",img)
cv.imshow("img_gamma",img_gamma)
cv.waitKey()
cv.destroyAllWindows()

numpy实现伽马变换

   2.4 全局直方图均衡化

   直方图均衡化的目的是将原图片每个像素值的像素点个数进行重新分配到[0,255]的256个像素值上,使得每个像素值对应的像素点个数近似相等,即重新分配后,0-255的每个像素值对应的像素点个数近似为(rows*cols/256),(直方图均衡化对应的数学原理参考:https://blog.csdn.net/superjunenaruto/article/details/52431941)。opencv里面equalizeHist()函数实现了相应的功能,只能处理单通道数据,参数列表如下:

cv2.equalizeHist(src,dst)
src: 图像对象矩阵,必须为单通道的uint8类型的矩阵数据
dst:输出图像矩阵(和src的shape一样)

   实现代码和示例如下:

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import math img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg",)
img_equalize = cv.equalizeHist(img)
cv.imshow("img",img)
cv.imshow("img_equalize",img_equalize)
cv.waitKey()
cv.destroyAllWindows()

opencv equalizeHist()

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import math #统计灰度分布
def calc_hist(img):
rows,cols = img.shape[:]
hist=np.zeros(,np.uint64) #注意此处的数据格式不要用np.uint8,会溢出但不报错
for r in range(rows):
for c in range(cols):
hist[img[r,c]]+= return hist def equalize_hist(img):
rows,cols = img.shape[:]
hist = calc_hist(img) #计算灰度累积分布
hist_sum=np.zeros([],np.uint32) #注意数据类型为np.uint32,防止溢出
for i in range():
if i==:
hist_sum[i]=hist[i]
else:
hist_sum[i] = hist[i]+hist_sum[i-] #输出图像的灰度分布
output_hist = np.zeros(,np.uint8)
cofficient= 256.0/(rows*cols)
for i in range():
q = cofficient*float(hist_sum[i])-
if q>=:
output_hist[i]=math.floor(q)
else:
output_hist[i]= #输出图像的像素值
output_img=np.zeros([rows,cols],np.uint8)
for r in range(rows):
for c in range(cols):
output_img[r,c]=output_hist[img[r,c]] return output_img if __name__=="__main__":
img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg",)
img_equalize=equalize_hist(img)
cv.imshow("img",img)
cv.imshow("img_equalize",img_equalize)
cv.waitKey()
cv.destroyAllWindows()

使用numpy实现equalizeHist

(通过numpy实现equalizeHist的算法思路参见直方图均衡化的数学原理,这里没写出。。。。。)

   2.5 限制对比度自适应直方图均衡化

      相比全局直方图均衡化,自适应直方图均衡化将图像划分为不重叠的小块,在每一小块进行直方图均衡化,但若小块内有噪声,影响很大,需要通过限制对比度来进行抑制,即限制对比度自适应直方图均衡化。如果限制对比度的阈值设置会40,在局部直方图分布中某个像素值出现次数为45,那么多出的5次像素点会被去掉,平均成其他像素值,如图所示:

        

opencv通过createCLAHE()和apply()函数来实现,其对应参数如下:

clahe=cv2.createCLAHE(clipLimit,tileGridSize)
clipLimit:限制对比度的阈值,默认为40,直方图中像素值出现次数大于该阈值,多余的次数会被重新分配
tileGridSize:图像会被划分的size, 如tileGridSize=(,),默认为(,) calhe.apply(img) #对img进行限制对比度自适应直方图均衡化

      代码示例和效果如下:(实际使用中可以先去噪声,再进行对比度增强)

#coding:utf-

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import math img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg",)
clahe = cv.createCLAHE(,(,))
dst = clahe.apply(img)
cv.imshow("img",img)
cv.imshow("dst",dst)
cv.waitKey()
cv.destroyAllWindows()

createCLAHE()

参考:

  官方文档:https://www.docs.opencv.org/4.1.0/

(二)OpenCV-Python学习—对比度增强的更多相关文章

  1. 二、python学习-函数

    类型判断 1.type()直接获取类型 2.isinstance 用法一:isinstance(值,类型) 返回真或假 用法二:isinstance(值,(类型1,类型2 ...)) 有一个类型满足 ...

  2. (二)Python 学习第二天--爬5068动漫图库小案例

    (注:代码和网站仅仅是学习用途,非营利行为,源代码参考网上大神代码,仅仅用来学习

  3. python入门灵魂5问--python学习路线,python教程,python学哪些,python怎么学,python学到什么程度

    一.python入门简介 对于刚接触python编程或者想学习python自动化的人来说,基本都会有以下python入门灵魂5问--python学习路线,python教程,python学哪些,pyth ...

  4. OpenCV之Python学习笔记

    OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...

  5. Python学习(二)Python 简介

    Python 简介 官方指南及文档 Python2.7官方指南(中文版):http://pan.baidu.com/s/1dDm18xr Python3.4官方指南(中文版):http://pan.b ...

  6. python学习_数据处理编程实例(二)

    在上一节python学习_数据处理编程实例(二)的基础上数据发生了变化,文件中除了学生的成绩外,新增了学生姓名和出生年月的信息,因此将要成变成:分别根据姓名输出每个学生的无重复的前三个最好成绩和出生年 ...

  7. 【Python学习笔记之二】浅谈Python的yield用法

    在上篇[Python学习笔记之一]Python关键字及其总结中我提到了yield,本篇文章我将会重点说明yield的用法 在介绍yield前有必要先说明下Python中的迭代器(iterator)和生 ...

  8. Python学习二:词典基础详解

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7862377.html 邮箱:moyi@moyib ...

  9. python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码

    python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...

随机推荐

  1. Node.js 实现 MySQL 数据库增删改查

    安装mysql $ npm isntall mysql 连接数据库 需要根据实际配置修改数据库用户名.及密码及数据库名 let mysql = require('mysql'); let connec ...

  2. 【OEM】OEM安装维护

    [OEM]OEM安装维护 一.1  BLOG文档结构图       一.2  前言部分   一.2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道 ...

  3. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

  4. iniparser——C配置文件解析库

    简介 ini文件则是一些系统或者软件的配置文件,iniparser是免费.独立的INI解析器,Github地址(也是主要更新地址)请点击这个,官网上的tarball版本比较老,主要是为了保留之前的di ...

  5. Python Image库简单处理图像

    直接列举几个常用的函数,可在 http://effbot.org/imagingbook/image.htm 中查看更多相关函数. from PIL import Image import numpy ...

  6. PEP 8016-Python之父重回决策层

      PEP 8016-Python之父重回决策层 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 去年,技术社区里还发生了一件大事:Linux 之父 Linus Torvalds 宣 ...

  7. Pthon面向对象-特殊属性

    Pthon面向对象-特殊属性 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.特殊属性 #!/usr/bin/env python #_*_conding:utf-8_*_ ...

  8. 对 Jenkins+ANT+Jmeter 接口测试的实践

    转载地址:https://testerhome.com/topics/5262 1.前言 最近感觉大家都在讲Jenkins+jmeter+ant或maven的使用,但没有说到具体怎么投入到项目使用,只 ...

  9. hive 初始化数据库报错

    安装hive,初始化数据库的时候报错 schematool -dbType mysql -initSchema Metastore Connection Driver : com.mysql.cj.j ...

  10. 用OKR提升员工的执行力

    很多管理者在公司管控的过程中常常出现一种乏力的感觉,觉得很多事情推进不下去,结果总是令人不满意.管理者总是会吐槽,“员工执行力差!”而此时大部分管理者会认为公司执行力差是员工能力和态度的问题. 事实上 ...