Python圖像處理庫處理步驟
探索Python圖像處理庫
0. 前言
和多數(shù)編程任務類似,在編寫圖像處理應用程序時,我們無需重復“造輪子”的過程,利用 Python
強大且豐富的第三方庫能夠大量縮減應用程序的編寫時間,達到事半功倍的效果。在本節(jié)中,我們將學習使用不同的 Python
庫實現(xiàn)一些常見的圖像處理、變換和可視化技術,這些技術通常可以用作更復雜的圖像處理任務的基本預處理/后處理步驟。
1. 利用 scikit-image 繪制圖像
scikit-image
是基于 scipy
的圖像處理庫,它將圖片作為 Numpy
數(shù)組進行處理。在本小節(jié)中,我們將介紹如何在圖像中添加隨機噪聲添加到圖像(具有不同的方差 sigma
σ \sigma σ )以創(chuàng)建帶有噪聲的圖像,然后創(chuàng)建圖像蒙太奇效果。
(1) 首先導入所需的庫,并使用 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()
,通過添加具有給定方差的高斯隨機噪聲,利用輸入圖像創(chuàng)建帶有噪聲的圖像。根據(jù) scikit-image
文檔所示,函數(shù) random_noise()
函數(shù)的用法如下:
skimage.util.random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs)
使用以上函數(shù)通過向輸入圖像添加具有不同方差的隨機高斯噪聲來生成噪聲圖像。
(3) 使用 NumPy
函數(shù) np.linspace()
從 0
到 1
(按值的遞增順序)生成 9
個不同的 σ \sigma σ 值:
# 在 0 到 1 區(qū)間內(nèi)創(chuàng)建 包含9 個點的等差序列,作為標準差 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 值在圖像中添加高斯隨機噪聲 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)建多個單通道或多通道圖像的蒙太奇效果圖像:
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)整圖像大小/裁剪圖像是一項常見且重要的預處理步驟,例如,深度學習模型需要將輸入圖像調(diào)整為同一大小。在本小節(jié)中,我們將學習如何使用 scipy.ndimage
模塊的 zoom()
函數(shù)縮放圖像,然后介紹如何使用 Numpy ndarray
切片語法裁剪圖像。
(1) 首先,從 Python
庫模塊導入所需的函數(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ù)默認使用樣條插值縮放陣列,在函數(shù)中通過指定 “nearest
” 模式執(zhí)行樣條插值,樣條插值將通過復制最近的像素來擴展輸入圖像。我們可以分別指定每個軸的縮放因子,由于我們不需要在顏色通道上縮放,所以通道上的縮放因子指定為 1
,而寬度和高度維度的縮放因子指定為 2
,樣條插值的階 (order
),默認為 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
切片語法通過裁剪圖像顯示原始圖像和縮放后的圖像:
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 輪廓簡介
輪廓可以簡單地理解為連接圖像中對象所有邊界連續(xù)點的曲線,輪廓通常具有相同的顏色或強度。輪廓是形狀分析、物體檢測等應用中的重要工具。為了得到更好的輪廓精度,可以使用二值圖像檢測對象輪廓。因此,在檢測圖像輪廓之前,通常需要對圖像應用閾值處理或 Canny
邊緣檢測算法。
在 OpenCV
中,可以使用 cv2.threshold()
函數(shù)使用固定閾值創(chuàng)建二值圖像:
cv2.threshold(img, thresh, maxval, type)
使用 Canny
算法檢測圖像邊緣:
Canny(img, threshold1, threshold2, apertureSize = 3, L2gradient = false)
Canny()
函數(shù)將輸入灰度圖像和兩個滯后閾值(最大閾值和最小閾值)作為輸入,其核心思想在于,當像素值>最大閾值時,其被視為強邊緣像素,而在最小閾值和最大閾值之間的像素值被認為是弱邊緣像素。強邊將包含在邊緣圖中,而弱邊僅當它們連接到強邊時才會包含在邊緣圖中,通常,上閾值的大小為下閾值的 1.5–2
倍。
使用 findContours()
函數(shù)可以計算灰度圖像的輪廓。首先,需要使用以上兩個函數(shù)將圖像轉換為二值圖像,然后計算圖像輪廓。此外,需要注意的是,使用 OpenCV
函數(shù)查找輪廓需要從黑色背景中查找白色對象,要檢測的對象是白色的,背景是黑色的。findContours()
函數(shù)接受三個參數(shù),用于查找二值圖像中的輪廓:
cv2.findContours(img, mode, method)
3.2 繪制輪廓
(1) 首先,導入所需的庫。使用 OpenCV
的 imread()
函數(shù)從磁盤讀取輸入圖像,OpenCV
以 BGR
格式存儲 RGB
圖像,如果想要使用 matplotlib.pyplot
正確顯示,我們需要使用 cv2.cvtClor()
函數(shù)將其轉換為 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 模式轉換為 RGB
(2) 將圖像轉換為灰度圖像,并使用具有合適滯后閾值的 Canny
邊緣檢測器來查找圖像中的邊緣,然后從二值邊緣圖像中檢測輪廓:
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ù)將灰度圖像轉換為二值圖像,然后根據(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
個輪廓:
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)計圖像中的對象數(shù)量
接下來,我們學習使用 OpenCV
的 findContours()
函數(shù)來統(tǒng)計圖像中的對象數(shù),我們以從輸入圖像中計算孟加拉語字母數(shù)量為例。
(1) 導入所需的庫后,將圖像轉換為灰度圖像,并使用 Canny
邊緣檢測器:
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)學閉運算函數(shù) morphologyEx()
刪除圖像中的小孔,改進檢測質(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ù)查找所有對象輪廓,并使用 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 將彩色圖像轉換為灰度圖像
在本小節(jié)中,我們將學習 PIL
圖像模式以及如何將帶有調(diào)色板的 PNG
彩色圖像轉換為灰度圖像。要完成圖像轉換任務,最簡單的方法是使用 convert()
函數(shù)將圖像的色彩模式從彩色圖像轉換為灰度圖像。
5.1 使用 convert() 函數(shù)
(1) 首先,導入所需的庫,并使用 PIL
圖像類的方法將圖像從磁盤讀取到圖像對象,使用 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) 接下來,在 image
對象上,需要調(diào)用方法 convert()
轉換圖像色彩模式,將其轉換為灰度圖像,然后繪制輸出圖像:
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 圖像轉換為灰度圖像
還有另一種使用 PIL
庫將圖像轉換為灰度圖像的方法,相較于上一種方法,這是一種更復雜的方式。但使用這種方法可以令我們明確理解圖像如何以 PIL
格式進行存儲。
(1) 首先導入所有所需的庫,并定義函數(shù) rgb2gray()
以從 RGB
彩色圖像計算灰度圖像強度值,讀取 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()
方法計算圖像中每個像素值的調(diào)色板索引。使用計算的索引從圖像調(diào)色板中獲取每個像素的 R
、G
和 B
值。最后,使用自定義 rgb2gray()
函數(shù)(或使用 scikit-image.color
模塊中的相同函數(shù))計算與圖像中相同位置對應的輸出像素的灰度強度值:
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) # 轉換為灰度圖像
(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 旋轉圖像
有時,我們可能需要幾何變換作為圖像處理任務中的預處理步驟。在本小節(jié)中,我們將學習如何使用 scipy.ndimage
模塊中的 rotate()
函數(shù)旋轉圖像。接下來,我們將逆時針旋轉圖像一定的角度,并使用樣條插值。
(1) 從相應的 Python
庫模塊導入所需的函數(shù),讀取彩色輸入圖像:
from scipy.ndimage import rotate from skimage.io import imread from matplotlib import pyplot as plt im = imread('1.jpg')
(2) 應用 SciPy
庫的 rotate()
函數(shù),ndimage
模塊根據(jù)輸入圖像與旋轉值執(zhí)行旋轉變換,逆時針旋轉按照慣例應當以正角度表示,而順時針則以負角度表示:
im = rotate(im, -45) plt.figure(figsize=(5,5)) plt.imshow(im) plt.axis('off') plt.show()
小結
在本節(jié)中,我們介紹了多個用于圖像處理的流行 Python
第三方庫,利用這些圖像處理庫我們可以輕松的執(zhí)行基本的圖像變換操作。本節(jié)我們重點介紹了如何利用 scikit-image
繪制圖像、使用 PIL
庫修改圖像模式、利用 SciPy
庫調(diào)整圖像大小以及進行簡單的幾何變換、同時介紹了輪廓的基本概念并學習了如何提取對象輪廓、進一步我們可以根據(jù)輪廓可以統(tǒng)計圖像中的目標數(shù)量。
到此這篇關于Python圖像處理探索之Python圖像處理庫的文章就介紹到這了,更多相關Python圖像處理庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python實現(xiàn)根據(jù)月份和日期得到星座的方法
這篇文章主要介紹了python實現(xiàn)根據(jù)月份和日期得到星座的方法,涉及Python操作字符串及數(shù)組的技巧,非常具有實用價值,需要的朋友可以參考下2015-03-03django通過ajax發(fā)起請求返回JSON格式數(shù)據(jù)的方法
這篇文章主要介紹了django通過ajax發(fā)起請求返回JSON格式數(shù)據(jù)的方法,較為詳細的分析了django處理ajax請求的技巧,需要的朋友可以參考下2015-06-06使用pytorch提取卷積神經(jīng)網(wǎng)絡的特征圖可視化
這篇文章主要給大家介紹了關于使用pytorch提取卷積神經(jīng)網(wǎng)絡的特征圖可視化的相關資料,文中給出了詳細的思路以及示例代碼,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2022-03-03Python jieba 中文分詞與詞頻統(tǒng)計的操作
這篇文章主要介紹了Python jieba 中文分詞與詞頻統(tǒng)計的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03python爬蟲把url鏈接編碼成gbk2312格式過程解析
這篇文章主要介紹了python爬蟲把url鏈接編碼成gbk2312格式過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-06-06