Python圖像處理庫(kù)處理步驟
探索Python圖像處理庫(kù)
0. 前言
和多數(shù)編程任務(wù)類似,在編寫圖像處理應(yīng)用程序時(shí),我們無(wú)需重復(fù)“造輪子”的過程,利用 Python
強(qiáng)大且豐富的第三方庫(kù)能夠大量縮減應(yīng)用程序的編寫時(shí)間,達(dá)到事半功倍的效果。在本節(jié)中,我們將學(xué)習(xí)使用不同的 Python
庫(kù)實(shí)現(xiàn)一些常見的圖像處理、變換和可視化技術(shù),這些技術(shù)通??梢杂米鞲鼜?fù)雜的圖像處理任務(wù)的基本預(yù)處理/后處理步驟。
1. 利用 scikit-image 繪制圖像
scikit-image
是基于 scipy
的圖像處理庫(kù),它將圖片作為 Numpy
數(shù)組進(jìn)行處理。在本小節(jié)中,我們將介紹如何在圖像中添加隨機(jī)噪聲添加到圖像(具有不同的方差 sigma
σ \sigma σ )以創(chuàng)建帶有噪聲的圖像,然后創(chuàng)建圖像蒙太奇效果。
(1) 首先導(dǎo)入所需的庫(kù),并使用 imread()
函數(shù)讀取輸入 RGB
圖像:
from skimage.io import imread from skimage.util import random_noise, montage import matplotlib.pyplot as plt import numpy as np im = imread("1.jpg")
(2) 使用 scikit-image
模塊的函數(shù) random_noise()
,通過添加具有給定方差的高斯隨機(jī)噪聲,利用輸入圖像創(chuàng)建帶有噪聲的圖像。根據(jù) scikit-image
文檔所示,函數(shù) random_noise()
函數(shù)的用法如下:
skimage.util.random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs)
使用以上函數(shù)通過向輸入圖像添加具有不同方差的隨機(jī)高斯噪聲來(lái)生成噪聲圖像。
(3) 使用 NumPy
函數(shù) np.linspace()
從 0
到 1
(按值的遞增順序)生成 9
個(gè)不同的 σ \sigma σ 值:
# 在 0 到 1 區(qū)間內(nèi)創(chuàng)建 包含9 個(gè)點(diǎn)的等差序列,作為標(biāo)準(zhǔn)差 sigmas = np.linspace(0, 1, 9) noisy_images = np.zeros((9, im.shape[0], im.shape[1], im.shape[2])) for i in range(len(sigmas)): # 用不同的 Sigma 值在圖像中添加高斯隨機(jī)噪聲 noisy_images[i,:,:,:] = random_noise(im, var=sigmas[i]**2)
(4) 使用 scikit image-util
模塊的函數(shù) montage()
創(chuàng)建含噪圖像的蒙太奇效果圖像。montage()
函數(shù)接受有噪圖像 ndarray
作為輸入?yún)?shù),并在網(wǎng)格中顯示圖像。scikit-image
函數(shù) montage()
的調(diào)用方法如下,利用該函數(shù)可以創(chuàng)建多個(gè)單通道或多通道圖像的蒙太奇效果圖像:
noisy_images_montage = montage(noisy_images, rescale_intensity=True, multichannel=True) # 創(chuàng)建蒙太奇
(5) 最后,繪制噪聲圖像的蒙太奇效果圖像:
plt.figure(figsize=(15,15)) plt.imshow(noisy_images_montage) plt.title('Noisy montage', size=15) plt.axis('off') plt.show()
2. 使用 SciPy 模塊裁剪/調(diào)整圖像大小
調(diào)整圖像大小/裁剪圖像是一項(xiàng)常見且重要的預(yù)處理步驟,例如,深度學(xué)習(xí)模型需要將輸入圖像調(diào)整為同一大小。在本小節(jié)中,我們將學(xué)習(xí)如何使用 scipy.ndimage
模塊的 zoom()
函數(shù)縮放圖像,然后介紹如何使用 Numpy ndarray
切片語(yǔ)法裁剪圖像。
(1) 首先,從 Python
庫(kù)模塊導(dǎo)入所需的函數(shù):
from scipy import ndimage import matplotlib.pyplot as plt from skimage.io import imread
(2) 讀取輸入圖像并使用 scipy.ndimage.zoom()
函數(shù)縮放圖像。根據(jù) SciPy
文檔所述,zoom()
函數(shù)的調(diào)用方式如下:
scipy.ndimage.zoom(input, zoom, output=None, order=3, mode='constant', cval=0.0, prefilter=True)
zoom()
函數(shù)默認(rèn)使用樣條插值縮放陣列,在函數(shù)中通過指定 “nearest
” 模式執(zhí)行樣條插值,樣條插值將通過復(fù)制最近的像素來(lái)擴(kuò)展輸入圖像。我們可以分別指定每個(gè)軸的縮放因子,由于我們不需要在顏色通道上縮放,所以通道上的縮放因子指定為 1
,而寬度和高度維度的縮放因子指定為 2
,樣條插值的階 (order
),默認(rèn)為 3
,階是 [0, 5]
范圍內(nèi)的整數(shù):
im = imread('1.jpg') / 255 zoomed_im = ndimage.zoom(im, (2,2,1), mode='nearest', order=1) # 縮放圖像 print(im.shape, zoomed_im.shape)
(3) 最后,使用 NumPy ndarray
切片語(yǔ)法通過裁剪圖像顯示原始圖像和縮放后的圖像:
plt.figure(figsize=(20,10)) plt.subplot(121) plt.imshow(im) plt.title('Original Image', size=25) plt.subplot(122) plt.imshow(zoomed_im[125:325,375:550,:]) # 裁剪圖像 plt.title('Zoomed and Cropped Image', size=25) plt.show()
3. 使用 OpenCV 繪制輪廓
3.1 輪廓簡(jiǎn)介
輪廓可以簡(jiǎn)單地理解為連接圖像中對(duì)象所有邊界連續(xù)點(diǎn)的曲線,輪廓通常具有相同的顏色或強(qiáng)度。輪廓是形狀分析、物體檢測(cè)等應(yīng)用中的重要工具。為了得到更好的輪廓精度,可以使用二值圖像檢測(cè)對(duì)象輪廓。因此,在檢測(cè)圖像輪廓之前,通常需要對(duì)圖像應(yīng)用閾值處理或 Canny
邊緣檢測(cè)算法。
在 OpenCV
中,可以使用 cv2.threshold()
函數(shù)使用固定閾值創(chuàng)建二值圖像:
cv2.threshold(img, thresh, maxval, type)
使用 Canny
算法檢測(cè)圖像邊緣:
Canny(img, threshold1, threshold2, apertureSize = 3, L2gradient = false)
Canny()
函數(shù)將輸入灰度圖像和兩個(gè)滯后閾值(最大閾值和最小閾值)作為輸入,其核心思想在于,當(dāng)像素值>最大閾值時(shí),其被視為強(qiáng)邊緣像素,而在最小閾值和最大閾值之間的像素值被認(rèn)為是弱邊緣像素。強(qiáng)邊將包含在邊緣圖中,而弱邊僅當(dāng)它們連接到強(qiáng)邊時(shí)才會(huì)包含在邊緣圖中,通常,上閾值的大小為下閾值的 1.5–2
倍。
使用 findContours()
函數(shù)可以計(jì)算灰度圖像的輪廓。首先,需要使用以上兩個(gè)函數(shù)將圖像轉(zhuǎn)換為二值圖像,然后計(jì)算圖像輪廓。此外,需要注意的是,使用 OpenCV
函數(shù)查找輪廓需要從黑色背景中查找白色對(duì)象,要檢測(cè)的對(duì)象是白色的,背景是黑色的。findContours()
函數(shù)接受三個(gè)參數(shù),用于查找二值圖像中的輪廓:
cv2.findContours(img, mode, method)
3.2 繪制輪廓
(1) 首先,導(dǎo)入所需的庫(kù)。使用 OpenCV
的 imread()
函數(shù)從磁盤讀取輸入圖像,OpenCV
以 BGR
格式存儲(chǔ) RGB
圖像,如果想要使用 matplotlib.pyplot
正確顯示,我們需要使用 cv2.cvtClor()
函數(shù)將其轉(zhuǎn)換為 RGB
格式,然后繪制圖像:
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread("1.jpg") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 將 BGR 模式轉(zhuǎn)換為 RGB
(2) 將圖像轉(zhuǎn)換為灰度圖像,并使用具有合適滯后閾值的 Canny
邊緣檢測(cè)器來(lái)查找圖像中的邊緣,然后從二值邊緣圖像中檢測(cè)輪廓:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edged = cv2.Canny(gray, 125, 250) contours_edged, _ = cv2.findContours(edged, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) print("Number of Contours found with Canny edges = " + str(len(contours_edged)))
或者使用閾值函數(shù)將灰度圖像轉(zhuǎn)換為二值圖像,然后根據(jù)閾值圖像中查找輪廓:
ret, thresh = cv2.threshold(gray, 127, 255, 0) contours_thresh, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) print("Number of Contours found with threshold = " + str(len(contours_thresh)))
(3) 使用 matplotlib.pyplot
模塊的 imshow()
函數(shù)顯示原始圖像、閾值圖像和輪廓圖像:
plt.figure(figsize=(20,15)) plt.subplot(221), plt.imshow(image), plt.title('Original Image', size=10), plt.axis('off') plt.subplot(222), plt.imshow(thresh, cmap='gray'), plt.title('Threshold Image', size=10), plt.axis('off') plt.subplot(223), plt.imshow(edged, cmap='gray'), plt.title('Canny Edges Image', size=10), plt.axis('off') plt.subplot(224), plt.imshow(cv2.drawContours(np.copy(image), contours_thresh, -1, (0,255,0), 3)) plt.title('Contour Lines with Threshold Image', size=10), plt.axis('off')
(4) 最后,從邊緣二值圖像中繪制前 n=200
個(gè)輪廓:
n = 200 plt.figure(figsize=(7,7)) colors = plt.cm.coolwarm(np.linspace(0, 1, n)) for i in range(n): image = cv2.drawContours(image, contours_edged, i, 255*colors[i], 3) plt.imshow(image) plt.title('First ' + str(n) + ' Contour lines with Canny Edges', size=10), plt.axis('off') plt.tight_layout() plt.show()
4. 使用 OpenCV 統(tǒng)計(jì)圖像中的對(duì)象數(shù)量
接下來(lái),我們學(xué)習(xí)使用 OpenCV
的 findContours()
函數(shù)來(lái)統(tǒng)計(jì)圖像中的對(duì)象數(shù),我們以從輸入圖像中計(jì)算孟加拉語(yǔ)字母數(shù)量為例。
(1) 導(dǎo)入所需的庫(kù)后,將圖像轉(zhuǎn)換為灰度圖像,并使用 Canny
邊緣檢測(cè)器:
import cv2 import numpy as np import matplotlib.pylab as plt image = cv2.imread('2.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edged = cv2.Canny(gray, 75, 150)
(2) 使用形態(tài)學(xué)閉運(yùn)算函數(shù) morphologyEx()
刪除圖像中的小孔,改進(jìn)檢測(cè)質(zhì)量:
thresh = cv2.threshold(gray, 215, 255, cv2.THRESH_BINARY_INV)[1] kernel = np.ones((2,2),np.uint8) thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
(3) 最后,使用 findContours()
函數(shù)查找所有對(duì)象輪廓,并使用 drawContours()
函數(shù)迭代繪制這些輪廓:
cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) output = image.copy() for c in cnts: cv2.drawContours(output, [c], -1, (0, 0, 255), 2)
(4) 繪制原始圖像、二值圖像和輸出圖像:
text = "Found {} objects".format(len(cnts)) cv2.putText(output, text, (50, 220), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) plt.figure(figsize=(20,7)) plt.subplot(131), plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)), plt.axis('off'), plt.title('Original image', size=10) plt.subplot(132), plt.imshow(thresh, cmap='gray'), plt.axis('off'), plt.title('Binary image', size=10) plt.subplot(133), plt.imshow(cv2.cvtColor(output, cv2.COLOR_BGR2RGB)), plt.axis('off'), plt.title('Counting objects', size=10) plt.show()
5. 使用 PIL 將彩色圖像轉(zhuǎn)換為灰度圖像
在本小節(jié)中,我們將學(xué)習(xí) PIL
圖像模式以及如何將帶有調(diào)色板的 PNG
彩色圖像轉(zhuǎn)換為灰度圖像。要完成圖像轉(zhuǎn)換任務(wù),最簡(jiǎn)單的方法是使用 convert()
函數(shù)將圖像的色彩模式從彩色圖像轉(zhuǎn)換為灰度圖像。
5.1 使用 convert() 函數(shù)
(1) 首先,導(dǎo)入所需的庫(kù),并使用 PIL
圖像類的方法將圖像從磁盤讀取到圖像對(duì)象,使用 matplotlib
繪制原始 PNG
圖像:
import numpy as np from PIL import Image import matplotlib.pyplot as plt img = Image.open('1.jpg') print(img.mode) plt.imshow(img) plt.axis('off') plt.title('Original Image') plt.show()
(2) 接下來(lái),在 image
對(duì)象上,需要調(diào)用方法 convert()
轉(zhuǎn)換圖像色彩模式,將其轉(zhuǎn)換為灰度圖像,然后繪制輸出圖像:
img = img.convert('RGB').convert('L') print(img.mode) plt.imshow(img, cmap='gray') plt.axis('off') plt.title('Grayscale Image') plt.show()
5.2 將帶有調(diào)色板的 PNG 圖像轉(zhuǎn)換為灰度圖像
還有另一種使用 PIL
庫(kù)將圖像轉(zhuǎn)換為灰度圖像的方法,相較于上一種方法,這是一種更復(fù)雜的方式。但使用這種方法可以令我們明確理解圖像如何以 PIL
格式進(jìn)行存儲(chǔ)。
(1) 首先導(dǎo)入所有所需的庫(kù),并定義函數(shù) rgb2gray()
以從 RGB
彩色圖像計(jì)算灰度圖像強(qiáng)度值,讀取 PNG
圖像并提取圖像調(diào)色板:
import numpy as np from PIL import Image import matplotlib.pyplot as plt def rgb2gray(R, G, B): return 0.2989 * R + 0.5870 * G + 0.1140 * B img = Image.open('2.jpg') # 讀取 jpg 圖像 pal = img.getpalette() # 獲取調(diào)色板
(2) 使用 PIL image
類的 getpixel()
方法計(jì)算圖像中每個(gè)像素值的調(diào)色板索引。使用計(jì)算的索引從圖像調(diào)色板中獲取每個(gè)像素的 R
、G
和 B
值。最后,使用自定義 rgb2gray()
函數(shù)(或使用 scikit-image.color
模塊中的相同函數(shù))計(jì)算與圖像中相同位置對(duì)應(yīng)的輸出像素的灰度強(qiáng)度值:
arr = np.zeros((img.height, img.width)) # 初始化輸出圖像 for i in range(arr.shape[0]): for j in range(arr.shape[1]): idx = img.getpixel((j,i)) # 獲取調(diào)色板中像素的索引 R, G, B = pal[3*idx], pal[3*idx+1], pal[3*idx+2] # 獲取像素 R,G,B 值 arr[i,j] = rgb2gray(R, G, B) # 轉(zhuǎn)換為灰度圖像
(3) 繪制輸出圖像:
plt.subplot(121) plt.imshow(img) plt.title('Origial Image') plt.axis('off') plt.subplot(122) plt.imshow(arr, cmap='gray') plt.title('Grayscale Image') plt.axis('off') plt.show()
6. 使用 SciPy 旋轉(zhuǎn)圖像
有時(shí),我們可能需要幾何變換作為圖像處理任務(wù)中的預(yù)處理步驟。在本小節(jié)中,我們將學(xué)習(xí)如何使用 scipy.ndimage
模塊中的 rotate()
函數(shù)旋轉(zhuǎn)圖像。接下來(lái),我們將逆時(shí)針旋轉(zhuǎn)圖像一定的角度,并使用樣條插值。
(1) 從相應(yīng)的 Python
庫(kù)模塊導(dǎo)入所需的函數(shù),讀取彩色輸入圖像:
from scipy.ndimage import rotate from skimage.io import imread from matplotlib import pyplot as plt im = imread('1.jpg')
(2) 應(yīng)用 SciPy
庫(kù)的 rotate()
函數(shù),ndimage
模塊根據(jù)輸入圖像與旋轉(zhuǎn)值執(zhí)行旋轉(zhuǎn)變換,逆時(shí)針旋轉(zhuǎn)按照慣例應(yīng)當(dāng)以正角度表示,而順時(shí)針則以負(fù)角度表示:
im = rotate(im, -45) plt.figure(figsize=(5,5)) plt.imshow(im) plt.axis('off') plt.show()
小結(jié)
在本節(jié)中,我們介紹了多個(gè)用于圖像處理的流行 Python
第三方庫(kù),利用這些圖像處理庫(kù)我們可以輕松的執(zhí)行基本的圖像變換操作。本節(jié)我們重點(diǎn)介紹了如何利用 scikit-image
繪制圖像、使用 PIL
庫(kù)修改圖像模式、利用 SciPy
庫(kù)調(diào)整圖像大小以及進(jìn)行簡(jiǎn)單的幾何變換、同時(shí)介紹了輪廓的基本概念并學(xué)習(xí)了如何提取對(duì)象輪廓、進(jìn)一步我們可以根據(jù)輪廓可以統(tǒng)計(jì)圖像中的目標(biāo)數(shù)量。
到此這篇關(guān)于Python圖像處理探索之Python圖像處理庫(kù)的文章就介紹到這了,更多相關(guān)Python圖像處理庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VSCode2022配置Python3.9.6的詳細(xì)教程
這篇文章主要介紹了VSCode2022配置Python3.9.6教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09python實(shí)現(xiàn)根據(jù)月份和日期得到星座的方法
這篇文章主要介紹了python實(shí)現(xiàn)根據(jù)月份和日期得到星座的方法,涉及Python操作字符串及數(shù)組的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03Pycharm中安裝pywin32報(bào)錯(cuò)問題及解決
這篇文章主要介紹了Pycharm中安裝pywin32報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04django通過ajax發(fā)起請(qǐng)求返回JSON格式數(shù)據(jù)的方法
這篇文章主要介紹了django通過ajax發(fā)起請(qǐng)求返回JSON格式數(shù)據(jù)的方法,較為詳細(xì)的分析了django處理ajax請(qǐng)求的技巧,需要的朋友可以參考下2015-06-06使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化
這篇文章主要給大家介紹了關(guān)于使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化的相關(guān)資料,文中給出了詳細(xì)的思路以及示例代碼,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03Python jieba 中文分詞與詞頻統(tǒng)計(jì)的操作
這篇文章主要介紹了Python jieba 中文分詞與詞頻統(tǒng)計(jì)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2021-03-03python爬蟲把url鏈接編碼成gbk2312格式過程解析
這篇文章主要介紹了python爬蟲把url鏈接編碼成gbk2312格式過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06Python中如何使用if語(yǔ)句處理列表實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于在Python中如何使用if語(yǔ)句處理列表的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02