Opencv-Python学习笔记七——图像直方图 calcHist,直方图均衡化equalizeHist

图像直方图

tutorial_py_histogram

直方图是对图像像素的统计分布,它统计了每个像素(0到L-1)的数量。
直方图均衡化就是将原始的直方图拉伸,使之均匀分布在全部灰度范围内,从而增强图像的对比度。
直方图均衡化的中心思想是把原始图像的的灰度直方图从比较集中的某个区域变成在全部灰度范围内的均匀分布。

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) #返回hist

  • 第一个参数必须用方括号括起来。
  • 第二个参数是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道;
  • 第三个参数是Mask,这里没有使用,所以用None。
  • 第四个参数是histSize,表示这个直方图分成多少份(即多少个直方柱)。第二个例子将绘出直方图,到时候会清楚一点。
  • 第五个参数是表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。

最后是两个可选参数,由于直方图作为函数结果返回了,所以第六个hist就没有意义了(待确定) 最后一个accumulate是一个布尔值,用来表示直方图是否叠加。

要理解直方图,绕不开“亮度”这个概念。人们把照片的亮度分为0到255共256个数值,数值越大,代表的亮度越高。其中0代表纯黑色的最暗区域,255表示最亮的纯白色,而中间的数字就是不同亮度的灰色。人们还进一步把这些亮度分为了5个区域,分别是黑色,阴影,中间调,高光和白色。

直方图中柱子的高度,代表了画面中有多少像素是那个亮度,其实就可以看出来画面中亮度的分布和比例.

直方图

灰度直方图

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

img = cv2.imread('dark.jpg')

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

plt.imshow(img_gray, cmap=plt.cm.gray)

hist = cv2.calcHist([img], [0], None, [256], [0, 256])

plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.xlim([0, 256])
plt.show()
灰度直方图

颜色直方图

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

img = cv2.imread('image800.jpg')

chans = cv2.split(img)
colors = ('b', 'g', 'r')

plt.figure()
plt.title("’Flattened’ Color Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")

for (chan, color) in zip(chans, colors):
    hist = cv2.calcHist([chan], [0], None, [256], [0, 256])
    plt.plot(hist, color = color)
    plt.xlim([0, 256])
plt.show()  
calcHist

多通道的直方图

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

img = cv2.imread('person.jpg')

# Matplotlib有一个绘制直方图的函数:matplotlib.pyplot.hist() 
plt.hist(img.ravel(),256,[0,256])
plt.show()

chans = cv2.split(img)
colors = ('b', 'g', 'r')

fig = plt.figure(figsize=(15, 5))
ax = fig.add_subplot(131)
hist = cv2.calcHist([chans[1], chans[0]], [0, 1], None,
     [32, 32], [0, 256, 0, 256])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for G and B")
plt.colorbar(p)

ax = fig.add_subplot(132)
hist = cv2.calcHist([chans[1], chans[2]], [0, 1], None,
     [32, 32], [0, 256, 0, 256])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for G and R")
plt.colorbar(p)

ax = fig.add_subplot(133)
hist = cv2.calcHist([chans[0], chans[2]], [0, 1], None,
 [32, 32], [0, 256, 0, 256])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for B and R")
plt.colorbar(p)

print("2D histogram shape: {}, with {} values".format(hist.shape, hist.flatten().shape[0]))

hist = cv2.calcHist([img], [0, 1, 2],
 None, [8, 8, 8], [0, 256, 0, 256, 0, 256])
print("3D histogram shape: {}, with {} values".format(hist.shape, hist.flatten().shape[0]))
2D histogram

掩膜直方图

%matplotlib inline
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('dark.jpg', 0)
 
# create a mask  应用遮罩
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv.bitwise_and(img, img, mask=mask)
 
#Calculate histogram with mask and without mask
# Check third argument for mask
"""
蒙板(掩模) 
将要统计的部分设置成白色,其他部分设置成黑色,就构成了蒙板。然后传递给原图像即可
"""
hist_full = cv.calcHist([img], [0], None, [256], [0,256])
hist_mask = cv.calcHist([img], [0], mask, [256], [0,256])
 
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, color='r'), plt.plot(hist_mask, color='b')
plt.xlim([0,256])
plt.tight_layout()
plt.show()
mask-histogram

通过方法计算彩色图片的各通道直方图

# 彩色图像不同通道的直方图
%matplotlib inline
import cv2    
import numpy as np    
    
img = cv2.imread("person.jpg")    
b, g, r = cv2.split(img) 

