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

2020-11-22 雷鋒網

雷鋒網(公眾號:雷鋒網) 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 distributions

conda install scikit-image

python 中的圖像處理概述

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

從 skimage 庫導入灰度圖像

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

from skimage import data

import numpy as np

import matplotlib.pyplot as plt


image = data.binary_blobs()

plt.imshow(image, cmap='gray')

從 skimage 庫導入彩色圖像

from skimage import data

import numpy as np

import matplotlib.pyplot as plt


image = data.astronaut()


plt.imshow(image)

從外部源導入圖像

# The I/O module is used for importing the image

from skimage import data

import numpy as np

import matplotlib.pyplot as plt

from skimage import io


image = io.imread('skimage_logo.png')


plt.imshow(image);

加載多個圖像

images = io.ImageCollection('../images/*.png:../images/*.jpg')


print('Type:', type(images))

images.files

Out[]: 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 np

import matplotlib.pyplot as plt


import skimage.data as data

import skimage.segmentation as seg

import skimage.filters as filters

import skimage.draw as draw

import skimage.color as color

繪製圖像的簡單函數:

def image_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 image

from skimage import io

image = 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-ordinates

r = center[0] + radius*np.sin(radians)


return np.array([c, r]).T


# Exclude last point because a closed path should not have duplicate points

points = 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 here


image_labels[indices] = 1

image_labels[points[:, 1].astype(np.int), points[:, 0].astype(np.int)] = 2


image_show(image_labels);

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

image_segmented = seg.random_walker(image_gray, image_labels)


# Check our results

fig, 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 results

fig, 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 color

image_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).size

3368

