python+OpenCv直方圖(灰度直方圖、掩膜的應(yīng)用、直方圖均衡化、自適應(yīng)直方圖均衡化)
一、灰度直方圖
概念:
圖像直方圖是表示數(shù)字圖像中亮度分布的直方圖,標(biāo)繪了圖像中每個(gè)亮度值的像素個(gè)數(shù)。
這種直方圖中,橫坐標(biāo)的左側(cè)為較暗的區(qū)域,而右側(cè)為較亮的區(qū)域。因此一張較暗圖片的直方圖中的數(shù)據(jù)多集中于左側(cè)和中間部分,而整體明亮、只有少量陰影的圖像則相反。如圖:

注意:圖像直方圖是根據(jù)灰度圖進(jìn)行繪制的,而不是彩色圖像。
圖像直方圖的術(shù)語:
dims:需要統(tǒng)計(jì)的特征數(shù)目。
(比如,如果僅統(tǒng)計(jì)了灰度值,則dims=1,如果統(tǒng)計(jì)了BGR三色,則dims=3)
bins:每個(gè)特征空間子區(qū)段的數(shù)目。
(如下圖的直方圖中,每一豎條表示某一值或一區(qū)間,則該直方圖的bins=16)
range:要統(tǒng)計(jì)特征的取值范圍。
(如下圖中,我們將[0,255]區(qū)間分成了16個(gè)子區(qū)間,其中range=[0,255])

直方圖的意義:
直方圖是圖像中像素強(qiáng)度分布的圖形表達(dá)方式。
它統(tǒng)計(jì)了每一個(gè)強(qiáng)度值所具有的像素個(gè)數(shù)。
不同的圖像的直方圖可能是相同的
OpenCv API:
cv2.calcHist(images, channels, mask, histSize, ranges)
參數(shù):
- images:原圖像。當(dāng)傳入函數(shù)時(shí)應(yīng)該用中括號(hào) [] 括起來,例如:[img]
- channels:如果輸入圖像是灰度圖,它的值就是[0];如果是彩色圖像的話,傳入的參數(shù)可以是[0],[1],[2]它們分別對(duì)應(yīng)著通道B,G,R。
- mask:掩模圖像。要統(tǒng)計(jì)整幅圖像的直方圖就把它設(shè)為None。但是如果你想統(tǒng)計(jì)圖像某一部分的直方圖的話,你就需要制作一個(gè)掩模圖像,并使用它。
- histSize:bins的數(shù)目。也應(yīng)該用中括號(hào)括起來,例如:[256]。
- ranges:像素值范圍。通常為[0,256]。
代碼編寫:
import cv2 as cv
import matplotlib.pyplot as plt
src = cv.imread("E:\\view.jpg", 0) # 直接以灰度圖方式讀入
img = src.copy()
# 統(tǒng)計(jì)灰度圖
greyScale_map = cv.calcHist([img], [0], None, [256], [0, 256])
# 繪制灰度圖
plt.figure(figsize=(10, 6), dpi=100)
plt.plot(greyScale_map)
plt.grid()
plt.show()

二、掩膜的應(yīng)用
原理:
掩膜是用選定的圖像、圖形或物體,對(duì)要處理的圖像進(jìn)行遮擋,來控制圖像處理的區(qū)域。
在數(shù)字圖像處理中,我們通常使用二維矩陣數(shù)組進(jìn)行掩膜。掩膜是由0和1組成一個(gè)二進(jìn)制圖像,利用該掩膜圖像要處理的圖像進(jìn)行掩膜,其中1值的區(qū)域被處理,0值區(qū)域被屏蔽,不會(huì)處理。
應(yīng)用:
掩膜的主要用途是:
- 提取感興趣區(qū)域:用預(yù)先制作的感興趣區(qū)掩膜與待處理圖像進(jìn)行”與“操作,得到感興趣區(qū)圖像,感興趣區(qū)內(nèi)圖像值保持不變,而區(qū)外圖像值都為0。
- 屏蔽作用︰用掩膜對(duì)圖像上某些區(qū)域作屏蔽,使其不參加處理或不參加處理參數(shù)的計(jì)算,或僅對(duì)屏蔽區(qū)作處理或統(tǒng)計(jì)。
- 結(jié)構(gòu)特征提取︰用相似性變量或圖像匹配方法檢測和提取圖像中與掩模相似的結(jié)構(gòu)特征。
- ·特殊形狀圖像制作。
掩膜在遙感影像處理中使用較多,當(dāng)提取道路或者河流,或者房屋時(shí),通過一個(gè)掩膜矩陣來對(duì)圖像進(jìn)行像素過濾,然后將我們需要的地物或者標(biāo)志突出顯示出來。
代碼編寫:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
src = cv.imread("E:\\view.jpg", 0) # 直接以灰度圖方式讀入
img = src.copy()
# 創(chuàng)建蒙版
mask = np.zeros(img.shape[:2], np.uint8)
mask[700:1000, 100:400] = 1
# 掩膜
masked_img = cv.bitwise_and(img, img, mask=mask) # 與操作
# 統(tǒng)計(jì)掩膜后圖像的灰度圖
mask_histr = cv.calcHist([img], [0], mask, [256], [0, 256])
# 顯示圖像
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8), dpi=100)
axes[0][0].imshow(img, cmap=plt.cm.gray)
axes[0][0].set_title("原圖")
axes[0][1].imshow(mask, cmap=plt.cm.gray)
axes[0][1].set_title("蒙版數(shù)據(jù)")
axes[1][0].imshow(masked_img, cmap=plt.cm.gray)
axes[1][0].set_title("掩膜后圖像")
axes[1][1].plot(mask_histr)
axes[1][1].grid()
axes[1][1].set_title("掩膜后圖像的灰度直方圖")
plt.show()
三、直方圖均衡化
原理:
想象一下,如果一副圖像中的大多數(shù)像素點(diǎn)的像素值都集中在某一個(gè)小的灰度值值范圍之內(nèi)會(huì)怎樣呢?如果一幅圖像整體很亮,那所有的像素值的取值個(gè)數(shù)應(yīng)該都會(huì)很高。所以應(yīng)該把它的直方圖做一個(gè)橫向拉伸(如下圖),就可以擴(kuò)大圖像像素值的分布范圍,提高圖像的對(duì)比度,這就是直方圖均衡化要做的事情。

