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