現在讓我們使用區域像素平均值對它們重新著色,就像我們在 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編寫的音頻信號處理庫,主要關注音樂信息檢索(MIR)任務。它涵蓋了廣泛的音頻分析任務,例如:對未知聲音進行分類檢測音頻事件並排除長時間錄音中的靜音時段執行有監督和無監督的分割提取音頻縮略圖等等您可以使用以下代碼安裝它:pip install pyAudioAnalysis用於圖像處理的Python庫如果您正在尋找數據科學行業的角色,您必須學習如何使用圖像數據。
  • ImagePy——UI界面支持開放插件的Python開源圖像處理框架
    ImagePy 是一款基於 imagej 等插件的圖像處理框架,它可以與 scipy.ndimage、scikit-image、opencv、simpleitk、mayavi 以及任何基於 numpy 的庫進行組合使用,其地址為 http://imagepy.org。
  • 數據工程師需要掌握的 18 個 Python 庫
    作者 | 劉早起早起責編 | 屠敏本文對Python中在數據分析中需要掌握的庫進行了整理,一起來看看吧!利用函數的調用,MATLAB中可以輕鬆的利用一行命令來繪製,然後再用一系列的函數調整結果。它有一套完全仿照MATLAB的函數形式的繪圖接口,在matplotlib.pyplot模塊中。這套函數接口方便MATLAB用戶過度到matplotlib。
  • 使用Python調整圖像大小
    Returns: Image: 一幅漂亮的正方形圖片!一個很好的起點是查看scikit image。OpenCVOpenCV可以用來作圖像處理。你可以通過-s "chicken nuggets"進行設置。如果不希望在程序運行時將文本輸出到標準流,則quiet是一個選項參數。從命令行運行程序:python resize.py -s 35 -p ".
  • python|圖像識別
    影響力之大和最吸引人的技術就是圖像識別,圖像識別技術是人工智慧的一個重要領域,它是指利用計算機對圖像進行處理、分析和理解,以識別各種不同模式的目標和對象的技術。今天以女神宋慧喬的兩張不同照片為例,利用python識別其相似度,從而判定是否是同一人,同時讓我們對圖像識別有個初步的了解,什麼?照片可以換蒼老師和波老師嗎?我懷疑你們在開車,可是我沒有證據!
  • Python驗證碼識別:利用pytesser識別簡單圖形驗證碼
    3、二值化處理二值化是圖像分割的一種常用方法。生成一張查找表,再調用point()進行映射。可以不用切割,有關圖片切割的方法參見這篇博客:http://www.cnblogs.com/apexchu/p/4231041.html四、利用pytesser模塊實現識別pytesser是谷歌OCR開源項目的一個模塊,在python中導入這個模塊即可將圖片中的文字轉換成文本。
  • 基於python+OpenCV模塊的人臉識別定位技術
    什麼是OpenCV模塊OpenCV是一款跨平臺的視覺庫,可以支持的作業系統有Linux、Windows和Mac OS作業系統,並且還提供了多種語言的接口,比如Python,java,MATLAB等常用語言。
  • 掌握了這24個頂級Python庫,你就是大神!
    命名它——那麼scikit-learn會有一個模塊。建議瀏覽以下連結以了解有關scikit-learn的更多信息:《Python中的Scikit-learn——筆者去年學到的最重要的機器學習工具!》TensorFlowTensorFlow由谷歌開發,是一個流行的深度學習庫,可幫助構建、培訓不同模型。是一個開放源碼的端到端平臺。
  • 驗證碼識別實例,python簡單圖像處理和實現
    基本識別原理概述:1、每一幅圖像在構成上,都是由一個個像素組成的矩陣,每一個像素為單元格。2、 彩色圖像的像素的由三原色(紅,綠,藍)構成元組,灰度圖像的像素是一個單值,每個像素的值範圍為(0,255)。
  • 如何用PyTorch進行語義分割?一個教程教會你
    正值PyTorch 1.7更新,那麼我們這次便給大家帶來一個PyTorch簡單實用的教程資源:用PyTorch進行語義分割。△圖源:stanford該教程是基於2020年ECCV Vipriors Chalange Start Code實現了語義分割,並且添加了一些技巧。
  • 百度飛槳發布工業級圖像分割利器PaddleSeg
    PaddleSeg 重磅發布飛槳的新產品 PaddleSeg 全新上線,重點針對圖像分割領域,面向開發者提供了完備且易用的工業級分割模型庫。是的,你沒有看錯,真正經得起考驗的【真. 工業級】的分割模型庫。
  • opencv-python獲取圖像:面向對象與面向過程
    關於圖片的來源:1973年6月,美國南加州大學的信號圖像處理研究所的一個助理教授和他的一個研究生打算為了一個學術會議找一張數字照片,而他們對於手頭現有成堆"無聊"照片感到厭煩。事實上他們需要的是一個人臉照片,同時又能讓人眼前一亮。這時正好有人走進實驗室,手上帶著一本當時的花花公子雜誌,結果故事發生了……而限於當時實驗室設備和測試圖片的需要,lenna的圖片只摳到了原圖的肩膀部分。
  • 教程:使用Python進行基本圖像數據分析!
    導入圖像並觀察其屬性拆分圖層Greyscale對像素值使用邏輯運算符使用邏輯運算符進行運算衛星圖像數據分析  導入圖像  現在讓我們加載圖像並觀察各種屬性:  if __name__ == '__main__':  import imageio  import matplotlib.pyplot as plt  %matplotlib inline  pic = imageio.imread('F:
  • Python模塊NumPy,Pandas,matplotlib的中文文檔
    今天比較忙所以不能寫長文了作為一名數據工程師需要熟練掌握python中的這些numpy,matplotlib,pandas,sklearn,seaborn,statsmodel.模塊但是由於這些模塊的文檔都是英文的可能一些英文不好的同學學起來會比較的困難,所以我從網上給大家找到一些中文的文檔
  • 以鳶尾花數據集為例,用Python對決策樹進行分類
    分類樹本質上,分類樹就是設計一系列問題來進行分類。下圖是在鳶尾花數據集(花種)上訓練的分類樹。根(棕色)和決策(藍色)節點包含分成子節點的問題。根節點是最頂層的決策節點。換句話說,它是開始進行分類的節點。葉節點(綠色),也稱為終端節點,是沒有子節點的節點。葉節點是通過多數投票分配類的地方。
  • 開源機器學習框架:Scikit-learn API簡介
    datasets.load_sample_image(IMAGE_NAME)    加載單個樣本圖像的numpy數組datasets.load_sample_images()    加載用於圖像處理的樣本圖像。datasets.load_svmlight_file(f [,n_features,...])
  • 用Python進行Web爬取數據
    它為你提供了從網站中高效提取數據,根據需要進行處理並以你喜歡的結構和格式存儲數據所需的所有工具。你可以在這裡閱讀更多有關Scrapy的信息。 https://www.analyticsvidhya.com/blog/2017/07/web-scraping-in-python-using-scrapySeleniumSelenium是另一個使瀏覽器自動化的流行工具。
  • 入門| 一文了解什麼是語義分割及常用的語義分割方法有哪些
    這種了解在諸如自動駕駛、機器人以及圖像搜尋引擎等許多領域都是非常重要的。因此,本文討論的主題是使用深度學習方法進行有監督的語義分割。卷積層可以有效地捕捉圖像中的局部特徵,並以層級的方式將許多這樣的模塊嵌套在一起,這樣 CNN 就可以試著提取更大的結構了。通過一系列卷積捕捉圖像的複雜特徵,CNN 可以將一張圖的內容編碼為緊湊表徵。但為了將單獨的像素映射給標籤,我們需要將標準 CNN 編碼器擴展為編碼器-解碼器架構。