影象處理中媲美matlab的python包——scikit-image(skimage)包的用法詳解
前言:
基於python的圖片處理包還是很多的,比如PIL,Pillow, opencv, scikit-image等。其中,PIL和Pillow只提供最基礎的數字影象處理,功能有限;opencv本質上是一個c++庫,只是提供了python的介面,官方更新速度非常慢,而且安裝很不容易。綜合來看,scikit-image是基於scipy的一款影象處理包,它功能非常齊全,同時將圖片作為numpy陣列進行處理,幾乎集合了matlab的所有影象處理功能,在資料的處理方式,函式名字等方面對matlab的模仿姿勢非常到位。
更為重要的是,作為python的一個影象處理包,這個包是完全開源免費的,而且可以依託於python強大的功能,與tensorflow等軟體配合使用於主流的深度學習等領域。因此,用scikit-image進行影象處理是一個非常好的選擇,matlab能幹的事情它都能幹,matlab不能幹的事情他也可以,個人認為在數字影象處理領域,它是完全可以代替matlab的。價格昂貴且介面並不怎麼美觀的matlab簡直要哭暈在廁所。
當然,如果有一定的程式設計基礎,學習這個包最好的方法是去看官方文件,scikit-image官方文件,對於初學者來說,可以先看以下通俗版的介紹入門。
一、安裝。
二、匯入scikit-image包
這個包有非常多的子模組,分別負責不同的功能,所以在匯入的時候,對於不同的功能可以分別匯入不同的模組,各模組的功能如下:
子模組名稱 | 主要實現功能 |
---|---|
io | 讀取、儲存和顯示圖片或視訊 |
data | 提供一些測試圖片和樣本資料 |
color | 顏色空間變換 |
filters | 影象增強、邊緣檢測、排序濾波器、自動閾值等 |
draw | 操作於numpy陣列上的基本圖形繪製,包括線條、矩形、圓和文字等 |
transform | 幾何變換或其它變換,如旋轉、拉伸和拉東變換等 |
morphology | 形態學操作,如開閉運算、骨架提取等 |
exposure | 圖片強度調整,如亮度調整、直方圖均衡等 |
feature | 特徵檢測與提取等 |
measure | 影象屬性的測量,如相似性或等高線等 |
segmentation | 影象分割 |
restoration | 影象恢復 |
util | 通用函式 |
下邊分別敘述
from skimage import 函式名
1、讀取,顯示影象。(用到的模組:io)
from skimage import io
img=io.imread('圖片路徑',as_grey = bool值)
io.imshow(img)
其中,as_grey屬性如果是True,則讀入彩圖之後自動轉換成灰度影象,否則讀入彩圖,預設為False。
讀入圖片之後,可以獲取圖片的各種屬性
print(type(img)) #顯示型別
print(img.shape) #顯示尺寸
print(img.shape[0]) #圖片寬度
print(img.shape[1]) #圖片高度
print(img.shape[2]) #圖片通道數
print(img.size) #顯示總畫素個數
print(img.max()) #最大畫素值
print(img.min()) #最小畫素值
print(img.mean()) #畫素平均值
2、儲存影象
讀取時matlab的語法幾乎相同,寫入圖片檔案時,將matlab中的imwrite()
函式改成imsave()
函式即可。
from skimage import io,data
img=io.imread('圖片路徑',as_grey = bool值)#以上的讀取圖片函式
io.imshow(img)
io.imsave('儲存路徑',img)
儲存圖片的時候也可以隨便儲存為不同的格式(jpg,png等)。
對於二值影象來說,用io.imsave()
函式直接儲存會得到一張黑色的影象,個人覺得是因為儲存的時候程式依舊以為圖片的數值範圍是0~255,需要轉換一下資料型別,有知道的更方便的解決辦法的可以在評論區交流
3、影象的裁剪,縮放。(用到的模組:transform)
1)改變圖片尺寸resize
同樣,提供了skimage.transform.resize(image, output_shape)
函式,和matlab裡重新調整影象大小的語法沒有絲毫區別。
image: 需要改變尺寸的圖片
output_shape: 新的圖片尺寸
from skimage import transform,io
import matplotlib.pyplot as plt#用於顯示影象
img=io.imread('圖片路徑',as_grey = bool值)
dst=transform.resize(img, (長, 寬))
plt.figure('resize')
plt.subplot(121)
plt.title('before resize')
plt.imshow(img,plt.cm.gray)
plt.subplot(122)
plt.title('before resize')
plt.imshow(dst,plt.cm.gray)
plt.show()
可以將圖片變成80*60大小。
4、圖片的連通域標記與選擇(用到的模組:measure)
1)獲取連通域及其屬性
獲取影象連通域是影象處理中比較高階的功能,matlab可以通過函式直接獲取影象的連通域,在skimage包中,我們同樣可以採用measure子模組下的label()函式來實現相同的效果。
函式格式:
from skimage import measure
labels = measure.label(二值影象,connectivity=None)
- connectivity表示連線的模式,1代表4鄰接,2代表8鄰接。
返回一個與影象同樣大小的陣列,背景都是0,對於前景的連通域從1開始往上標記。
當然,此時做到的只是對連通域進行標記給人看,如果想分別對每一個連通區域進行操作,比如計算面積、外接矩形、凸包面積等,則需要呼叫measure子模組的regionprops()函式。在同上匯入measure包之後,該函式格式為:
label_att = measure.regionprops(label_image)
這樣,我們就可以從“label_att”這個數組裡獲取影象裡任意一個連通域的屬性,屬性列表如下:
屬性名稱 | 型別 | 描述 |
---|---|---|
area | int | 區域內畫素點總數 |
bbox | tuple | 邊界外接框(min_row, min_col, max_row, max_col) |
centroid | array | 質心座標 |
convex_area | int | 凸包內畫素點總數 |
convex_image | ndarray | 和邊界外接框同大小的凸包 |
coords | ndarray | 區域內畫素點座標 |
Eccentricity | float | 離心率 |
equivalent_diameter | float | 和區域面積相同的圓的直徑 |
euler_number | int | 區域尤拉數 |
extent | float | 區域面積和邊界外接框面積的比率 |
filled_area | int | 區域和外接框之間填充的畫素點總數 |
perimeter | float | 區域周長 |
label | int | 區域標記 |
這裡需要注意的是:measure.label函式獲取的連通域背景是0,前景的連通域其實是從1開始計算,而measure.regionprops函式獲取的連通域不包含背景,前景的連通域屬性就是從0開始的。
下面舉一個例子:
隨便找一張圖片如下:
執行程式碼如下:
from skimage import io,filters,measure
img = io.imread('test.jpg',as_grey=True) #讀取圖片
thresh = filters.threshold_otsu(img) #用otsu演算法確定最佳分割閾值
bwimg =(img>=(thresh)) #用閾值進行分割,生成二值影象
labels = measure.label(bwimg) #標記連通域
label_att = measure.regionprops(labels) #獲取各個連通域的屬性。
可以看到labels找出了5個連通域,而label_att卻只有四個連通域的屬性,這是因為不包括背景的連通域的屬性。
2)刪除小塊區域
圖片難免會有噪聲,在以上獲取連通域處理的時候,噪點也會算作是一個很小的連通域,morphology子模組的remove_small_objects()函式提供了方便的噪點去除功能。函式格式(一般與上一個函式連用):
from skimage import morphology
img1 = morphology.remove_small_objects(ar, min_size=要刪除的連通域大小閾值, connectivity=1,in_place=False)
img1是刪除了小於連通域面積閾值的二值影象。
其中,各引數含義如下:
- ar: 上邊的獲取的標記好連通域的陣列
- connectivity: 鄰接模式,1表示4鄰接,2表示8鄰接
- in_place: bool型值,如果為True,表示直接在輸入影象中刪除小塊區域,否則進行復制後再刪除。預設為False.
附錄:
scikit-image這個包對matlab的模仿甚至還體現在很多細節上,比如說,matlab會自帶一些圖片讓使用者進行測試,如果我們不想從外部讀取圖片,就可以直接使用這些示例圖片對函式進行測試,scikit-image包同樣也有如下功能:
而且使用方法也很簡單:
from skimage import io,data
img=data.lena()
io.imshow(img)
astronaut | 宇航員圖片 |
---|---|
coffee | 一杯咖啡圖片 |
lena | lena美女圖片 |
camera | 拿相機的人圖片 |
coins | 硬幣圖片 |
moon | 月亮圖片 |
checkerboard | 棋盤圖片 |
horse | 馬圖片 |
page | 書頁圖片 |
chelsea | 小貓圖片 |
hubble_deep_field | 星空圖片 |
text | 文字圖片 |
clock | 時鐘圖片 |
immunohistochemistry | 結腸圖片 |
圖片名對應的就是函式名,這些示例圖片存放在skimage的安裝目錄下面,路徑名稱為data_dir,也可以將這個路徑打印出來:
from skimage import data_dir
print(data_dir)