使用OpenCV在Python中進(jìn)行圖像處理
介紹
在本教程中,我們將學(xué)習(xí)如何使用Python語言執(zhí)行圖像處理。我們不會(huì)局限于單個(gè)庫或框架;但是,我們將最常使用的是Open CV庫。我們將先討論一些圖像處理,然后再繼續(xù)介紹可以方便使用圖像處理的不同應(yīng)用程序/場景。
?
什么是圖像處理?
重要的是要了解圖像處理的確切含義,以及在深入了解圖像處理的作用之前,圖像處理在大圖中的作用是什么。圖像處理最常被稱為“數(shù)字圖像處理”,而經(jīng)常使用的領(lǐng)域是“計(jì)算機(jī)視覺”。請(qǐng)勿混淆。圖像處理算法和計(jì)算機(jī)視覺(CV)算法都將圖像作為輸入。但是,在圖像處理中,輸出也是圖像,而在計(jì)算機(jī)視覺中,輸出可能是有關(guān)圖像的某些特征/信息。
?
我們?yōu)槭裁葱枰?/strong>
我們收集或生成的數(shù)據(jù)大部分是原始數(shù)據(jù),即由于多種可能的原因,不適合直接在應(yīng)用程序中使用。因此,我們需要先對(duì)其進(jìn)行分析,執(zhí)行必要的預(yù)處理,然后再使用它。
例如,假設(shè)我們正在嘗試構(gòu)建cat分類器。我們的程序?qū)D像作為輸入,然后告訴我們圖像是否包含貓。建立該分類器的第一步是收集數(shù)百張貓圖片。一個(gè)普遍的問題是,我們抓取的所有圖片都不會(huì)具有相同的尺寸/尺寸,因此在將它們輸入模型進(jìn)行訓(xùn)練之前,我們需要將所有尺寸調(diào)整/預(yù)處理為標(biāo)準(zhǔn)尺寸。
這只是圖像處理對(duì)于任何計(jì)算機(jī)視覺應(yīng)用必不可少的眾多原因之一。
?
先決條件
在繼續(xù)進(jìn)行之前,讓我們討論一下需要了解的內(nèi)容,以便輕松地學(xué)習(xí)本教程。首先,您應(yīng)該掌握任何語言的基本編程知識(shí)。其次,您應(yīng)該知道什么是機(jī)器學(xué)習(xí)以及它如何工作的基礎(chǔ),因?yàn)楸疚闹形覀儗⑹褂靡恍C(jī)器學(xué)習(xí)算法進(jìn)行圖像處理。另外,如果您在繼續(xù)學(xué)習(xí)本教程之前對(duì)Open CV有任何了解或基礎(chǔ)知識(shí),這將對(duì)您有所幫助。但這不是必需的。
為了遵循本教程,您一定要知道的一件事是圖像在內(nèi)存中的準(zhǔn)確表示方式。每個(gè)圖像由一組像素表示,即像素值矩陣。對(duì)于灰度圖像,像素值的范圍是0到255,它們代表該像素的強(qiáng)度。例如,如果您具有20 x 20尺寸的圖像,則將以20x20的矩陣(總共400個(gè)像素值)表示。
如果要處理彩色圖像,則應(yīng)該知道它將具有三個(gè)通道-紅色,綠色和藍(lán)色(RGB)。因此,單個(gè)圖像將有三個(gè)這樣的矩陣。
?
安裝
注意:由于我們將通過Python使用OpenCV,因此隱含的要求是您的工作站上已經(jīng)安裝了Python(版本3)。
windows
$ pip install opencv-python
蘋果系統(tǒng)
$ brew install openCV3 --with-contrib --with-python3
Linux
$ sudo apt-get install libopencv-dev python-opencv
要檢查安裝是否成功,請(qǐng)?jiān)赑ython Shell或命令提示符中運(yùn)行以下命令:
import CV2
?
您應(yīng)該知道的一些基本知識(shí)
在我們繼續(xù)在應(yīng)用程序中使用圖像處理之前,重要的是要了解哪種操作屬于此類,以及如何進(jìn)行這些操作。這些操作以及其他操作將在以后的應(yīng)用程序中使用。
對(duì)于本文,我們將使用以下圖像:

注意:為了在本文中顯示圖像,已對(duì)圖像進(jìn)行了縮放,但是我們使用的原始大小約為1180x786。
您可能已經(jīng)注意到圖像當(dāng)前是彩色的,這意味著它由三個(gè)顏色通道表示,即紅色,綠色和藍(lán)色。我們將圖像轉(zhuǎn)換為灰度圖像,并使用下面的代碼將圖像分為單獨(dú)的通道。
?
查找圖像細(xì)節(jié)
在使用imread()
函數(shù)加載圖像后,我們可以檢索有關(guān)圖像的一些簡單屬性,例如像素?cái)?shù)和尺寸:
print("Image Properties")
print("- Number of Pixels: " + str(img.size))
print("- Shape/Dimensions: " + str(img.shape))
輸出:
Image Properties
- Number of Pixels: 2782440
- Shape/Dimensions: (1180, 786, 3)
?
將圖像分成單獨(dú)的通道
現(xiàn)在,我們將使用OpenCV將圖像分為紅色,綠色和藍(lán)色分量,顯示它們:
CV2_imshow(red) # 顯示紅色通道
CV2_imshow(blue) #顯示藍(lán)色通道
CV2_imshow(green) #顯示綠色通道
CV2_imshow(img_gs) # 顯示灰色版本
為簡便起見,我們只顯示灰度圖像。
灰度圖像:

