opencv-python圖像增強(qiáng)解讀
圖像增強(qiáng)算子
幾何變換算子
? 圖像的幾何變換又稱為圖像空間變換, 它將一幅圖像中的坐標(biāo)位置映射到另一幅圖像中的新坐標(biāo)位置。
- 圖像縮放
縮放只是調(diào)整圖像的大小。為此,OpenCV 附帶了一個(gè)函數(shù)cv.resize()。圖像的大小可以手動(dòng)指定,也可以指定縮放因子,使用了不同 的插值方法。
首選的插值方法是cv2.INTER_AREA 用于縮小,cv.INTER_CUBIC(慢)和cv.INTER_LINEAR 用于縮放。
默認(rèn)情況下, 出于所有調(diào)整大小的目的,使用的插值方法為cv.INTER_LINEAR。
您可以使用以下方法調(diào)整輸入圖像的大?。?/p>
- ? INTER_AREA基于區(qū)域像素關(guān)系的一種重采樣或者插值方式.該方法是圖像抽取的首選方法,它可以產(chǎn)生更少的波紋.
- ? INTER_LINEAR是雙線性插值,默認(rèn)情況下使用該方式進(jìn)行插值;INTER_CUBIC是用3次方函數(shù)差值.
import numpy as np import cv2 as cv img = cv.imread('1.jpg') res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC) #或者 height, width = img.shape[:2] res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)
- 圖像翻轉(zhuǎn)
?opencv翻轉(zhuǎn)圖像有三種方式,分別時(shí)上下翻轉(zhuǎn)、左右翻轉(zhuǎn)和對(duì)角線翻轉(zhuǎn)。
import cv2 as cv import numpy as np img = cv.imread(image_path, cv.IMREAD_COLOR) # 上下翻轉(zhuǎn) dst1 = cv.flip(img, 0) res1 = np.vstack((img, dst1)) # 左右翻轉(zhuǎn) dst2 = cv.flip(img, 1) res2 = np.vstack((img, dst2)) # 對(duì)角線翻轉(zhuǎn) dst3 = cv.flip(img, -1) res3 = np.vstack((img, dst3))
- 仿射變換
?仿射變換基本上是兩個(gè)圖像之間的關(guān)系。使用矩陣乘法(線性變換)的形式表示的轉(zhuǎn)換,后跟向量加法(轉(zhuǎn)換)關(guān)于這種關(guān)系的信息大概可以通過兩種方式來實(shí)現(xiàn):
- 1.我們知道X和T我們也知道它們是相關(guān)的。那么我們的任務(wù)就是找M
- 2.我們知道M和X。為了獲得T,我們只需要計(jì)算T= M⋅ X。其中M的是確定的,或者它可以作為點(diǎn)之間的幾何關(guān)系。
在OpenCV中,仿射變換可以通過函數(shù)warpAffine來支持,當(dāng)然部分單獨(dú)的函數(shù)也可以進(jìn)行某個(gè)特定的變換,如縮放和旋轉(zhuǎn)就有單獨(dú)的變換函數(shù)。
img=cv2.imread('yun.jpg',cv2.IMREAD_GRAYSCALE) cv2.imwrite('yun.jpg',img) #原圖的寬高 h,w=img.shape[:2] #仿射變換矩陣 縮小2倍 A1=np.array([[0.5,0,0],[0,0.5,0]],np.float32) A2=cv2.warpAffine(img,A1,(w,h),borderValue=126) #縮小后平移 B1=np.array([[0.5,0,w/4],[0,0.5,h/4]],np.float32) B2=cv2.warpAffine(img,B1,(w,h),borderValue=126) #使圖像旋轉(zhuǎn) C1=cv2.getRotationMatrix2D((w/2.0,h/2.0),30,1) C2=cv2.warpAffine(img,C1,(w,h),borderValue=126)
圖像金字塔算子
它的本質(zhì)是對(duì)圖像進(jìn)行放縮變換。一般情況下,我們要處理是一副具有固定分辨率的圖像。
但是有些情況下,我們需要對(duì)同一圖像的不同分辨率的子圖像進(jìn)行處理。
比如,我們要在一幅圖像中查找某個(gè)目標(biāo),比如臉,我們不知道目標(biāo)在圖像中的尺寸大小。這種情況下,我們需要?jiǎng)?chuàng)建一組圖像,這些圖像是具有不同分辨率的原始圖像。
我們把這組圖像叫做圖像金字塔(簡單來說就是同一圖像的不同分辨率的子圖集合)。
如果我們把最大的圖像放在底部,最小的放在頂部,看起來像一座金字塔,故而得名圖像金字塔。
? 圖像金字塔最初用于機(jī)器視覺和圖像壓縮,一幅圖像的金字塔是一系列以金字塔形狀排列的分辨率逐步降低,且來源于同一張?jiān)紙D的圖像集合。
其通過梯次向下采樣獲得,直到達(dá)到某個(gè)終止條件才停止采樣。金字塔的底部是待處理圖像的高分辨率表示,而頂部是低分辨率的近似。我們將一層一層的圖像比喻成金字塔,層級(jí)越高,則圖像越小,分辨率越低。
- 拉普拉斯金字塔
用來從金字塔低層圖像重建上層未采樣圖像,在數(shù)字圖像處理中也即是預(yù)測殘差,可以對(duì)圖像進(jìn)行最大程度的還原,配合高斯金字塔一起使用。
兩者的簡要區(qū)別:高斯金字塔用來向下降采樣圖像,而拉普拉斯金字塔則用來從金字塔底層圖像中向上采樣重建一個(gè)圖像。
要從金字塔第i層生成第i+1層(我們表示第i+1層為G_i+1),我們先要用高斯核對(duì)G_1進(jìn)行卷積,然后刪除所有偶數(shù)行和偶數(shù)列。
當(dāng)然的是,新得到圖像面積會(huì)變?yōu)樵磮D像的四分之一。按上述過程對(duì)輸入圖像G_0執(zhí)行操作就可產(chǎn)生出整個(gè)金字塔。
當(dāng)圖像向金字塔的上層移動(dòng)時(shí),尺寸和分辨率就降低。OpenCV中,從金字塔中上一級(jí)圖像生成下一級(jí)圖像的可以用PryDown。而通過PryUp將現(xiàn)有的圖像在每個(gè)維度都放大兩遍。
圖像金字塔中的向上和向下采樣分別通過OpenCV函數(shù) pyrUp 和 pyrDown 實(shí)現(xiàn)。
對(duì)圖像向上采樣:pyrUp函數(shù)
對(duì)圖像向下采樣:pyrDown函數(shù)
這里的向下與向上采樣,是對(duì)圖像的尺寸而言的(和金字塔的方向相反),向上就是圖像尺寸加倍,向下就是圖像尺寸減半。而如果我們按上圖中演示的金字塔方向來理解,金字塔向上圖像其實(shí)在縮小,這樣剛好是反過來了。
但需要注意的是,PryUp和PryDown不是互逆的,即PryUp不是降采樣的逆操作。這種情況下,圖像首先在每個(gè)維度上擴(kuò)大為原來的兩倍,新增的行(偶數(shù)行)以0填充。然后給指定的濾波器進(jìn)行卷積(實(shí)際上是一個(gè)在每個(gè)維度都擴(kuò)大為原來兩倍的過濾器)去估計(jì)“丟失”像素的近似值。
PryDown( )是一個(gè)會(huì)丟失信息的函數(shù)。為了恢復(fù)原來更高的分辨率的圖像,我們要獲得由降采樣操作丟失的信息,這些數(shù)據(jù)就和拉普拉斯金字塔有關(guān)系了。
import cv2 as cv # 高斯金字塔 def pyramid_demo(image): level = 3 # 金字塔層數(shù) temp = image.copy() pyramid_images = [] for i in range(level): dst = cv.pyrDown(temp) # 降采樣 pyramid_images.append(dst) # 降采樣的結(jié)果添加進(jìn)列表 cv.imshow('pyramid_down' + str(i), dst) # 金字塔第幾層 imshow temp = dst.copy() # 采樣的圖像又賦給temp 接著降采樣 return pyramid_images # 拉普拉斯金字塔 # 由高斯金字塔可以構(gòu)建拉普拉斯金字塔 def lapalian_demo(image): pyramid_images = pyramid_demo(image) level = len(pyramid_images) # 求層數(shù) for i in range(level - 1, -1, -1): # 每次遞減 if (i - 1) < 0: expand = cv.pyrUp(pyramid_images[i], dstsize=image.shape[:2]) # 升采樣 lpls = cv.subtract(image, expand) cv.imshow("lapalian_down" + str(i), lpls) else: expand = cv.pyrUp(pyramid_images[i], dstsize=pyramid_images[i - 1].shape[:2]) lpls = cv.subtract(pyramid_images[i - 1], expand) cv.imshow("lapalian_down_" + str(i), lpls)
圖像平滑算子
在處理和傳輸數(shù)字圖像的過程中可能會(huì)受到不同的噪聲的干擾,圖像噪聲會(huì)引起圖像質(zhì)量降低、圖像變得模糊,使圖像的特征被淹沒、而通過除去噪聲來達(dá)到圖像增強(qiáng)的目的的操作被稱為圖像平滑處理
- 均值濾波
假設(shè)被噪聲污染的數(shù)字圖像空間含有 N*N 個(gè)像素點(diǎn),而這幅數(shù)字圖像中每一個(gè)像素點(diǎn)值可以通過領(lǐng)域內(nèi)幾個(gè)像素點(diǎn)的平均值計(jì)算出來,采用平滑圖像處理方法就可以得到一幅新的圖像,這個(gè)過程就被稱為均值濾波。
import cv2 import numpy as np #讀取圖像信息 k = 5 img0 = cv2.imread("1.jpg") img1 = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY) h, w = img0.shape[:2] r5=cv2.blur(img1,(k,k)) #5*5卷積
- 方框?yàn)V波
方框?yàn)V波是均值濾波的一種形式。在均值濾波中,濾波結(jié)果的像素值是任意一個(gè)點(diǎn)的鄰域平均值,等于各鄰域像素值之和的均值,而在方框?yàn)V波中,可以自由選擇是否對(duì)均值濾波的結(jié)果進(jìn)行歸一化,即可以自由選擇濾波結(jié)果是鄰域像素值之和的平均值,還是鄰域像素值之和。
import cv2 import matplotlib.pyplot as plt # 讀取圖片 img = cv2.imread('1.jpg') # 方框?yàn)V波,True表示歸一化,則效果與均值濾波相同。 result = cv2.boxFilter(source, -1, (5, 5), normalize=False) # sqrBoxFilter實(shí)現(xiàn)對(duì)每個(gè)像素值的平方求和 # result1 = cv2.sqrBoxFilter(source, -1, (5, 5), normalize=True)
- 高斯濾波
為了克服簡單局部平均法的弊端(圖像模糊),目前已提出許多保持邊緣、細(xì)節(jié)的局部平滑算法。它們的出發(fā)點(diǎn)都集中在如何選擇鄰域的大小、形狀和方向、參數(shù)加平均及鄰域各店的權(quán)重系數(shù)等。
圖像高斯平滑也是鄰域平均的思想對(duì)圖像進(jìn)行平滑的一種方法,在圖像高斯平滑中,對(duì)圖像進(jìn)行平均時(shí),不同位置的像素被賦予了不同的權(quán)重。高斯平滑與簡單平滑不同,它在對(duì)鄰域內(nèi)像素進(jìn)行平均時(shí),給予不同位置的像素不同的權(quán)值.
import cv2 k = 5 img=cv2.imread('1.jpg') #(5, 5)表示高斯矩陣的長與寬都是5,標(biāo)準(zhǔn)差取0 blur=cv2.GaussianBlur(img,(k,k),0)
- 中值濾波
中值濾波器遍歷信號(hào)的每個(gè)元素(在這種情況下為圖像),并用其相鄰像素的中位數(shù)(位于估計(jì)像素周圍的正方形鄰域)中替換每個(gè)像素。
import cv2 k = 5 img=cv2.imread('1.jpg') #常用來去除椒鹽噪聲 #卷積核使用奇數(shù) blur=cv2.medianBlur(img,k)
- 雙邊濾波
? 雙邊濾波是一種非線性的濾波方法,是結(jié)合圖像的空間鄰近度和像素值相似度的一種折衷處理,同時(shí)考慮空間與信息和灰度相似性,達(dá)到保邊去噪的目的,具有簡單、非迭代、局部處理的特點(diǎn)。
之所以能夠達(dá)到保邊去噪的濾波效果是因?yàn)闉V波器由兩個(gè)函數(shù)構(gòu)成:一個(gè)函數(shù)是由幾何空間距離決定濾波器系數(shù),另一個(gè)是由像素差值決定濾波器系數(shù).
相對(duì)高斯濾波去降噪,會(huì)較明顯地模糊邊緣,對(duì)于高頻細(xì)節(jié)的保護(hù)效果并不明顯。
#cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]]) #能在保持邊界清晰的情況下有效的去除噪音 #但是這種操作與其他濾波器相比會(huì)比較慢 import cv2 img=cv2.imread('1.jpg') #cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace) #9 鄰域直徑,兩個(gè)75分別是空間高斯函數(shù)標(biāo)準(zhǔn)差,灰度值相似性高斯函數(shù)標(biāo)準(zhǔn)差 blur = cv2.bilateralFilter(img,9,75,75)
?參數(shù)解釋:
src
:輸入圖像d
:過濾時(shí)周圍每個(gè)像素領(lǐng)域的直徑sigmaColor
:在color space中過濾sigma。參數(shù)越大,臨近像素將會(huì)在越遠(yuǎn)的地方mix。sigmaSpace
:在coordinate space中過濾sigma。參數(shù)越大,那些顏色足夠相近的的顏色的影響越大。
傅立葉變換算子
表示能將滿足一定條件的某個(gè)函數(shù)表示成三角函數(shù)(正弦和/或余弦函數(shù))或者它們的積分的線性組合。
在不同的研究領(lǐng)域,傅立葉變換具有多種不同的變體形式,如連續(xù)傅立葉變換和離散傅立葉變換。
傅里葉變換是一種分析信號(hào)的方法,它可分析信號(hào)的成分,也可用這些成分合成信號(hào)。
許多波形可作為信號(hào)的成分,比如正弦波、方波、鋸齒波等,傅里葉變換用正弦波作為信號(hào)的成分。對(duì)于圖像,將時(shí)域轉(zhuǎn)化為頻域。
- 傅立葉變換算子
在頻域范圍內(nèi)可以研究圖像增強(qiáng),可以利用頻率成分和圖像外表之間的對(duì)應(yīng)關(guān)系。
一些在空間域表述困難的增強(qiáng)任務(wù),在頻率域中變得非常普通濾波在頻率域更為直觀,它可以解釋空間域?yàn)V波的某些性質(zhì),可以在頻率域指定濾波器,做反變換,然后在空間域使用結(jié)果濾波器作為空間域?yàn)V波器的指導(dǎo),一旦通過頻率域試驗(yàn)選擇了空間濾波,通常實(shí)施都在空間域進(jìn)行。
意義:
1、圖像的頻率是表征圖像中灰度變化劇烈程度的指標(biāo),是灰度在平面空間上的梯度**(灰度變化得快頻率就高,灰度變化得慢 頻率就低)**
? 2、圖像上某一點(diǎn)與鄰域點(diǎn)灰度值差異的強(qiáng)弱,即梯度的大小,也即該點(diǎn)的頻率的大?。ú町?梯度越大,頻率越高,能量越低, 在頻譜圖上就越暗。差異/梯度越小,頻率越低,能量越高,在頻譜圖上就越亮。換句話說,頻率譜上越亮能量越高,頻率 越低,圖像差異越小/平緩)。一般來講,梯度大則該點(diǎn)的亮度強(qiáng),否則該點(diǎn)亮度弱。頻譜圖,也叫功率圖。
#OpenCV實(shí)現(xiàn) dft = cv2.dft(np.float32(img2), flags = cv2.DFT_COMPLEX_OUTPUT) dft_shift = np.fft.fftshift(dft) magnitude_spectrum1 = 20*np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1])) plt.subplot(121), plt.imshow(img2, cmap = 'gray') plt.title('原圖'), plt.xticks([]), plt.yticks([]) plt.subplot(122), plt.imshow(magnitude_spectrum1, cmap = 'gray') plt.title('頻譜圖'), plt.xticks([]), plt.yticks([]) plt.show()
形態(tài)學(xué)操作算子
? 形態(tài)學(xué)算子的主要思想是用一定形狀的結(jié)構(gòu)元素在圖像中抽取出相應(yīng)的某些結(jié)構(gòu),通常可以用于圖像的濾波、分割、分類等處理。形態(tài)學(xué)算子有腐蝕、膨脹、開和閉四種。
- 圖像腐蝕
?腐蝕是一種消除邊界點(diǎn),使邊界向內(nèi)部收縮的過程??梢杂脕硐∏覠o意義的物體。腐蝕的算法: 用3x3的結(jié)構(gòu)元素,掃描圖像的每一個(gè)像素 用結(jié)構(gòu)元素與其覆蓋的二值圖像做“與”操作 如果都為1,結(jié)果圖像的該像素為1。否則為0。
結(jié)果:使二值圖像減小一圈
import cv2 img0 = cv2.imread("1.jpg") img1 = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY) erosion1 = cv2.erode(img1, kernel1)
- 圖像膨脹
膨脹是將與物體接觸的所有背景點(diǎn)合并到該物體中,使邊界向外部擴(kuò)張的過程??梢杂脕硖钛a(bǔ)物體中的空洞。膨脹的算法: 用3x3的結(jié)構(gòu)元素,掃描圖像的每一個(gè)像素 用結(jié)構(gòu)元素與其覆蓋的二值圖像做“與”操作 如果都為0,結(jié)果圖像的該像素為0。否則為1
結(jié)果:使二值圖像擴(kuò)大一圈
import cv2 img0 = cv2.imread("1.jpg") img1 = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY) dilation1 = cv2.dilate(img1, kernel1)
- 開運(yùn)算
雖然腐蝕可以將粘連的目標(biāo)進(jìn)行分離,膨脹可以將斷續(xù)的目標(biāo)進(jìn)行連接,但是無論是腐蝕還是膨脹處理后,目標(biāo)的尺寸都會(huì)產(chǎn)生變化。
開運(yùn)算,閉運(yùn)算就是為了解決這個(gè)問題。
先腐蝕后膨脹的過程稱為開運(yùn)算。用來消除小物體、在纖細(xì)點(diǎn)處分離物體、平滑較大物體的邊界的同時(shí)并不明顯改變其面積。
import cv2 import numpy as np ori = cv2.imread(r"1.jpg") k = np.ones((10, 10), np.uint8) opening = cv2.morphologyEx(ori, cv2.MORPH_OPEN,k) # 開運(yùn)算
- 閉運(yùn)算
先膨脹后腐蝕的過程稱為閉運(yùn)算。用來填充物體內(nèi)細(xì)小空洞、連接鄰近物體、平滑其邊界的同時(shí)并不明顯改變其面積。
import cv2 import numpy as np ori = cv2.imread(r"1.jpg") k1 = np.ones((8, 8), np.uint8) k2 = np.ones((15, 15), np.uint8) closing1 = cv2.morphologyEx(ori, cv2.MORPH_CLOSE, k1) closing2 = cv2.morphologyEx(ori, cv2.MORPH_CLOSE, k2)
- 梯度運(yùn)算
? 圖像的梯度操作就是將圖像膨脹的結(jié)果減去腐蝕的結(jié)果,以得到圖像的邊緣。
將形態(tài)學(xué)運(yùn)算函數(shù)中第二個(gè)參數(shù)改為cv2.MORPH_GRADIENT即可。
即cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
import cv2 import numpy as np ori = cv2.imread(r"1.jpg") result=cv2.morphologyEx(ori, cv2.MORPH_GRADIENT, kernel)
?
- 禮帽運(yùn)算
禮帽操作就是用原圖減去開運(yùn)算的圖像,以得到前景圖外面的毛刺噪聲,因?yàn)殚_運(yùn)算可以消除小物體,所以通過做差就可以將消除掉的小物體提取出來,使用時(shí)修改形態(tài)學(xué)運(yùn)算函數(shù)參數(shù)為cv2.MORPH_TOPHAT即可
import cv2 import numpy as np ori = cv2.imread(r"1.jpg") result=cv2.morphologyEx(ori, cv2.MORPH_TOPHAT, kernel)
- 黑帽運(yùn)算
? 黑帽就是用原圖減去閉運(yùn)算的圖像,以得到前景圖像內(nèi)部的小孔等噪聲。使用時(shí)修改形態(tài)學(xué)運(yùn)算函數(shù)參數(shù)為cv2.MORPH_BLACKHAT即可。
import cv2 import numpy as np ori = cv2.imread(r"1.jpg") result=cv2.morphologyEx(ori, cv2.MORPH_BLACKHAT, kernel)
直方圖均衡化
?圖像的空域處理是一種重要的圖像處理技術(shù),這類方法直接以圖像的像素操作為基礎(chǔ),主要分為灰度變換和空域?yàn)V波兩大類,直方圖均衡化(Histogram equalization)就是一種常用的灰度變換方法。
? 通常,暗圖像直方圖的分量集中在灰度較低的一端,而亮圖像直方圖分量偏向于灰度較高的一端
- 直方圖均衡化
? 可以得到這樣的結(jié)論:如果一幅圖像的灰度直方圖幾乎覆蓋了整個(gè)灰度的取值范圍,并且除了個(gè)別灰度值的個(gè)數(shù)較為突出,整個(gè)灰度值分布近似于均勻分布,那么這幅圖像就具有較大的灰度動(dòng)態(tài)范圍和較高的對(duì)比度,同時(shí)圖像的細(xì)節(jié)更為豐富。
已經(jīng)證明,僅僅依靠輸入圖像的直方圖信息,就可以得到一個(gè)變換函數(shù),利用該變換函數(shù)可以將輸入圖像達(dá)到上述效果,該過程就是直方圖均衡化。
import cv2 import numpy as np from matplotlib import pyplot as plt ''' calcHist-計(jì)算圖像直方圖 函數(shù)原型:calcHist(images,channels,mask,histSize,ranges,hist=None,accumulate=None) images:圖像矩陣,例如:[image] channels:通道數(shù),例如:0 mask:掩膜,一般為:None histSize:直方圖大小,一般等于灰度級(jí)數(shù) ranges:橫軸范圍 ''' # 獲取灰度圖像 img = cv2.imread("1.jpg", 0) # 灰度圖像的直方圖 hist = cv2.calcHist([img],[0],None,[256],[0,256]) plt.figure()#新建一個(gè)圖像 plt.title("Grayscale Histogram") plt.xlabel("Bins")#X軸標(biāo)簽 plt.ylabel("# of Pixels")#Y軸標(biāo)簽 plt.plot(hist) plt.xlim([0,256])#設(shè)置x坐標(biāo)軸范圍 plt.show() ''' equalizeHist—直方圖均衡化 函數(shù)原型: equalizeHist(src, dst=None) src:圖像矩陣(單通道圖像) dst:默認(rèn)即可 ''' # 灰度圖像直方圖均衡化 dst = cv2.equalizeHist(img) # 直方圖 hist = cv2.calcHist([dst],[0],None,[256],[0,256]) plt.figure() plt.hist(dst.ravel(), 256) plt.show() cv2.imshow("Histogram Equalization",np.hstack([img, dst])) cv2.waitKey(0)
# 彩色圖像直方圖均衡化 img = cv2.imread("1.jpg", 1) cv2.imshow("src", img) # 彩色圖像均衡化,需要分解通道 對(duì)每一個(gè)通道均衡化 (b, g, r) = cv2.split(img) bH = cv2.equalizeHist(b) gH = cv2.equalizeHist(g) rH = cv2.equalizeHist(r) # 合并每一個(gè)通道 result = cv2.merge((bH, gH, rH)) cv2.imshow("dst_rgb", result) cv2.waitKey(0)
Gamma變換
? 伽馬變換就是用來圖像增強(qiáng),其提升了暗部細(xì)節(jié),簡單來說就是通過非線性變換,讓圖像從暴光強(qiáng)度的線性響應(yīng)變得更接近人眼感受的響應(yīng),即將漂白(相機(jī)曝光)或過暗(曝光不足)的圖片,進(jìn)行矯正。
- gamma變換
Gamma變換是對(duì)輸入圖像灰度值進(jìn)行的非線性操作,使輸出圖像灰度值與輸入圖像灰度值呈指數(shù)關(guān)系:
這個(gè)指數(shù)即為Gamma。
經(jīng)過Gamma變換后的輸入和輸出圖像灰度值關(guān)系如圖1所示:橫坐標(biāo)是輸入灰度值,縱坐標(biāo)是輸出灰度值,藍(lán)色曲線是gamma值小于1時(shí)的輸入輸出關(guān)系,紅色曲線是gamma值大于1時(shí)的輸入輸出關(guān)系。
可以觀察到,當(dāng)gamma值小于1時(shí)(藍(lán)色曲線),圖像的整體亮度值得到提升,同時(shí)低灰度處的對(duì)比度得到增加,更利于分辯低灰度值時(shí)的圖像細(xì)節(jié)。
Gamma大于1時(shí),對(duì)圖像的灰度分布直方圖具有拉伸作用(使灰度向高灰度值延展),而小于1時(shí),對(duì)圖像的灰度分布直方圖具有收縮作用(是使灰度向低灰度值方向靠攏).
import cv2 #分道計(jì)算每個(gè)通道的直方圖 img0 = cv2.imread('12.jpg') hist_b = cv2.calcHist([img0],[0],None,[256],[0,256]) hist_g = cv2.calcHist([img0],[1],None,[256],[0,256]) hist_r = cv2.calcHist([img0],[2],None,[256],[0,256]) def gamma_trans(img,gamma): #具體做法先歸一化到1,然后gamma作為指數(shù)值求出新的像素值再還原 gamma_table = [np.power(x/255.0,gamma)*255.0 for x in range(256)] gamma_table = np.round(np.array(gamma_table)).astype(np.uint8) #實(shí)現(xiàn)映射用的是Opencv的查表函數(shù) return cv2.LUT(img0,gamma_table) img0_corrted = gamma_trans(img0, 0.5) cv2.imshow('img0',img0) cv2.imshow('gamma_image',img0_corrted) cv2.imwrite('gamma_image.png',img0_corrted) #分通道計(jì)算Gamma校正后的直方圖 hist_b_c =cv2.calcHist([img0_corrted],[0],None,[256],[0,256]) hist_g_c =cv2.calcHist([img0_corrted],[1],None,[256],[0,256]) hist_r_c =cv2.calcHist([img0_corrted],[2],None,[256],[0,256]) fig = plt.figure('gamma') pix_hists = [[hist_b, hist_g, hist_r], [hist_b_c, hist_g_c, hist_r_c]] pix_vals = range(256) for sub_plt, pix_hist in zip([121, 122], pix_hists): ax = fig.add_subplot(sub_plt, projection='3d') for c, z, channel_hist in zip(['b', 'g', 'r'], [20, 10, 0], pix_hist): cs = [c] * 256 ax.bar(pix_vals, channel_hist, zs=z, zdir='y', color=cs, alpha=0.618, edgecolor='none', lw=0) ax.set_xlabel('Pixel Values') ax.set_xlim([0, 256]) ax.set_ylabel('Count') ax.set_zlabel('Channels') plt.show() cv2.waitKey()
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C站最全Python標(biāo)準(zhǔn)庫總結(jié),你想要的都在這里
這篇文章主要介紹了C站最全的Python標(biāo)準(zhǔn)庫,總共包含10個(gè)類型,希望能對(duì)大家有幫助,看完不虧系列2021-07-07使用Python快樂學(xué)數(shù)學(xué)Github萬星神器Manim簡介
這篇文章主要介紹了使用Python快樂學(xué)數(shù)學(xué)Github萬星神器Manim簡介,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08python list 切片倒著取的實(shí)現(xiàn)示例
切片操作非常靈活,可以按照需要獲取列表中的任意一段元素,本文主要介紹了python list 切片倒著取的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01PyTorch快速搭建神經(jīng)網(wǎng)絡(luò)及其保存提取方法詳解
本篇文章主要介紹了PyTorch快速搭建神經(jīng)網(wǎng)絡(luò)及其保存提取方法詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04詳解python中的lambda與sorted函數(shù)
這篇文章主要介紹了python中的lambda與sorted函數(shù)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下2020-09-09