scikit-image 簡介與安裝
我們已經在《OpenCV-Python實戰(9)——OpenCV用于影像分割的閾值技術》中介紹了影像閾值技術,由于影像閾值技術是許多計算機視覺應用中的關鍵步驟,因此許多演算法庫中都包含閾值技術,其中就包括 scikit-image, scikit-image 是用于影像處理的演算法包,其詳細介紹可以參考官方網站,由 scikit-image 操作的影像需要先轉換為 NumPy 陣列,
在本文中,我們將利用 scikit-image 實作閾值技術,如果還沒有安裝 scikit-image 庫,首先需要使用以下命令安裝 scikit-image:
pip install scikit-image
使用 scikit-image 進行閾值處理
為了在 scikit-image 中使用閾值演算法,我們以 Otsu 的二值化演算法對測驗影像進行閾值處理為例進行介紹,第一步是匯入所需的包:
from skimage.filters import threshold_otsu
from skimage import img_as_ubyte
然后使用 scikit-image 應用 Otsu 的二值化演算法:
# 加載影像
image = cv2.imread('example.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist([gray_image], [0], None, [256], [0, 256])
# 基于 otsu 方法的回傳閾值
thresh = threshold_otsu(gray_image)
# 生成布爾陣列:
binary = gray_image > thresh
# 轉換為uint8資料型別
binary = img_as_ubyte(binary)
# 可視化
def show_img_with_matplotlib(color_img, title, pos):
img_RGB = color_img[:, :, ::-1]
ax = plt.subplot(2, 2, pos)
plt.imshow(img_RGB)
plt.title(title, fontsize=8)
plt.axis('off')
def show_hist_with_matplotlib_gray(hist, title, pos, color, t=-1):
ax = plt.subplot(2, 2, pos)
plt.xlabel("bins")
plt.ylabel("number of pixels")
plt.xlim([0, 256])
plt.axvline(x=t, color='m', linestyle='--')
plt.plot(hist, color=color)
show_img_with_matplotlib(image, "image", 1)
show_img_with_matplotlib(cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR), "gray img", 2)
show_hist_with_matplotlib_gray(hist, "grayscale histogram", 3, 'm', thresh)
show_img_with_matplotlib(cv2.cvtColor(binary, cv2.COLOR_GRAY2BGR), "Otsu's binarization (scikit-image)", 4)
plt.show()
threshold_otsu(gray_image) 函式根據 Otsu 的二值化演算法回傳閾值,之后,使用此值構建二進制影像( dtype= bool ),最后應將其轉換為 8 位無符號整數格式( dtype=uint8 )以進行可視化,使用img_as_ubyte() 函式完成轉換程序,
程式輸出如下圖所示:

接下來,介紹下如何使用 scikit-image 中的一些其它閾值技術,
scikit-image 中的其他閾值技術
接下來,將對比 Otsu、triangle、Niblack 和 Sauvola 閾值技術進行閾值處理的不同效果, Otsu 和 triangle 是全域閾值技術,而 Niblack 和 Sauvola 是區域閾值技術,當背景不均勻時,區域閾值技術則是更好的方法閾值處理方法,
同樣的,第一步是匯入所需的包:
from skimage.filters import threshold_otsu, threshold_triangle, threshold_niblack, threshold_sauvola
from skimage import img_as_ubyte
import cv2
import matplotlib.pyplot as plt
呼叫每個閾值方法( threshold_otsu()、threshold_niblack()、threshold_sauvola() 和 threshold_triangle() ),以使用 scikit-image 對比執行閾值操作:
# Otsu
thresh_otsu = threshold_otsu(gray_image)
binary_otsu = gray_image > thresh_otsu
binary_otsu = img_as_ubyte(binary_otsu)
# Niblack
thresh_niblack = threshold_niblack(gray_image, window_size=25, k=0.8)
binary_niblack = gray_image > thresh_niblack
binary_niblack = img_as_ubyte(binary_niblack)
# Sauvola
thresh_sauvola = threshold_sauvola(gray_image, window_size=25)
binary_sauvola = gray_image > thresh_sauvola
binary_sauvola = img_as_ubyte(binary_sauvola)
# triangle
thresh_triangle = threshold_triangle(gray_image)
binary_triangle = gray_image > thresh_triangle
binary_triangle = img_as_ubyte(binary_triangle)
輸出可以在下一個螢屏截圖中看到:
如上圖所示,當影像不均勻時,區域閾值方法可以提供更好的結果,因此,可以將這些區域閾值方法應用于文本識別,
最后,我們了解一個更加有趣的閾值演算法—— Multi-Otsu 閾值技術,其可用于將輸入影像的像素分為多個不同的類別,每個類別根據影像內灰度的強度計算獲得,
Multi-Otsu 根據所需類別的數量計算多個閾值,默認類數為3,此時將獲得三個類別,演算法回傳兩個閾值,由直方圖中的紅線表示,
import matplotlib
import numpy as np
import cv2
from skimage import data
from skimage.filters import threshold_multiotsu
image = cv2.imread('8.png')
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用默認值呼叫 threshold_multiotsu()
thresholds = threshold_multiotsu(image)
regions = np.digitize(image, bins=thresholds)
def show_img_with_matplotlib(img, title, pos, cmap):
ax = plt.subplot(1, 3, pos)
plt.imshow(img, cmap=cmap)
plt.title(title, fontsize=8)
plt.axis('off')
fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(10, 3.5))
# 繪制灰度影像
show_img_with_matplotlib(image, 'Original', 1, cmap='gray')
# 可視化直方圖
ax[1].hist(image.ravel(), bins=255)
ax[1].set_title('Histogram')
for thresh in thresholds:
ax[1].axvline(thresh, color='r')
# 可視化 Multi Otsu 結果
show_img_with_matplotlib(regions, 'Multi-Otsu result', 3, cmap='jet')
plt.subplots_adjust()
plt.show()

可以通過修改 threshold_multiotsu 的 classes 引數來改變類別數,以觀察不同效果:
# 將類別數修改為4
thresholds = threshold_multiotsu(image, classes=3)
regions = np.digitize(image, bins=thresholds)

scikit-image 也提供了其他更多的閾值技術,可以參閱 API 檔案,以查看所有可用方法,
小結
本文中,我們介紹了如何使用 scikit-image 中的不同閾值演算法,包括兩種全域閾值技術( Otsu 和 三角形二值演算法)和兩種區域閾值技術( Niblack 和 Sauvola 演算法),
相關鏈接
OpenCV-Python實戰(9)——OpenCV用于影像分割的閾值技術
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/325435.html
標籤:AI
