Python基于紋理背景和聚類(lèi)算法實(shí)現(xiàn)圖像分割詳解
一.基于紋理背景的圖像分割
該部分主要講解基于圖像紋理信息(顏色)、邊界信息(反差)和背景信息的圖像分割算法。在OpenCV中,GrabCut算法能夠有效地利用紋理信息和邊界信息分割背景,提取圖像目標(biāo)物體。該算法是微軟研究院基于圖像分割和摳圖的課題,它能有效地將目標(biāo)圖像分割提取,如圖1所示[1]。
GrabCut算法原型如下所示:
mask, bgdModel, fgdModel = grabCut(img, mask, rect, bgdModel, fgdModel, iterCount[, mode])
– image表示輸入圖像,為8位三通道圖像
– mask表示蒙板圖像,輸入/輸出的8位單通道掩碼,確定前景區(qū)域、背景區(qū)域、不確定區(qū)域。當(dāng)模式設(shè)置為GC_INIT_WITH_RECT時(shí),該掩碼由函數(shù)初始化
– rect表示前景對(duì)象的矩形坐標(biāo),其基本格式為(x, y, w, h),分別為左上角坐標(biāo)和寬度、高度
– bdgModel表示后臺(tái)模型使用的數(shù)組,通常設(shè)置為大小為(1, 65)np.float64的數(shù)組
– fgdModel表示前臺(tái)模型使用的數(shù)組,通常設(shè)置為大小為(1, 65)np.float64的數(shù)組
– iterCount表示算法運(yùn)行的迭代次數(shù)
– mode是cv::GrabCutModes操作模式之一,cv2.GC_INIT_WITH_RECT 或 cv2.GC_INIT_WITH_MASK表示使用矩陣模式或蒙板模式
下面是Python的實(shí)現(xiàn)代碼,通過(guò)調(diào)用np.zeros()函數(shù)創(chuàng)建掩碼、fgbModel和bgModel,接著定義rect矩形范圍,調(diào)用函數(shù)grabCut()實(shí)現(xiàn)圖像分割。由于該方法會(huì)修改掩碼,像素會(huì)被標(biāo)記為不同的標(biāo)志來(lái)指明它們是背景或前景。接著將所有的0像素和2像素點(diǎn)賦值為0(背景),而所有的1像素和3像素點(diǎn)賦值為1(前景),完整代碼如下所示。
# -*- coding: utf-8 -*- # By: Eastmount import cv2 import numpy as np import matplotlib.pyplot as plt import matplotlib #讀取圖像 img = cv2.imread('nv.png') #灰度化處理圖像 grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #設(shè)置掩碼、fgbModel、bgModel mask = np.zeros(img.shape[:2], np.uint8) bgdModel = np.zeros((1,65), np.float64) fgdModel = np.zeros((1,65), np.float64) #矩形坐標(biāo) rect = (100, 100, 500, 800) #圖像分割 cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) #設(shè)置新掩碼:0和2做背景 mask2 = np.where((mask==2)|(mask==0), 0, 1).astype('uint8') #設(shè)置字體 matplotlib.rcParams['font.sans-serif']=['SimHei'] #顯示原圖 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.subplot(1,2,1) plt.imshow(img) plt.title('(a)原始圖像') plt.xticks([]), plt.yticks([]) #使用蒙板來(lái)獲取前景區(qū)域 img = img*mask2[:, :, np.newaxis] plt.subplot(1,2,2) plt.imshow(img) plt.title('(b)目標(biāo)圖像') plt.colorbar() plt.xticks([]), plt.yticks([]) plt.show()
輸出圖像如圖2所示,圖2(a)為原始圖像,圖2(b)為圖像分割后提取的目標(biāo)人物,但人物右部分的背景仍然存在。如何移除這些背景呢?這里需要使用自定義的掩碼進(jìn)行提取,讀取一張灰色背景輪廓圖,從而分離背景與前景,希望讀者下來(lái)實(shí)現(xiàn)該功能。
二.基于K-Means聚類(lèi)算法的區(qū)域分割
K-Means聚類(lèi)是最常用的聚類(lèi)算法,最初起源于信號(hào)處理,其目標(biāo)是將數(shù)據(jù)點(diǎn)劃分為K個(gè)類(lèi)簇,找到每個(gè)簇的中心并使其度量最小化。該算法的最大優(yōu)點(diǎn)是簡(jiǎn)單、便于理解,運(yùn)算速度較快,缺點(diǎn)是只能應(yīng)用于連續(xù)型數(shù)據(jù),并且要在聚類(lèi)前指定聚集的類(lèi)簇?cái)?shù)[2]。
下面是K-Means聚類(lèi)算法的分析流程,步驟如下:
- 第一步,確定K值,即將數(shù)據(jù)集聚集成K個(gè)類(lèi)簇或小組;
- 第二步,從數(shù)據(jù)集中隨機(jī)選擇K個(gè)數(shù)據(jù)點(diǎn)作為質(zhì)心(Centroid)或數(shù)據(jù)中心;
- 第三步,分別計(jì)算每個(gè)點(diǎn)到每個(gè)質(zhì)心之間的距離,并將每個(gè)點(diǎn)劃分到離最近質(zhì)心的小組,跟定了那個(gè)質(zhì)心;
- 第四步,當(dāng)每個(gè)質(zhì)心都聚集了一些點(diǎn)后,重新定義算法選出新的質(zhì)心;
- 第五步,比較新的質(zhì)心和老的質(zhì)心,如果新質(zhì)心和老質(zhì)心之間的距離小于某一個(gè)閾值,則表示重新計(jì)算的質(zhì)心位置變化不大,收斂穩(wěn)定,則認(rèn)為聚類(lèi)已經(jīng)達(dá)到了期望的結(jié)果,算法終止;
- 第六步,如果新的質(zhì)心和老的質(zhì)心變化很大,即距離大于閾值,則繼續(xù)迭代執(zhí)行第三步到第五步,直到算法終止。
圖29-3是對(duì)身高和體重進(jìn)行聚類(lèi)的算法,將數(shù)據(jù)集的人群聚集成三類(lèi)。
在圖像處理中,通過(guò)K-Means聚類(lèi)算法可以實(shí)現(xiàn)圖像分割、圖像聚類(lèi)、圖像識(shí)別等操作,本小節(jié)主要用來(lái)進(jìn)行圖像顏色分割。假設(shè)存在一張100×100像素的灰度圖像,它由10000個(gè)RGB灰度級(jí)組成,我們通過(guò)K-Means可以將這些像素點(diǎn)聚類(lèi)成K個(gè)簇,然后使用每個(gè)簇內(nèi)的質(zhì)心點(diǎn)來(lái)替換簇內(nèi)所有的像素點(diǎn),這樣就能實(shí)現(xiàn)在不改變分辨率的情況下量化壓縮圖像顏色,實(shí)現(xiàn)圖像顏色層級(jí)分割。
在OpenCV中,Kmeans()函數(shù)原型如下所示:
retval, bestLabels, centers = kmeans(data, K, bestLabels, criteria, attempts, flags[, centers])
– data表示聚類(lèi)數(shù)據(jù),最好是np.flloat32類(lèi)型的N維點(diǎn)集
– K表示聚類(lèi)類(lèi)簇?cái)?shù)
– bestLabels表示輸出的整數(shù)數(shù)組,用于存儲(chǔ)每個(gè)樣本的聚類(lèi)標(biāo)簽索引
– criteria表示算法終止條件,即最大迭代次數(shù)或所需精度。在某些迭代中,一旦每個(gè)簇中心的移動(dòng)小于criteria.epsilon,算法就會(huì)停止
– attempts表示重復(fù)試驗(yàn)kmeans算法的次數(shù),算法返回產(chǎn)生最佳緊湊性的標(biāo)簽
– flags表示初始中心的選擇,兩種方法是cv2.KMEANS_PP_CENTERS ;和cv2.KMEANS_RANDOM_CENTERS
– centers表示集群中心的輸出矩陣,每個(gè)集群中心為一行數(shù)據(jù)
下面使用該方法對(duì)灰度圖像顏色進(jìn)行分割處理,需要注意,在進(jìn)行K-Means聚類(lèi)操作之前,需要將RGB像素點(diǎn)轉(zhuǎn)換為一維的數(shù)組,再將各形式的顏色聚集在一起,形成最終的顏色分割。
# -*- coding: utf-8 -*- # By: Eastmount import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像灰度顏色 img = cv2.imread('scenery.png', 0) #獲取圖像高度、寬度 rows, cols = img.shape[:] #圖像二維像素轉(zhuǎn)換為一維 data = img.reshape((rows * cols, 1)) data = np.float32(data) #定義中心 (type,max_iter,epsilon) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) #設(shè)置標(biāo)簽 flags = cv2.KMEANS_RANDOM_CENTERS #K-Means聚類(lèi) 聚集成4類(lèi) compactness, labels, centers = cv2.kmeans(data, 4, None, criteria, 10, flags) #生成最終圖像 dst = labels.reshape((img.shape[0], img.shape[1])) #用來(lái)正常顯示中文標(biāo)簽 plt.rcParams['font.sans-serif']=['SimHei'] #顯示圖像 titles = ['原始圖像', '聚類(lèi)圖像'] images = [img, dst] for i in range(2): plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結(jié)果如圖4所示,左邊為灰度圖像,右邊為K-Means聚類(lèi)后的圖像,它將灰度級(jí)聚集成四個(gè)層級(jí),相似的顏色或區(qū)域聚集在一起。
下面代碼是對(duì)彩色的圖像進(jìn)行顏色分割處理,它將彩色的圖像聚集成2類(lèi)、4類(lèi)和64類(lèi)。
# -*- coding: utf-8 -*- # By: Eastmount import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('scenery.png') #圖像二維像素轉(zhuǎn)換為一維 data = img.reshape((-1,3)) data = np.float32(data) #定義中心 (type,max_iter,epsilon) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) #設(shè)置標(biāo)簽 flags = cv2.KMEANS_RANDOM_CENTERS #K-Means聚類(lèi) 聚集成2類(lèi) compactness, labels2, centers2 = cv2.kmeans(data, 2, None, criteria, 10, flags) #K-Means聚類(lèi) 聚集成4類(lèi) compactness, labels4, centers4 = cv2.kmeans(data, 4, None, criteria, 10, flags) #K-Means聚類(lèi) 聚集成8類(lèi) compactness, labels8, centers8 = cv2.kmeans(data, 8, None, criteria, 10, flags) #K-Means聚類(lèi) 聚集成16類(lèi) compactness, labels16, centers16 = cv2.kmeans(data, 16, None, criteria, 10, flags) #K-Means聚類(lèi) 聚集成64類(lèi) compactness, labels64, centers64 = cv2.kmeans(data, 64, None, criteria, 10, flags) #圖像轉(zhuǎn)換回uint8二維類(lèi)型 centers2 = np.uint8(centers2) res = centers2[labels2.flatten()] dst2 = res.reshape((img.shape)) centers4 = np.uint8(centers4) res = centers4[labels4.flatten()] dst4 = res.reshape((img.shape)) centers8 = np.uint8(centers8) res = centers8[labels8.flatten()] dst8 = res.reshape((img.shape)) centers16 = np.uint8(centers16) res = centers16[labels16.flatten()] dst16 = res.reshape((img.shape)) centers64 = np.uint8(centers64) res = centers64[labels64.flatten()] dst64 = res.reshape((img.shape)) #圖像轉(zhuǎn)換為RGB顯示 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) dst2 = cv2.cvtColor(dst2, cv2.COLOR_BGR2RGB) dst4 = cv2.cvtColor(dst4, cv2.COLOR_BGR2RGB) dst8 = cv2.cvtColor(dst8, cv2.COLOR_BGR2RGB) dst16 = cv2.cvtColor(dst16, cv2.COLOR_BGR2RGB) dst64 = cv2.cvtColor(dst64, cv2.COLOR_BGR2RGB) #用來(lái)正常顯示中文標(biāo)簽 plt.rcParams['font.sans-serif']=['SimHei'] #顯示圖像 titles = ['原始圖像', '聚類(lèi)圖像 K=2', '聚類(lèi)圖像 K=4', '聚類(lèi)圖像 K=8', '聚類(lèi)圖像 K=16', '聚類(lèi)圖像 K=64'] images = [img, dst2, dst4, dst8, dst16, dst64] for i in range(6): plt.subplot(2,3,i+1), plt.imshow(images[i], 'gray'), plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結(jié)果如圖5所示,它對(duì)比了原始圖像和各K-Means聚類(lèi)處理后的圖像。當(dāng)K=2時(shí),聚集成2種顏色;當(dāng)K=4時(shí),聚集成4種顏色;當(dāng)K=8時(shí),聚集成8種顏色;當(dāng)K=16時(shí),聚集成16種顏色;當(dāng)K=64時(shí),聚集成64種顏色。
同樣,如果是人物圖像顯示如圖6所示,比如小珞珞。
三.總結(jié)
本文主要講解了常用的圖像分割方法,包括基于紋理背景和聚類(lèi)算法的圖像分割方法。希望讀者能結(jié)合本文知識(shí)點(diǎn),圍繞自己的研究領(lǐng)域或工程項(xiàng)目進(jìn)行深入的學(xué)習(xí),實(shí)現(xiàn)所需的圖像處理。
到此這篇關(guān)于Python基于紋理背景和聚類(lèi)算法實(shí)現(xiàn)圖像分割詳解的文章就介紹到這了,更多相關(guān)Python圖像分割內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python使用樹(shù)狀圖實(shí)現(xiàn)可視化聚類(lèi)詳解
- python 層次聚類(lèi)算法圖文示例
- Python K-means實(shí)現(xiàn)簡(jiǎn)單圖像聚類(lèi)的示例代碼
- Python使用OpenCV和K-Means聚類(lèi)對(duì)畢業(yè)照進(jìn)行圖像分割
- Python實(shí)現(xiàn)K-means聚類(lèi)算法并可視化生成動(dòng)圖步驟詳解
- 在Python中使用K-Means聚類(lèi)和PCA主成分分析進(jìn)行圖像壓縮
- python基于K-means聚類(lèi)算法的圖像分割
- python聚類(lèi)算法解決方案(rest接口/mpp數(shù)據(jù)庫(kù)/json數(shù)據(jù)/下載圖片及數(shù)據(jù))
- 使用python實(shí)現(xiàn)3D聚類(lèi)圖示例代碼
相關(guān)文章
基于Python編寫(xiě)簡(jiǎn)易的成語(yǔ)接龍游戲
成語(yǔ)接龍是中華民族傳統(tǒng)的文字游戲。它歷史悠久,是傳統(tǒng)文字、文化、文明的一個(gè)縮影,也是老少皆宜的民間文化娛樂(lè)活動(dòng)。本文將用Python制作一個(gè)簡(jiǎn)單的成語(yǔ)接龍游戲,需要的可以參考一下2022-03-03python的pygal模塊繪制反正切函數(shù)圖像方法
在本篇文章中我們給大家整理了關(guān)于如何用python的pygal模塊繪制反正切函數(shù)圖像的知識(shí)點(diǎn)內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。2019-07-07Python深度學(xué)習(xí)pytorch神經(jīng)網(wǎng)絡(luò)匯聚層理解
通常當(dāng)我們處理圖像時(shí),我們希望逐漸降低隱藏表示的空間分辨率,聚集信息,這樣隨著我們?cè)谏窠?jīng)網(wǎng)絡(luò)層疊的上升,每個(gè)神經(jīng)元對(duì)其敏感的感受野(輸入)就越大2021-10-10python使用multiprocessing的詳細(xì)方法
multiprocessing是Python標(biāo)準(zhǔn)庫(kù)中的一個(gè)模塊,用于實(shí)現(xiàn)多進(jìn)程編程,它提供了一種簡(jiǎn)單而高效的方式來(lái)利用多核處理器的能力,通過(guò)在多個(gè)進(jìn)程中同時(shí)執(zhí)行任務(wù),加快程序的執(zhí)行速度和提高系統(tǒng)的吞吐量,這篇文章主要介紹了python使用multiprocessing,需要的朋友可以參考下2024-03-03python使用PIL把透明背景圖片轉(zhuǎn)成白色背景的示例代碼
當(dāng)我們?cè)诓杉恍﹫D片的時(shí)候,這些圖片的背景經(jīng)常是透明的,但是如何把透明背景轉(zhuǎn)成白色背景呢,接下來(lái)就給大家解決這個(gè)問(wèn)題,本文主要介紹了python使用PIL把透明背景圖片轉(zhuǎn)成白色背景,需要的朋友可以參考下2023-08-08python dataframe列應(yīng)用正則表達(dá)式篩選方式
這篇文章主要介紹了python dataframe列應(yīng)用正則表達(dá)式篩選方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02python編程PyQt5創(chuàng)建按鈕及觸發(fā)點(diǎn)擊事件示例解析
這篇文章主要為大家介紹了python編程使用PyQt5如何創(chuàng)建按鈕及觸發(fā)點(diǎn)擊事件的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-10-10Python辦公自動(dòng)化解決world文件批量轉(zhuǎn)換
本文分享如何用 Python 來(lái)讀取 Word、寫(xiě)入 Word、將 Word 轉(zhuǎn)換為 pdf。學(xué)會(huì)之后,如果遇到大量 Word 文件需要處理的時(shí)候,就不慌了2021-09-09