栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

17-直方图

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

17-直方图

直方图

何为直方图?没那么高大上,其实就是二维统计图。每个照片都是有像素点所组成,当然也是[0,255],直方图就是统计每个值所对应的像素点有几个。
直方图横坐标表示0-255这些像素点值;纵坐标表示对应像素点值的个数有多少个,例如:像素为55的像素点有多少个
cv2.calcHist(images,channels,mask,histSize,ranges)
cv2.calcHist([img],[0],None,[256],[0,256])

参数一:images:原图像格式为uint8或float32;当传入函数时应该用中括号括住,通常情况下都是输入的是灰度图
参数二:同样用中括号括起来,它会告诉函数我们图像的直方图;如果输入图像时灰度图它的值就是[0];如果时彩色图像传入的参数可以是[0][1][2],分别对应BGR
参数三:掩模图像,说白了就是取部分图像而已;统计整个图像的直方图时就把它设置为None;当然也可以通过掩模来统计图像的某部分的直方图
参数四:BIN的数目,也就是横坐标的总量程而已,一般都是256,也就是0-255这256个像素点值,也需要用中括号括起来
参数五:像素值的范围,一般设置为[0,256]
import cv2
import numpy as np
from matplotlib import pyplot as plt

def show_photo(name,picture):#图像显示函数
    cv2.imshow(name,picture)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
img = cv2.imread('E:Jupyter_workspacestudydata/cat.png',0)#这里的参数0表示以灰度图进行读取
hist = cv2.calcHist([img],[0],None,[256],[0,256])#当然由于是灰度图通道数也只有一个即参数二[0];参数三None表示没有使用掩模直接输出整体图像的直方图;参数四[256]直方图的横坐标量程;参数五[0,256]像素值的范围
hist.shape#结果为:(256, 1) 其中256表示这个图像中有0-255这256个取值,1表示得到的直方图是二维的,即每个像素出现多少个

plt.hist(img.ravel(),256)
plt.show()


img = cv2.imread('E:Jupyter_workspacestudydata/cat.png')#第二个参数不填表示原图输入,这个图像为彩色图也就是彩色图输入
color = ('b','g','r')
for i,col in enumerate(color):#枚举格式遍历每个颜色通道
    histr = cv2.calcHist([img],[i],None,[256],[0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

原图:

原图对应的灰度图的直方图:

原图的BGR直方图:

掩模mask

np.zeros(img.shape[:2],np.uint8)
上面的函数中有掩模的操作,接下来介绍一下掩模mask的定义的操作

import cv2
import numpy as np
from matplotlib import pyplot as plt

def show_photo(name,picture):#图像显示函数
    cv2.imshow(name,picture)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
#创建mast,掩模是由黑白两部分组成的,然后与原图重叠,掩模白色区域对应原图区域不变,黑色区域对应原图区域变黑
mask = np.zeros(img.shape[:2],np.uint8)#这里面的掩码实际上就是边缘黑中间白,此时的mask就和原图片大小相同,uint8表示无符号八位整数0-255之间
print(mask.shape)#结果为:(321, 287)
mask[50:200,50:200] = 255#要保存的东西是白色的,白色区域为要保存的地方,所以将选取地方置为255
show_photo('mask',mask)

img = cv2.imread('E:Jupyter_workspacestudydata/cat.png',0)#灰度图读取照片
print(img.shape)#结果为:(321, 287)
show_photo('img',img)

masked_img = cv2.bitwise_and(img,img,mask=mask)#与操作,也就是有0则0,黑色为0所以说掩码黑色地区都为黑;参数一表示原图像,参数三表示掩模图像
show_photo('masked_img',masked_img)

hist_full = cv2.calcHist([img],[0],None,[256],[0,256])#不带掩模的图像进行统计直方图
hist_mask = cv2.calcHist([img],[0],mask,[256],[0,256])#带掩模mask的时候统计图像的部分掩模区域的直方图

plt.subplot(221),plt.imshow(img,'gray')
plt.subplot(222),plt.imshow(mask,'gray')
plt.subplot(223),plt.imshow(masked_img,'gray')
plt.subplot(224),plt.plot(hist_full),plt.plot(hist_mask)
plt.xlim([0,256])
plt.show()

掩模图像:

原图:

掩模操作后的图像:

上一:原图
上二:自定义的掩模
下一:掩模对应的原图部分
下二:蓝线对应原图的直方图,橙线对应掩模处理的部分原图的直方图

直方图均衡化

假设某图片部分像素值为:

25512820050
5020025550
255200128128
20020025550

下面表格中的函数映射中(255-0)表示设置的横轴的量程这里设置的是0-255

灰度值像素个数概率累积概率根据函数映射后灰度值取整
5044/16 = 0.250.250.25*(255-0)=63.7564
12833/16 = 0.18750.25+0.1875=0.43750.4375*(255-0)=111.5625112
20055/16 = 0.31250.25+0.1875+0.3125=0.750.75*(255-0)=191.25191
25544/16 = 0.250.25+0.1875+0.3125+0.25=11*(255-0)=255255

均衡化后的像素值为:

25511219164
6419125564
255191112112
192191255255

均衡化之后发现了这16个数相差的并不是特别大了

cv2.equalizeHist(img)
传入图像对象名称即可进行整体均衡化

import cv2
import numpy as np
from matplotlib import pyplot as plt

def show_photo(name,picture):#图像显示函数
    cv2.imshow(name,picture)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
img = cv2.imread('E:Jupyter_workspacestudydata/people.jpg',0)
plt.hist(img.ravel(),256)#原图像的直方图
plt.show()

equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)#均衡化后的直方图
plt.show()

res = np.hstack((img,equ))
show_photo('img_equ',res)#显示原图和均衡化后的图片

原图直方图:

均衡化后的直方图:

原图和均衡化后的图片对比:

均衡化后的图像脸上的细节变得更加模糊了,尴尬不??? 这时候就需要自定义均衡化 自定义均衡化

直方图的均衡化也就是整体的均衡化,其他像素点值大的地方给平均给其他地方了导致一下细节会丢失
若将原图分成块进行均衡化,每块进行自己块的均衡化效果会比全局整体均衡化更好些
当然,若图像里面噪音太大,局部反而没有整体均衡化好,需要自己事先去衡量一下
cv2.createCLAHE(clipLimit = 2.0,tileGridSize = (8,8))
(8,8)表示分块均衡化中块的大小

import cv2
import numpy as np
from matplotlib import pyplot as plt

def show_photo(name,picture):#图像显示函数
    cv2.imshow(name,picture)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
img = cv2.imread('E:Jupyter_workspacestudydata/people.jpg',0)
plt.hist(img.ravel(),256)#原图像的直方图

equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)#均衡化后的直方图

clahe = cv2.createCLAHE(clipLimit = 2.0,tileGridSize = (8,8))#自定义均衡化,每8*8分成块,按块进行均衡化
res_clahe = clahe.apply(img)

res = np.hstack((img,equ,res_clahe))
show_photo('img_equ_clahe',res)

原图-整体均衡化-自定义均衡化

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/326831.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号