一文概述用 python 的 scikit-image 模塊進行圖像分割

2021-01-07 雷鋒網

雷鋒網 AI 科技評論按,隨著人工智慧技術的逐年火熱,越來越多的人投入到計算機視覺領域的相關研究中。而圖像分割是圖像處理中非常重要的一個步驟,它是把圖像分成若干個特定的、具有獨特性質的區域,並提取出感興趣目標的技術。

近日,工程師 Parul Pandey 發表了一篇博文,在博文中,她介紹了用 python 的 scikit-image 庫進行圖像分割的方法。具體涉及 scikit-image 的安裝,圖像導入以及用監督算法和無監督算法進行圖像分割的方法。雷鋒網 AI 科技評論編譯整理如下。

遲早有一天,所有的一切都是數字,包括圖像。

看過《終結者》的人肯定會認為這是那個時代最偉大的科幻電影。在這部電影中,James Cameron 引入了一個有趣的視覺效果概念,它可以使觀眾有可能躲在被稱為終結者的電子人的眼睛後面。這種效應被稱為「終結者視覺」,在某種程度上,它將人與背景分割開來。在當時,這聽起來完全是天方夜譚,但在如今,圖像分割已經成為了許多圖像處理技術的重要組成部分。

圖像分割

我們都很清楚,Photoshop 或類似的圖形編輯器提供了無限的可能性,可以將一個人從一張圖片中帶到另一張圖片中。然而,要這樣做,首先需要確定那個人在源圖像中的位置,這就需要用到圖像分割技術了。有許多庫是為圖像分析而編寫的。在本文中,我們將詳細討論基於 python 的圖像處理庫 scikit-image。

完整的代碼也可以從與本文關聯的 Github 存儲庫中訪問。

Scikit-image

SciKit Image 是一個專門用於圖像處理的 python 包。

安裝

可以按如下方式安裝 scikit-image:

pip install -U scikit-image(Linux and OSX)pip install scikit-image(Windows)# For Conda-based distributionsconda install scikit-image

python 中的圖像處理概述

在使用圖像分割技術之前,有必要先了解 scikit image 以及它是如何處理圖像的。

從 skimage 庫導入灰度圖像

skimage 數據模塊包含一些內置示例數據集,這些數據集通常以 jpeg 或 png 格式存儲。

from skimage import dataimport numpy as npimport matplotlib.pyplot as pltimage = data.binary_blobs()plt.imshow(image, cmap='gray')

從 skimage 庫導入彩色圖像

from skimage import dataimport numpy as npimport matplotlib.pyplot as pltimage = data.astronaut()plt.imshow(image)

從外部源導入圖像

# The I/O module is used for importing the imagefrom skimage import dataimport numpy as npimport matplotlib.pyplot as pltfrom skimage import ioimage = io.imread('skimage_logo.png')plt.imshow(image);

加載多個圖像

images = io.ImageCollection('../images/*.png:../images/*.jpg')print('Type:', type(images))images.filesOut[]: Type: <class 『skimage.io.collection.ImageCollection』>

保存圖像

#Saving file as 'logo.png'io.imsave('logo.png', logo)

圖像分割

現在我們已經了解了 scikit-image,接下來讓我們來詳細了解圖像分割。圖像分割本質上是將數字圖像分割成多個片段的過程,以簡化或將圖像的表示方式更改為更有意義和更易於分析的內容。

在本文中,我們結合監督算法和無監督算法來處理分割過程。

scikit-image 庫中可用的一些分割算法

監督分割算法:一些可能來自人類輸入的先驗知識被用來指導算法。

無監督分割算法:不需要先驗知識。這些算法試圖將圖像自動細分到有意義的區域。用戶仍然可以通過調整某些設置以獲得想要的輸出。

讓我們從最簡單的閾值分割算法開始吧。

閾值算法

通過選擇高於或低於某個閾值的像素,將對象從從背景中分割出來是最簡單的方法。在北京分割中,這通常是一個非常有用的方法。了解更多可以查看:http://scikit-image.org/docs/dev/auto_examples/xx_applications/plot_thresholding.html

讓我們在 scikit-image 數據集的一張教科書圖像上試試這個。

基本輸入

import numpy as npimport matplotlib.pyplot as pltimport skimage.data as dataimport skimage.segmentation as segimport skimage.filters as filtersimport skimage.draw as drawimport skimage.color as color

繪製圖像的簡單函數:

defimage_show(image, nrows=1, ncols=1, cmap='gray'): fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=(14, 14))ax.imshow(image, cmap='gray')ax.axis('off')return fig, ax

圖像

text = data.page()image_show(text)

這個圖像有點暗,但我們仍然可以選擇一個值,它可以合理的分割圖像,而不需要用到任何先進的算法。為了得到這個分割閾值,我們將使用直方圖。

直方圖是一種顯示圖像中不同強度值的像素數的圖。簡單地說,直方圖是一個圖表,其中 X 軸顯示圖像中的所有像素值,而 Y 軸顯示這些值的頻率。

fig, ax = plt.subplots(1, 1)ax.hist(text.ravel(), bins=32, range=[0, 256])ax.set_xlim(0, 256);

我們的示例恰好是一張 8-bit 圖像,因此在 X 軸上總共有 256 個可能的值。在圖像中,0 表示黑色,255 表示白色,我們觀察到有些像素值很集中。這很可能是由於我們的文本背景比較淡,而其他部分則有點模糊不清。一個理想的分割直方圖應該是有兩個峰值,且兩個峰值隔的較遠,以便我們可以選擇在這兩個峰值中間選擇一個數字作為閾值。現在,讓我們試著根據簡單的閾值法來分割圖像。

有監督閾值

因為閾值是我們自己選擇的,所以我們稱之為監督閾值。

text_segmented = text > (value concluded from histogram i.e 50,70,120 )image_show(text_segmented);

文本>50

文本>70

文本>120

我們沒有得到理想的結果,因為左邊的陰影會造成問題,接下來讓我們嘗試無監督的閾值。

無監督閾值

scikit-image 有許多自動閾值設定方法,在選擇最佳閾值時不需要手動輸入。其中常用的方法有 otsu, li, local 等等。

text_threshold = filters.threshold_ # Hit tab with the cursor after the underscore to get all the methods.image_show(text < text_threshold);

otsu 算法分割效果圖

li 算法分割效果圖

在 local 算法中,我們還需要指定 block 的大小。offset 有助於調整圖像,以獲得更好的效果。

text_threshold = filters.threshold_local(text,block_size=51, offset=10) image_show(text > text_threshold);

local 閾值法分割效果圖

這是一種很好的方法,它在很大程度上消除了噪聲。

監督分割

閾值分割是一個非常基本的分割方法,但是它在高對比度圖像中效果不是很好,因此我們需要採用更加先進的算法。

在本節中,我們將使用一個免費的示例圖像,並嘗試使用監督分割技術分割圖像中人的頭部。

# import the imagefrom skimage import ioimage = io.imread('girl.jpg') plt.imshow(image);

源圖像

小 tip:在對圖像進行任何分割之前,最好使用一些濾波器對其進行去噪。

但是,在我們的例子中,圖像中的噪聲很小,因此我們直接對其進行處理。接下來我們將要做的是使用 rgb2gray 將圖像轉換成灰度圖。

image_gray = color.rgb2gray(image) image_show(image_gray);

我們將使用兩種原理完全不同的分割方法。

活動輪廓分割(Active Contour segmentation)

活動輪廓分割使用用戶定義的輪廓或線在感興趣的區域周圍進行初始化,然後該輪廓慢慢收縮。

對於我們的示例圖像,讓我們圍繞人的頭部畫一個圈來初始化輪廓。

def circle_points(resolution, center, radius):"""Generate points which define a circle on an image.Centre refers to the centre of the circle""" radians = np.linspace(0, 2*np.pi, resolution)c = center[1] + radius*np.cos(radians)#polar co-ordinatesr = center[0] + radius*np.sin(radians)return np.array([c, r]).T# Exclude last point because a closed path should not have duplicate pointspoints = circle_points(200, [80, 250], 80)[:-1]

上面對圓環邊緣點的 x 坐標和 y 坐標進行了計算。我們設置解析度值的為 200,那麼將計算 200 個這樣的點。

fig, ax = image_show(image)ax.plot(points[:, 0], points[:, 1], '--r', lw=3)

然後,該算法通過將閉合曲線擬合到人臉的邊緣,將人臉與圖像的其餘部分分割開來。

snake = seg.active_contour(image_gray, points)fig, ax = image_show(image)ax.plot(points[:, 0], points[:, 1], '--r', lw=3)ax.plot(snake[:, 0], snake[:, 1], '-b', lw=3);

我們可以調整參數 alpha 和 beta。alpha 值越高,輪廓的收縮速度越快,而 beta 越大收縮越緩慢。