“直方圖均衡化"是把原始圖像的灰度直方圖從比較集中的某個(gè)灰度區(qū)間變成在更廣泛灰度范圍內(nèi)的分布。直方圖均衡化就是對(duì)圖像進(jìn)行非線性拉伸,重新分配圖像像素值,使一定灰度范圍內(nèi)的像素?cái)?shù)量大致相同。
應(yīng)用:
提高圖像整體的對(duì)比度。
特別是有用數(shù)據(jù)的像素值分布比較接近時(shí),在X光圖像中使用廣泛,可以提高骨架結(jié)構(gòu)的顯示,另外在曝光過度或不足的圖像中可以更好的突出細(xì)節(jié)。
OpenCv API:
cv2.equalizeHist(img)
參數(shù):
img:輸入的灰度圖
代碼編寫:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
src = cv.imread("E:\\qi.png", 0) # 直接以灰度圖方式讀入
img = src.copy()
# 均衡化處理
dst = cv.equalizeHist(img)
# 顯示圖像
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img, cmap=plt.cm.gray)
axes[0].set_title("原圖")
axes[1].imshow(dst, cmap=plt.cm.gray)
axes[1].set_title("均衡化后的圖像")
plt.show()
四、自適應(yīng)的直方圖均衡化
由來:
上述的直方圖均衡化,我們考慮的是圖像的全局對(duì)比度。的確在進(jìn)行完直方圖均衡化之后,圖片背景的對(duì)比度被改變了,但在許多情況下,這樣做的效果并不好,因?yàn)榫饣蟮膱D像很有可能發(fā)生局部過亮或者局部過暗的情況,從而造成數(shù)據(jù)信息的丟失。
原理:
- 將整幅圖像分成很多小塊,這些小塊被稱為“tiles”(在 OpenCV中tiles的大小默認(rèn)是8x8),然后再對(duì)每一個(gè)小塊分別進(jìn)行直方圖均衡化。(所以在每一個(gè)的區(qū)域中,直方圖會(huì)集中在某一個(gè)小的區(qū)域中)。
- 如果有噪聲的話,噪聲會(huì)被放大。為了避免這種情況的出現(xiàn)要使用對(duì)比度限制。對(duì)于每個(gè)小塊來說,如果直方圖中的 bin超過對(duì)比度的上限的話,就把其中的像素點(diǎn)均勻分散到其他bins 中,然后在進(jìn)行直方圖均衡化。

最后,為了去除每一個(gè)小塊之間的邊界,再使用雙線性差值,對(duì)每一小塊進(jìn)行拼接。
OpenCv API:
clahe = cv.createCLAHE(clipLimit, tileGridSize) dst = clahe.apply(img)
參數(shù):
- clipLimit:對(duì)比度限制,默認(rèn)是40
- tileGridSize:分塊的大小,默認(rèn)為8*8 代碼編寫:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
src = cv.imread("E:\\qi.png", 0) # 直接以灰度圖方式讀入
img = src.copy()
# 創(chuàng)建一個(gè)自適應(yīng)均衡化的對(duì)象,并應(yīng)用于圖像
clahe = cv.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
dst = clahe.apply(img)
# 顯示圖像
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img, cmap=plt.cm.gray)
axes[0].set_title("原圖")
axes[1].imshow(dst, cmap=plt.cm.gray)
axes[1].set_title("自適應(yīng)均衡化后的圖像")
plt.show()
到此這篇關(guān)于python+OpenCv直方圖(灰度直方圖、掩膜的應(yīng)用、直方圖均衡化、自適應(yīng)直方圖均衡化)的文章就介紹到這了,更多相關(guān)python OpenCv直方圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實(shí)現(xiàn)列表轉(zhuǎn)換成字典數(shù)據(jù)結(jié)構(gòu)的方法
這篇文章主要介紹了Python實(shí)現(xiàn)列表轉(zhuǎn)換成字典數(shù)據(jù)結(jié)構(gòu)的方法,結(jié)合實(shí)例形式分析了Python數(shù)值類型轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下2016-03-03
基于Python實(shí)現(xiàn)圖片九宮格切圖程序
這篇文章主要為大家詳細(xì)介紹了如何利用python和C++代碼實(shí)現(xiàn)圖片九宮格切圖程序,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2023-04-04
Python協(xié)程 yield與協(xié)程greenlet簡單用法示例
這篇文章主要介紹了Python協(xié)程 yield與協(xié)程greenlet簡單用法,簡要講述了協(xié)程的概念、原理,并結(jié)合實(shí)例形式分析了Python協(xié)程 yield與協(xié)程greenlet基本使用方法,需要的朋友可以參考下2019-11-11