?
圖像閾值
閾值的概念非常簡單。如上面在圖像表示中所討論的,像素值可以是0到255之間的任何值。假設(shè)我們希望將圖像轉(zhuǎn)換為二進(jìn)制圖像,即為像素分配0或1的值。為此,我們可以執(zhí)行閾值化。例如,如果閾值(T)值為125,則所有值大于125的像素將被分配值為1,所有值小于或等于該值的像素將被分配值為0。通過代碼獲得更好的理解。
用于閾值的圖像:

如您所見,在生成的圖像中,已經(jīng)建立了兩個(gè)區(qū)域,即黑色區(qū)域(像素值0)和白色區(qū)域(像素值1)。事實(shí)證明,我們設(shè)置的閾值正好在圖像的中間,這就是為什么在此處劃分黑白值的原因。
?
應(yīng)用領(lǐng)域
#1:去除圖像中的噪點(diǎn)
既然您已經(jīng)基本了解了什么是圖像處理及其用途,那么讓我們繼續(xù)學(xué)習(xí)它的一些特定應(yīng)用程序。
在大多數(shù)情況下,我們收集的原始數(shù)據(jù)中有噪點(diǎn),即使圖像難以感知的不良特征。盡管這些圖像可以直接用于特征提取,但是算法的準(zhǔn)確性會(huì)受到很大影響。這就是為什么在將圖像處理傳遞給算法之前對(duì)其進(jìn)行圖像處理以獲得更好的準(zhǔn)確性的原因。
噪聲有很多不同的類型,例如高斯噪聲,胡椒噪聲等。我們可以通過應(yīng)用濾鏡來去除圖像中的噪聲,或者將噪聲降到最低,或者至少將其影響降到最低。濾波器也有很多選擇,每個(gè)都有不同的強(qiáng)度,因此對(duì)于特定類型的噪聲來說是最佳選擇。
為了正確理解這一點(diǎn),我們將在上面考慮過的玫瑰圖像的灰度版本中添加“鹽和胡椒”噪聲,然后嘗試使用不同的濾鏡從嘈雜的圖像中去除該噪聲,然后看看哪個(gè)是最好的-適合那種類型。
import numpy as np
CV2.imwrite('sp_05.jpg', sp_05)
好吧,我們在玫瑰圖像中添加了噪點(diǎn),現(xiàn)在看起來是這樣:
嘈雜的圖像:

現(xiàn)在讓我們在其上應(yīng)用不同的濾波器,并記下我們的觀察結(jié)果,即每個(gè)濾波器降低噪聲的程度。
?
帶有銳化內(nèi)核的算術(shù)濾波器
# 對(duì)噪音圖像進(jìn)行濾波
sharpened_img = CV2.filter2D(sp_05, -1, kernel_sharpening)
CV2_imshow(sharpened_img)
通過對(duì)帶有噪聲的圖像應(yīng)用算術(shù)濾波器,生成的圖像如下所示。與原始灰度圖像進(jìn)行比較后,我們可以看到它使圖像亮度過高,也無法突出玫瑰上的亮點(diǎn)。因此,可以得出結(jié)論,算術(shù)濾波器無法去除噪聲。
算術(shù)濾波器輸出:

?
中點(diǎn)濾波器
print("\n\n---Effects on S&P Noise Image with Probability 0.5---\n\n")
midpoint(sp_05)
將中點(diǎn)濾鏡應(yīng)用到噪聲的圖像上的結(jié)果圖像如下所示。與原始灰度圖像進(jìn)行比較后,我們可以看到,就像上面的核方法一樣,圖像亮度過高。但是,它可以突出玫瑰上的亮點(diǎn)。因此,可以說它是比算術(shù)濾波器更好的選擇,但仍然不能完全恢復(fù)原始圖像。
?
諧諧波均值濾波器
注意:可以在網(wǎng)上輕松找到這些過濾器的實(shí)現(xiàn),并且它們的工作原理超出了本教程的范圍。我們將從抽象/更高的層次來研究應(yīng)用程序。
print("\n\n--- Effects on S&P Noise Image with Probability 0.5 ---\n\n")
CV2_imshow(contraharmonic_mean(sp_05, (3,3), 0.5))
下面顯示了在噪聲下對(duì)圖像應(yīng)用Contraharmonic Mean?Filter?所得到的圖像。與原始灰度圖像進(jìn)行比較后,我們可以看到它已復(fù)制了幾乎與原始圖像完全相同的圖像。其強(qiáng)度/亮度級(jí)別相同,并且也突出了玫瑰上的亮點(diǎn)。因此,我們可以得出結(jié)論,對(duì)諧波均值濾波器在處理鹽和胡椒噪聲方面非常有效。
既然我們已經(jīng)找到了從嘈雜的圖像中恢復(fù)原始圖像的最佳過濾器,那么我們可以繼續(xù)下一個(gè)應(yīng)用程序了。
?
2:使用Canny Edge Detector進(jìn)行邊緣檢測
到目前為止,我們一直在使用的玫瑰圖像具有恒定的背景,即黑色,因此,對(duì)于該應(yīng)用程序,我們將使用不同的圖像以更好地顯示算法的功能。原因是如果背景恒定,則邊緣檢測任務(wù)將變得非常簡單,我們不希望這樣做。
我們在本教程的前面討論了cat分類器,讓我們向前看這個(gè)示例,看看圖像處理如何在其中發(fā)揮不可或缺的作用。
在分類算法中,首先會(huì)掃描圖像中的“對(duì)象”,即,當(dāng)您輸入圖像時(shí),算法會(huì)在該圖像中找到所有對(duì)象,然后將它們與您要查找的對(duì)象的特征進(jìn)行比較。如果是貓分類器,它將對(duì)圖像中找到的所有對(duì)象與貓圖像的特征進(jìn)行比較,如果找到匹配項(xiàng),它將告訴我們輸入圖像包含貓。
由于我們以cat分類器為例,因此公平地使用cat圖像是公平的。下面是我們將使用的圖像:
用于邊緣檢測的圖像:

?
import CV2
import numpy as np
from matplotlib import pyplot as plt
#顯示兩個(gè)圖片
plt.show()
邊緣檢測輸出:

?
如您所見,圖像中包含對(duì)象的部分(在這種情況下是貓)已通過邊緣檢測點(diǎn)到/分開了?,F(xiàn)在您必須要知道,什么是Canny Edge Detector,它是如何實(shí)現(xiàn)的?現(xiàn)在讓我們討論一下。
要理解上述內(nèi)容,需要討論三個(gè)關(guān)鍵步驟。首先,它以與我們之前討論的相似方式對(duì)圖像執(zhí)行降噪。其次,它在每個(gè)像素處使用一階導(dǎo)數(shù)來查找邊緣。其背后的邏輯是存在邊緣的點(diǎn)處,強(qiáng)度會(huì)突然變化,這會(huì)導(dǎo)致一階導(dǎo)數(shù)的值出現(xiàn)尖峰,從而使該像素成為“邊緣像素”。
最后,它執(zhí)行磁滯門限;上面我們說過,邊上的一階導(dǎo)數(shù)的值有一個(gè)峰值,但是我們沒有說明峰值需要多高才能將其分類為邊緣-這稱為閾值!
在本教程的前面,我們討論了簡單的閾值化。磁滯閾值是對(duì)此的改進(jìn),它使用兩個(gè)閾值而不是一個(gè)。其背后的原因是,如果閾值太高,我們可能會(huì)錯(cuò)過一些實(shí)際邊緣(真負(fù)值),而如果閾值太低,我們會(huì)得到很多歸類為實(shí)際上不是邊緣的邊緣(假正值)的點(diǎn)。 )。將一個(gè)閾值設(shè)置為高,將一個(gè)閾值設(shè)置為低。所有高于“高閾值”的點(diǎn)都被標(biāo)識(shí)為邊緣,然后評(píng)估所有高于低閾值但低于高閾值的點(diǎn);被標(biāo)識(shí)為邊的點(diǎn)附近或與之相鄰的點(diǎn)也被標(biāo)識(shí)為邊,其余部分被丟棄。
這些是Canny Edge Detector算法用于識(shí)別圖像邊緣的基本概念/方法。
?
結(jié)論
在本文中,我們學(xué)習(xí)了如何在Windows,MacOS和Linux等不同平臺(tái)上安裝OpenCV(用于Python圖像處理的最流行的庫),以及如何驗(yàn)證安裝是否成功。
我們繼續(xù)討論了什么是圖像處理及其在機(jī)器學(xué)習(xí)的計(jì)算機(jī)視覺領(lǐng)域中的用途。我們討論了一些常見的噪聲類型,以及如何在應(yīng)用程序中使用圖像之前使用不同的濾鏡將其從圖像中去除。
此外,我們了解了圖像處理如何在諸如“對(duì)象檢測”或“分類”之類的高端應(yīng)用中發(fā)揮不可或缺的作用。請(qǐng)注意,本文只是冰山一角,不可能在單個(gè)教程中介紹。