def calcAndDrawHist(image, color):  
    hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])  
    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)  
    histImg = np.zeros([256,256,3], np.uint8)  
    hpt = int(0.9* 256);  
      
    for h in range(256):  
        intensity = int(hist[h]*hpt/maxVal)  
        cv2.line(histImg,(h,256), (h,256-intensity), color)  
          
    return histImg; 


histImgB = calcAndDrawHist(b, [255, 0, 0])  
histImgG = calcAndDrawHist(g, [0, 255, 0])  
histImgR = calcAndDrawHist(r, [0, 0, 255])  

plt.figure(figsize=(8, 6))
plt.subplot(221)
plt.imshow(img[:,:,::-1]); plt.title('origin')
plt.subplot(222)
plt.imshow(histImgB[:,:,::-1]); plt.title('histImgB')
plt.subplot(223)
plt.imshow(histImgG[:,:,::-1]); plt.title('histImgG')
plt.subplot(224)
plt.imshow(histImgR[:,:,::-1]); plt.title('histImgR')

plt.tight_layout()
plt.show()
image.png

直方图均衡

cv2.equalizeHist()

直方图均衡化就是将原始的直方图拉伸,使之均匀分布在全部灰度范围内,从而增强图像的对比度。
直方图均衡化的中心思想是把原始图像的的灰度直方图从比较集中的某个区域变成在全部灰度范围内的均匀分布。旨在使得图像整体效果均匀,黑与白之间的各个像素级之间的点更均匀一点。

image.png

灰度直方图均衡

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

img = cv2.imread('dark.jpg',0)
# histogram equalization
equ = cv2.equalizeHist(img)
# 两个图片的像素分布连接在一起,拍成一维数组
res = np.hstack((img,equ))

plt.figure(figsize=(8, 6))
ax1 = plt.subplot2grid((2,2),(0, 0))
ax1.imshow(img, cmap=plt.cm.gray)
ax1.set_title('orignal image')

ax1 = plt.subplot2grid((2, 2), (0, 1))
ax1.imshow(equ, cmap=plt.cm.gray)
ax1.set_title('equalization')

ax1 = plt.subplot2grid((2, 2), (1, 0), colspan=3, rowspan=1)
ax1.imshow(res, cmap=plt.cm.gray)
ax1.set_title('horizational')

plt.tight_layout()
plt.show()
gray_equalizeHist

彩色图像直方图均衡

在OpenCV中,彩色的图像其实是用一个多通道数组来存储的,每个单通道数组中的元素的取值范围都是0到255。这与灰度图中像素的变化范围是相同的。因此对彩色图像进行直方图均衡化只要先将彩色图像分解成若干通道,然后这些通道分别进行直方图均衡化,最后合并所有通道即可。

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

def hisEqulColor(img):
    ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
    channels = cv2.split(ycrcb)
    print(len(channels))
    cv2.equalizeHist(channels[0], channels[0])
    cv2.merge(channels, ycrcb)
    cv2.cvtColor(ycrcb, cv2.COLOR_YCR_CB2BGR, img)
    return img

img = cv2.imread('dark.jpg')

equ = hisEqulColor(im)

h_stack_img = np.hstack((img, equ))

plt.figure(figsize=(10, 8))
ax1 = plt.subplot2grid((2,2),(0, 0))
ax1.imshow(img[:,:,::-1])
ax1.set_title('orignal image')

ax1 = plt.subplot2grid((2, 2), (0, 1))
ax1.imshow(equ[:,:,::-1])
ax1.set_title('equalization')

ax1 = plt.subplot2grid((2, 2), (1, 0), colspan=3, rowspan=1)
ax1.imshow(h_stack_img[:,:,::-1])
ax1.set_title('horizational')

plt.tight_layout()
plt.show()
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 直方图变换 灰度变换 点运算 几何变换 直方图变换 1.灰度直方图 灰度直方图:数字图像中每一灰度级像素出现的频次...
    hyfine阅读 4,455评论 0 0
  • 图像直方图(英语:Image Histogram)是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像...
    fengzhizi715阅读 9,878评论 1 6
  • 2018年5月1日 一早起床外面下着小雨,来到新郎家吃过喜面,我就开始布置婚礼现场,布置完成后就在等待一...
    二年级二班语桐妈妈阅读 229评论 0 0
  • 小时候的玩伴不多,班里的同学虽然都是一个村的,但玩得来的却只有红。 那时孩子们的名字带有浓重的时代特色,我俩的名字...
    烈酒长歌阅读 216评论 0 0
  • 又是一年一度的情人节,事实上这个节日的由来比较悲伤,由于我从事行业的原因,我们从来没有一起过过这个节日,这也是令人...
    海边的桃源阅读 124评论 0 0