snake = seg.active_contour(image_gray, points,alpha=0.06,beta=0.3)fig, ax = image_show(image)ax.plot(points[:, 0], points[:, 1], '--r', lw=3)ax.plot(snake[:, 0], snake[:, 1], '-b', lw=3);

隨機 walker 分割

在這種方法中,用戶以交互方式標記少量的像素,這些像素稱為標籤。然後假設每個未標記的像素釋放一個隨機 walker,然後可以確定隨機 walker 從每個未標記像素開始到達一個預標記像素的概率。通過將每個像素分配給計算出來的概率值最大的標籤,可以獲得高質量的分割圖像。

更多相關資料可以閱讀參考文獻:https://ieeexplore.ieee.org/document/1704833。

我們將在這裡重新使用前面示例中的種子值。為了簡單起見,讓我們繼續使用圓。

image_labels = np.zeros(image_gray.shape, dtype=np.uint8)

隨機 Walker 算法需要一個標籤圖像作為輸入。所以我們會有一個更大的圓,它包圍了人的整個臉,還有一個靠近臉中間的小圓。

indices = draw.circle_perimeter(80, 250,20)#from hereimage_labels[indices] = 1image_labels[points[:, 1].astype(np.int), points[:, 0].astype(np.int)] = 2image_show(image_labels);

現在,讓我們使用隨機 walker,並觀察發生了什麼。

image_segmented = seg.random_walker(image_gray, image_labels)# Check our resultsfig, ax = image_show(image_gray)ax.imshow(image_segmented == 1, alpha=0.3);

它並沒有如我們所預期的那樣描繪出臉的邊緣。為了解決這個問題,我們可以調整 beta 參數,直到得到所需的結果。經過幾次嘗試後,可以得到,當 beta 值為 3000 時,分割效果不錯。

image_segmented = seg.random_walker(image_gray, image_labels, beta = 3000)# Check our resultsfig, ax = image_show(image_gray)ax.imshow(image_segmented == 1, alpha=0.3);

以上就是監督分割,在這種算法中,我們必須提供某些輸入,也必須調整某些參數。然而,我們不可能總是讓人先看一張圖像,然後再決定輸入什麼或者從哪裡開始。幸運的是,對於這種情況,我們可以採用無監督分割技術。

無監督分割

無監督分割不需要事先了解圖像。在一張圖像太大的情況下,同時考慮所有像素是不可能的。因此,在這種情況下,無監督分割可以將圖像分解為幾個子區域,你可以使用數十到數百個區域來代替數百萬像素。下面是兩個無監督分割算法:

SLIC(簡單線性迭代聚類)

SLIC 算法實際上使用了一種叫做 k-means 的機器學習算法。它接收圖像的所有像素值,並嘗試將它們分離到給定數量的子區域中。

更多相關內容可以閱讀相關資料:https://ieeexplore.ieee.org/document/6205760。

SLIC 是處理彩色圖像的,所以我們將使用原始圖像。

image_slic = seg.slic(image,n_segments=155)

我們所做的只是將圖像的每個子圖像或子區域像素設置為該區域像素的平均值。

# label2rgb replaces each discrete label with the average interior colorimage_show(color.label2rgb(image_slic, image, kind='avg'));

我們已經將此圖像從 512*512=262000 個像素減少到 155 個區域。

Felzenszwalb 算法

該算法也使用了一種機器學習算法,即最小生成樹聚類算法。Felzenszwaib 算法並沒有告訴我們圖像將被分割成多少個集群。它將運行並生成儘可能多的適合它的集群。相關的參考文件可以在這裡查閱。

image_felzenszwalb = seg.felzenszwalb(image) image_show(image_felzenszwalb);

有很多區域,我們計算相互獨立的區域數。

np.unique(image_felzenszwalb).size3368

現在讓我們使用區域像素平均值對它們重新著色,就像我們在 SLIC 算法中所做的那樣。

image_felzenszwalb_colored = color.label2rgb(image_felzenszwalb, image, kind='avg')image_show(image_felzenszwalb_colored);

現在我們將圖像分成了合適的小區域。如果我們想要將圖像分成更少的區域,可以更改比例參數或者繼續組合它們。這種方法有時被稱為過度分割。

這看起來更像是一個拆分後的圖像,其本質上只是減少了顏色的數量。要再次組合它們,可以使用區域鄰接圖(RAG),但這超出了本文的範圍。

結論

圖像分割是圖像處理中非常重要的一個步驟。它是一個熱門的研究領域,應用非常廣泛,從計算機視覺到醫學圖像、從交通和視頻監控等領域都有涉及。Python scikit-image 提供了一個非常強大的庫,該庫具有大量用於圖像處理的算法。它是免費的,沒有任何限制,在其背後有一個活躍的社區。你可以查看他們的文檔,了解關於庫及其用例的更多信息。

via:https://towardsdatascience.com/image-segmentation-using-pythons-scikit-image-module-533a61ecc980

雷鋒網 AI 科技評論編譯。

相關焦點

  • Python十大工具,讓圖像簡潔直觀有魅力!
    因此,圖像處理就是對數字圖像進行分析、操作的過程,其主要目的是為改善圖像質量或從中提取一些有用信息。圖像處理的常見任務包括圖像顯示、圖像基本操作(裁剪、翻轉、旋轉等)、圖像分割、分類及特徵提取、圖像修復和圖像識別。而Python作為一種科學程式語言已在日漸普及,在生態系統庫中還免費提供了許多最為先進的圖像處理工具,因此成為了圖像處理的最佳選擇。
  • Python中的十大圖像處理工具
    圖像處理是分析和操縱數字圖像的過程,旨在提高其質量或從中提取一些信息,然後將其用於某些方面。圖像處理中的常見任務包括顯示圖像,基本操作(如裁剪、翻轉、旋轉等),圖像分割,分類和特徵提取,圖像恢復和圖像識別等。 Python之成為圖像處理任務的最佳選擇,是因為這一科學程式語言日益普及,並且其自身免費提供許多最先進的圖像處理工具。
  • 10個Python圖像處理工具,非常全了!
    介紹我們這個世界充滿了數據,而圖像是這些數據的重要組成部分。然而,要想使用這些圖像,需要對它們進行處理。因此,圖像處理是分析和處理數字圖像的必要的過程,其主要目的是提高圖像質量或從中提取一些信息,然後加以利用。圖像處理中常見的任務包括圖像顯示、裁剪、翻轉、旋轉等基本操作、圖像分割、分類和特徵提取、圖像恢復和圖像識別。
  • 10個不得不知的Python圖像處理工具,非常全了!
    介紹我們這個世界充滿了數據,而圖像是這些數據的重要組成部分。然而,要想使用這些圖像,需要對它們進行處理。因此,圖像處理是分析和處理數字圖像的必要的過程,其主要目的是提高圖像質量或從中提取一些信息,然後加以利用。圖像處理中常見的任務包括圖像顯示、裁剪、翻轉、旋轉等基本操作、圖像分割、分類和特徵提取、圖像恢復和圖像識別。
  • 常用的十大 python 圖像處理工具
    但無論是用於何種用途,這些圖像都需要進行處理。圖像處理就是分析和處理數字圖像的過程,主要旨在提高其質量或從中提取一些信息,然後可以將其用於某種用途。圖像處理中的常見任務包括顯示圖像,基本操作如裁剪、翻轉、旋轉等,圖像分割,分類和特徵提取,圖像恢復和圖像識別。
  • 一文總結數據科學家常用的Python庫(下)
    一文總結數據科學家常用的Python庫(上)用於建模的Python庫我們已經到達了本文最受期待的部分 - 構建模型!這就是我們大多數人首先進入數據科學領域的原因,不是嗎?讓我們通過這三個Python庫探索模型構建。
  • 十個Python圖像處理工具
    今天的世界充滿了數據,圖像是這些數據的重要組成部分。但是,在使用它們之前,必須對這些數字圖像進行處理 - 分析和操作,以提高其質量或提取一些可以使用的信息。常見的圖像處理任務包括顯示; 基本操作如裁剪,翻轉,旋轉等;;圖像分割,分類和特徵提取;圖像恢復;圖像識別。
  • ImagePy——UI界面支持開放插件的Python開源圖像處理框架
    雷鋒網 AI 科技評論按,ImagePy 是一款 python 開源圖像處理框架,其 UI 界面支持開放插件。在 github:https://github.com/Image-Py/imagepy 上,不僅有關於這款圖像處理軟體的詳細介紹,還有一些使用示例,雷鋒網 AI 科技評論接下來將詳細介紹這一開源圖像處理框架。
  • 使用Python圖像處理庫Pillow處理圖像文件
    #模塊:c:\pythonpa\cs\image_test.py#命令行:python image_test.py c:\pythonpa\cs\img\mandrill.jpg#功能:把c:\pythonpa\cs\img\mandrill.jpg的4個副本排列成2×2網格並顯示import sysimport osimport
  • 使用PixelLib來實現圖像分割
    目前流行的計算機視覺技術如圖像分類、目標檢測等已被廣泛應用於解決許多計算機視覺問題。在圖像分類中,對整個圖像進行分類。在目標檢測中,則是通過檢測圖像中單個目標的位置來擴展圖像分類。圖像分割一些計算機視覺問題需要讓計算機對圖像內容有更深入的理解。分類和目標檢測可能不適合解決這些問題,我們非常需要一種有效的技術來解這類的計算機視覺問題,圖像分割技術應運而生。每個圖像都由一組像素值組成。
  • python數據分析專題 (7):python數據分析模塊
    也就是這些python的擴展包讓python可以做數據分析,主要包括numpy,scipy,pandas,matplotlib,scikit-learn等等諸多強大的模塊,在結合上ipython交互工具 ,以及python強大的爬蟲數據獲取能力,字符串處理能力,讓python成為完整的數據分析工具。
  • Python+OpenCV的基礎圖像處理操作匯總
    圖像處理是對圖像進行的技術操作與分析,比如為了得到增強的圖像或提取一些有用的信息而進行的一系列操作。隨著我們的發展,許多應用程式使用圖像/幀/視頻作為輸入,對它們進行預處理,並將其輸入到設備或軟體或腳本中。圖像處理也可以是娛樂性的,可以用於許多應用。
  • 圖像分割的U-Net系列方法
    來源丨https://zhuanlan.zhihu.com/p/57530767僅作學術交流,如有侵權,請聯繫刪文在圖像分割任務特別是醫學圖像分割中
  • 一文總結圖像語義分割模型
    連結:https://zhuanlan.zhihu.com/p/133268053語義分割是圖像分割中的基本任務,是指對於圖像將每個像素都標註上對應的類別
  • 基於OpenCV的圖像分割處理!
    圖像閾值化分割是一種傳統的最常用的圖像分割方法,因其實現簡單、計算量小、性能較穩定而成為圖像分割中最基本和應用最廣泛的分割技術。通常情況下對於色彩均衡的圖像,直接將閾值設為127即可,但有時圖像灰度級的分布是不均衡的,如果此時還將閾值設為127,那麼閾值處理的結果就是失敗的。所以需要找出圖像的最佳的分割閾值。OTSU就是獲得最佳閾值的方法。OTSU(大津法)是一種確定圖像二值化分割閾值的算法,由日本學者大津於1979年提出。
  • 用Python (scikit-learn) 做PCA分析
    原始圖像(左)保留不同數量的方差我的上一個教程討論了使用Python的邏輯回歸(https://towardsdatascience.com/logistic-regression-using-python-sklearn-numpy-mnist-handwriting-recognition-matplotlib-a6b31e2b166a)。
  • 自動化測試實踐之Python識別驗證碼
    一、探討識別圖形驗證碼可以說是做爬蟲的必修課,涉及到計算機圖形學,機器學習,機器視覺,人工智慧等等高深領域……簡單地說,計算機圖形學的主要研究內容就是研究如何在計算機中表示圖形、以及利用計算機進行圖形的計算、處理和顯示的相關原理與算法。
  • 盤點python數據工程師需要掌握的18個庫
    對數組執行數學運算和邏輯運算時,NumPy 是非常有用的。在用 Python 對 n 維數組和矩陣進行運算時,NumPy 提供了大量有用特徵。數據清洗Pandaspandas 是基於NumPy 的一種工具,該工具是為了解決數據分析任務而創建的。Pandas 納入了大量庫和一些標準的數據模型,提供了高效地操作大型數據集所需的工具。
  • 全卷積網絡FCN進行圖像分割
    傳統的基於CNN的分割方法:為了對一個像素分類,使用該像素周圍的一個圖像塊作為CNN的輸入用於訓練和預測。這種方法有幾個缺點:一是存儲開銷很大。例如對每個像素使用的圖像塊的大小為15x15,然後不斷滑動窗口,每次滑動的窗口給CNN進行判別分類,因此則所需的存儲空間根據滑動窗口的次數和大小急劇上升。二是計算效率低下。
  • 對圖片字符進行定位及分割(python+cv2)
    '''Created on 2019年3月15日@author: Qiuyi'''from matplotlib import pyplot as pltimport numpy as npimport cv2rawimg = cv2.imread(r"D:\LearningFiles\splitCharactersOfPicture(python