一:圖像分割概述
圖像分割:在對(duì)圖像的研究和應(yīng)用中,人們往往僅對(duì)圖像中的某些目標(biāo)感興趣,這些目標(biāo)通常對(duì)應(yīng)圖像中具有特定性質(zhì)的區(qū)域。圖像分割是指把一幅圖像分成不同的具有特定性質(zhì)區(qū)域的圖像處理技術(shù),將這些區(qū)域分離提取出來(lái),以便進(jìn)一步提取特征和理解
圖像分割方法多種多樣,常用的技術(shù)包括:
- 基于閾值:根據(jù)像素的灰度值或者顏色信息,將圖像分成不同的區(qū)域。這種方法簡(jiǎn)單直觀,適用于一些簡(jiǎn)單的場(chǎng)景,但對(duì)于復(fù)雜圖像可能效果不佳
- 基于邊緣檢測(cè):通過(guò)檢測(cè)圖像中的邊緣信息,將圖像分割成不同的區(qū)域。常用的邊緣檢測(cè)算法包括Canny邊緣檢測(cè)和Sobel算子等
- 基于區(qū)域生長(zhǎng):從種子像素開(kāi)始,根據(jù)一定的相似性準(zhǔn)則,逐漸將相鄰像素合并為一個(gè)區(qū)域,直到滿足停止準(zhǔn)則。這種方法對(duì)于具有明顯區(qū)域邊界的圖像效果較好
- 基于圖割:將圖像分割問(wèn)題轉(zhuǎn)化為圖論中的圖割問(wèn)題,通過(guò)最小化圖中的能量函數(shù)來(lái)實(shí)現(xiàn)分割。這種方法可以捕捉到像素之間的全局關(guān)系,具有較好的準(zhǔn)確性
- 基于深度學(xué)習(xí):近年來(lái),深度學(xué)習(xí)技術(shù)在圖像分割中取得了顯著的進(jìn)展。通過(guò)使用深度卷積神經(jīng)網(wǎng)絡(luò)(CNN)或者全卷積網(wǎng)絡(luò)(FCN),可以學(xué)習(xí)到圖像的語(yǔ)義信息,并生成像素級(jí)的分割結(jié)果
圖像分割在很多應(yīng)用中都起著關(guān)鍵作用。例如,在醫(yī)學(xué)圖像處理中,圖像分割可以用于識(shí)別和定位腫瘤或病變區(qū)域,幫助醫(yī)生進(jìn)行診斷和治療決策。在自動(dòng)駕駛領(lǐng)域,圖像分割可用于識(shí)別道路、行人和交通標(biāo)志等,并提供有關(guān)環(huán)境的關(guān)鍵信息。此外,圖像分割還在圖像編輯、目標(biāo)檢測(cè)、虛擬現(xiàn)實(shí)和增強(qiáng)現(xiàn)實(shí)等領(lǐng)域有廣泛的應(yīng)用
二:閾值分割
(1)概述
閾值分割:是圖像分割中最簡(jiǎn)單和常用的方法之一。它基于像素的灰度值或顏色信息,將圖像中的像素分成兩個(gè)或多個(gè)不同的區(qū)域。閾值分割的基本思想是選擇一個(gè)閾值,將圖像中的像素分為高于或低于該閾值的兩個(gè)類別。步驟如下
- 灰度化:將彩色圖像轉(zhuǎn)換為灰度圖像,以便在單個(gè)灰度通道上進(jìn)行處理
- 選擇閾值:選擇一個(gè)適當(dāng)?shù)拈撝祦?lái)將圖像分割成不同的區(qū)域。閾值可以根據(jù)經(jīng)驗(yàn)、直方圖分析、自適應(yīng)方法等進(jìn)行選擇
- 分割圖像:根據(jù)所選擇的閾值,將圖像中的像素分為兩個(gè)或多個(gè)類別。通常情況下,像素值高于閾值的被分配到一個(gè)類別,低于閾值的被分配到另一個(gè)類別
閾值分割原理如下
g ( x , y ) = { 1 f ( x , y ) ≥ T 0 f ( x , y ) < T g(x, y)=\left\{\begin{array}{ll}1 & f(x, y) \geq T \\0 & f(x, y)<T\end{array}\right. g(x,y)={10?f(x,y)≥Tf(x,y)<T?
其中 f ( x , y ) f(x,y) f(x,y)為原始圖像, g ( x , y ) g(x,y) g(x,y)為結(jié)果圖像(二值), T T T為閾值。顯然,閾值的選取決定了二值化效果的好壞
(2)閾值化
閾值化:是圖像處理中的一種常用技術(shù),用于將圖像中的像素分成兩個(gè)或多個(gè)不同的類別,例如將圖像分為前景和背景。閾值化基于像素的灰度值或顏色信息,通過(guò)設(shè)置一個(gè)閾值來(lái)決定像素屬于哪個(gè)類別。在閾值化過(guò)程中,像素根據(jù)其與閾值的關(guān)系進(jìn)行分類。通常情況下,如果像素值高于閾值,則被歸為一個(gè)類別(例如前景),否則歸為另一個(gè)類別(例如背景)。閾值化的目的是根據(jù)圖像的特性將圖像進(jìn)行簡(jiǎn)化或分割,以便于后續(xù)處理或分析。閾值化常用于以下應(yīng)用場(chǎng)景
- 目標(biāo)檢測(cè):通過(guò)將圖像分割成前景和背景,可以更容易地提取感興趣的目標(biāo)區(qū)域,并進(jìn)行后續(xù)的目標(biāo)檢測(cè)和識(shí)別
- 圖像分割:閾值化可以將圖像分割成不同的區(qū)域,例如將腫瘤區(qū)域從醫(yī)學(xué)圖像中分割出來(lái),或?qū)⑽矬w從復(fù)雜的背景中分離出來(lái)
- 圖像增強(qiáng):通過(guò)選擇適當(dāng)?shù)拈撝?,可以增?qiáng)圖像的某些特征,例如增強(qiáng)圖像的邊緣信息或改善圖像的對(duì)比度
- 物體計(jì)數(shù):通過(guò)將圖像中的像素分成前景和背景,可以對(duì)前景像素進(jìn)行計(jì)數(shù),從而實(shí)現(xiàn)物體數(shù)量的估計(jì)或統(tǒng)計(jì)
閾值化的方法和技術(shù)有很多種,例如
- 上閾值化:灰度值大于等于閾值的所有像素作為前景像素,其余像素作為背景像素
- 下閾值化:灰度值小于等于閾值的所有像素作為前景像素
- 內(nèi)閾值化:確定一個(gè)較小的閾值和一個(gè)較大的閾值,灰度值介于二者之間的像素作為前景像素
- 外閾值化:灰度值介于小閾值和大閾值之外的像素作為前景像素
(3)基于灰度直方圖的閾值選擇
A:原理
基于灰度直方圖的閾值選擇:它基于圖像的灰度分布特性來(lái)選擇適當(dāng)?shù)拈撝?,將圖像分割成不同的區(qū)域
- 灰度直方圖:首先,計(jì)算圖像的灰度直方圖,即統(tǒng)計(jì)不同灰度級(jí)別的像素?cái)?shù)量。灰度直方圖可以反映圖像中各個(gè)灰度級(jí)別的分布情況
-
閾值選擇:根據(jù)灰度直方圖的形狀和特點(diǎn),選擇一個(gè)適當(dāng)?shù)拈撝祦?lái)將圖像分割成不同的區(qū)域。常見(jiàn)的閾值選擇方法包括以下幾種
- 單峰閾值法:適用于圖像灰度直方圖呈現(xiàn)單個(gè)明顯峰值的情況。閾值通常選擇在峰值處或峰值附近
- 雙峰閾值法:適用于圖像灰度直方圖呈現(xiàn)雙個(gè)明顯峰值的情況,其中一個(gè)峰值代表背景,另一個(gè)峰值代表目標(biāo)或前景。閾值選擇通常在兩個(gè)峰值之間的谷底處
- Otsu’s 方法:Otsu’s 方法是一種基于最大類間方差的自適應(yīng)閾值選擇方法。它能夠自動(dòng)選擇一個(gè)閾值,使得分割后的圖像的前景和背景之間的類間方差最大化
- 高斯混合模型(GMM):GMM 方法假設(shè)圖像中的像素灰度值服從多個(gè)高斯分布,通過(guò)擬合多個(gè)高斯分布,找到各個(gè)分布之間的轉(zhuǎn)折點(diǎn)作為閾值
- 分割圖像:根據(jù)選擇的閾值,將圖像中的像素分成兩個(gè)或多個(gè)類別,通常是將像素灰度值高于閾值的歸為一個(gè)類別,低于閾值的歸為另一個(gè)類別
例如下圖,圖像的灰度直方圖為雙峰分布,表明圖像的內(nèi)容大致為兩部分,分別為灰度分布的兩個(gè)山峰的附近,則選擇閾值為兩峰間的谷底點(diǎn)對(duì)應(yīng)灰度值。這適用于圖像中前景與背景灰度差別明顯,且各占一定比例的情形,是一種特殊的方法。若圖像整體直方圖不具有雙峰或多峰特性,可以考慮局部范圍內(nèi)應(yīng)用
B:程序
如下:實(shí)現(xiàn)基于雙峰分布的直方圖選擇閾值,分割圖像
- 重點(diǎn)在于找到直方圖的峰和波谷,但直方圖通常是不平滑的,因此,首先要平滑直方圖,再去搜索峰和谷
- 程序設(shè)計(jì)中,將直方圖中相鄰三個(gè)灰度的頻數(shù)相加求平均作為中間灰度對(duì)應(yīng)的頻數(shù),不斷平滑直方圖,直至成為雙峰分布
- 也可以采用其他方法確定峰谷
matlab實(shí)現(xiàn):文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-587327.html
clear,clc,close all;
Image=rgb2gray(imread('lotus1.jpg'));
figure,imshow(Image),title('原始圖像');
imhist(Image);
hist1=imhist(Image);
hist2=hist1;
iter=0;
while 1
[is,peak]=Bimodal(hist1);
if is==0
hist2(1)=(hist1(1)*2+hist1(2))/3;
for j=2:255
hist2(j)=(hist1(j-1)+hist1(j)+hist1(j+1))/3;
end
hist2(256)=(hist1(255)+hist1(256)*2)/3;
hist1=hist2;
iter=iter+1;
if iter>1000
break;
end
else
break;
end
end
[trough,pos]=min(hist1(peak(1):peak(2)));
thresh=pos+peak(1);
figure,stem(1:256,hist1,'Marker','none');
hold on
stem([thresh,thresh],[0,trough],'Linewidth',2);
hold off
result=zeros(size(Image));
result(Image>thresh)=1;
figure,imshow(result),title('基于雙峰直方圖的閾值化');
imwrite(result,'bilotus1.jpg');
function [is,peak]=Bimodal(histgram)
count=0;
for j=2:255
if histgram(j-1)<histgram(j) && histgram(j+1)<histgram(j)
count=count+1;
peak(count)=j;
if count>2
is=0;
return;
end
end
end
if count==2
is=1;
else
is=0;
end
end
import cv2
import numpy as np
import matplotlib.pyplot as plt
def Bimodal(histgram):
count = 0
peak = []
for j in range(1, 255):
if histgram[j-1] < histgram[j] and histgram[j+1] < histgram[j]:
count += 1
peak.append(j)
if count > 2:
return 0, peak
if count == 2:
return 1, peak
else:
return 0, peak
# 讀取圖像并轉(zhuǎn)換為灰度圖像
image = cv2.imread('lotus1.jpg')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 顯示原始圖像
plt.figure()
plt.imshow(gray_image, cmap='gray')
plt.title('原始圖像')
# 繪制灰度直方圖
plt.figure()
plt.hist(gray_image.ravel(), bins=256, color='gray')
plt.title('灰度直方圖')
# 計(jì)算灰度直方圖
hist1 = cv2.calcHist([gray_image], [0], None, [256], [0, 256])
hist2 = hist1.copy()
iter = 0
while True:
is_bimodal, peak = Bimodal(hist1)
if is_bimodal == 0:
hist2[0] = (hist1[0]*2 + hist1[1]) / 3
for j in range(1, 255):
hist2[j] = (hist1[j-1] + hist1[j] + hist1[j+1]) / 3
hist2[255] = (hist1[254] + hist1[255]*2) / 3
hist1 = hist2
iter += 1
if iter > 1000:
break
else:
break
# 根據(jù)雙峰直方圖選擇閾值
trough, pos = np.min(hist1[peak[0]:peak[1]]), np.argmin(hist1[peak[0]:peak[1]])
thresh = pos + peak[0]
# 繪制帶閾值的直方圖
plt.figure()
plt.stem(np.arange(256), hist1, markerfmt='none')
plt.axvline(x=thresh, ymin=0, ymax=trough, linewidth=2)
plt.title('雙峰直方圖閾值化')
# 基于閾值進(jìn)行圖像分割
result = np.zeros_like(gray_image)
result[gray_image > thresh] = 255
# 顯示分割結(jié)果
plt.figure()
plt.imshow(result, cmap='gray')
plt.title('基于雙峰直方圖的閾值化')
# 保存結(jié)果圖像
cv2.imwrite('bilotus1.jpg', result)
# 顯示所有圖像
plt.show()
(4)基于模式分類思路的閾值選擇
A:原理
基于模式分類思路的閾值選擇:是一種根據(jù)像素的特征模式來(lái)選擇閾值的方法。它基于對(duì)圖像中不同像素的特征進(jìn)行分析和分類,以確定最佳的閾值,將圖像分割為不同的區(qū)域。以下是基于模式分類思路的閾值選擇的基本步驟
- 計(jì)算特征:首先,對(duì)圖像中的像素進(jìn)行特征計(jì)算。常見(jiàn)的特征包括像素灰度值、梯度、紋理等
- 劃分模式:將像素根據(jù)特征的不同模式進(jìn)行分類。根據(jù)特定的閾值,將像素分為不同的模式類別。例如,可以將像素分為背景和前景模式類別
- 計(jì)算類別間差異度量:對(duì)不同的模式類別計(jì)算其間的差異度量,比如類別之間的平均灰度差異、方差等。這些度量反映了不同類別之間的分離程度
- 選擇最佳閾值:根據(jù)類別間的差異度量,選擇最佳的閾值作為分割圖像的閾值。通常,較大的類別間差異度量意味著更好的分割效果
- 應(yīng)用閾值:使用選擇的閾值將圖像分割為不同的區(qū)域。將像素灰度值與閾值進(jìn)行比較,并根據(jù)比較結(jié)果將像素分為不同的類別
基于模式分類思路的閾值選擇方法可以適應(yīng)不同的圖像特征和分割要求。通過(guò)對(duì)像素進(jìn)行特征分析和模式分類,該方法能夠根據(jù)圖像的內(nèi)在特性選擇最佳的閾值,從而實(shí)現(xiàn)有效的圖像分割。然而,選擇適當(dāng)?shù)奶卣骱秃线m的模式分類算法是該方法的關(guān)鍵,需要根據(jù)具體問(wèn)題進(jìn)行選擇和優(yōu)化
B:最大類間方差法(OTSU)
最大類間方差法(OTSU):是一種自適應(yīng)的圖像閾值選擇方法,用于將圖像分割成前景和背景兩個(gè)區(qū)域。該方法通過(guò)最大化圖像兩個(gè)類別之間的類間方差,來(lái)選擇最佳的閾值,以實(shí)現(xiàn)最佳的分割效果。下面是最大類間方差法的基本原理
- 計(jì)算直方圖:首先,計(jì)算圖像的灰度直方圖,統(tǒng)計(jì)不同灰度級(jí)別的像素?cái)?shù)量
- 計(jì)算類內(nèi)方差:對(duì)于每個(gè)可能的閾值(0到255),將圖像分成前景和背景兩個(gè)類別,并計(jì)算兩個(gè)類別的類內(nèi)方差。類內(nèi)方差反映了同一類別內(nèi)像素灰度值的變化程度
- 計(jì)算類間方差:通過(guò)將圖像分割為前景和背景兩個(gè)類別,計(jì)算這兩個(gè)類別之間的類間方差。類間方差反映了兩個(gè)類別之間的灰度差異程度
- 最大化類間方差:遍歷所有可能的閾值,找到使類間方差最大的閾值,即最佳閾值。最大化類間方差意味著前景和背景之間的差異最大化,從而實(shí)現(xiàn)最佳的圖像分割效果
- 應(yīng)用閾值:使用選擇的最佳閾值將圖像分割為前景和背景兩個(gè)區(qū)域。將像素灰度值與閾值進(jìn)行比較,并根據(jù)比較結(jié)果將像素分為不同的類別
兩類方差
σ o 2 = 1 p o ∑ i = 0 T p i ( i ? μ o ) 2 σ B 2 = 1 p B ∑ i = T + 1 L ? 1 p i ( i ? μ B ) 2 \sigma_{o}^{2}=\frac{1}{p_{o}} \sum_{i=0}^{T} p_{i}\left(i-\mu_{o}\right)^{2} \quad \sigma_{B}^{2}=\frac{1}{p_{B}} \sum_{i=T+1}^{L-1} p_{i}\left(i-\mu_{B}\right)^{2} σo2?=po?1?i=0∑T?pi?(i?μo?)2σB2?=pB?1?i=T+1∑L?1?pi?(i?μB?)2
類內(nèi)方差和類間方差
σ i n 2 = p O ? σ o 2 + p B ? σ B 2 σ 1 2 = p o × ( μ o ? μ ) 2 + p B × ( μ B ? μ ) 2 \begin{array}{l}\sigma_{i n}^{2}=p_{O} \cdot \sigma_{o}^{2}+p_{B} \cdot \sigma_{B}^{2} \\\sigma_{1}^{2}=p_{o} \times\left(\mu_{o}-\mu\right)^{2}+p_{B} \times\left(\mu_{B}-\mu\right)^{2}\end{array} σin2?=pO??σo2?+pB??σB2?σ12?=po?×(μo??μ)2+pB?×(μB??μ)2?
如下
matlab實(shí)現(xiàn)
Image=rgb2gray(imread('lotus1.jpg'));
figure,imshow(Image),title('原始圖像');
T=graythresh(Image);
result=im2bw(Image,T);
figure,imshow(result),title('OTSU方法二值化圖像 ');
% imwrite(result,'lotus1otsu.jpg');
python實(shí)現(xiàn):
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 讀取圖像并轉(zhuǎn)換為灰度圖像
image = cv2.imread('lotus1.jpg')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 顯示原始圖像
plt.figure()
plt.imshow(gray_image, cmap='gray')
plt.title('原始圖像')
# 使用Otsu方法選擇閾值
_, threshold = cv2.threshold(gray_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 對(duì)圖像進(jìn)行二值化
result = cv2.bitwise_and(gray_image, threshold)
# 顯示二值化結(jié)果
plt.figure()
plt.imshow(result, cmap='gray')
plt.title('OTSU方法二值化圖像')
# 保存結(jié)果圖像
# cv2.imwrite('lotus1otsu.jpg', result)
# 顯示所有圖像
plt.show()
C:最大熵法
最大熵法:是一種常用的圖像分割方法之一,用于將圖像分割為不同的區(qū)域。它基于信息熵的概念,通過(guò)最大化圖像中各個(gè)區(qū)域的熵來(lái)選擇最佳的分割結(jié)果。以下是最大熵法的基本原理
- 定義圖像熵:首先,計(jì)算圖像的全局熵,即將整個(gè)圖像視為一個(gè)區(qū)域,計(jì)算其熵。圖像熵是表示圖像灰度分布的隨機(jī)性和不確定性的度量
- 定義局部熵:將圖像劃分為不同的區(qū)域,并計(jì)算每個(gè)區(qū)域的局部熵。局部熵反映了各個(gè)區(qū)域內(nèi)像素灰度分布的隨機(jī)性和不確定性
- 計(jì)算條件熵:根據(jù)圖像的分割結(jié)果,計(jì)算每個(gè)區(qū)域的條件熵。條件熵是指在已知區(qū)域分割情況下,對(duì)于每個(gè)區(qū)域內(nèi)的像素,其灰度分布的隨機(jī)性和不確定性
- 定義目標(biāo)函數(shù):定義一個(gè)目標(biāo)函數(shù),如最大熵準(zhǔn)則函數(shù),將全局熵、局部熵和條件熵組合起來(lái)。目標(biāo)函數(shù)的目標(biāo)是最大化分割結(jié)果的熵,以達(dá)到最佳的圖像分割效果
- 尋找最佳分割:通過(guò)迭代優(yōu)化方法或其他優(yōu)化算法,搜索最佳的分割結(jié)果。最終目標(biāo)是找到使目標(biāo)函數(shù)最大化的最佳區(qū)域分割
最大熵法能夠自適應(yīng)地選擇圖像的最佳分割結(jié)果,無(wú)需預(yù)先了解圖像的特征或背景信息。通過(guò)最大化圖像的熵,該方法能夠?qū)崿F(xiàn)在不同區(qū)域間的邊界上找到最佳的分割結(jié)果,適用于不同類型的圖像分割任務(wù)。需要注意的是,最大熵法在實(shí)際應(yīng)用中可能需要考慮一些因素,如計(jì)算復(fù)雜度、初始分割結(jié)果、優(yōu)化算法等。根據(jù)具體的應(yīng)用需求和圖像特性,可能需要結(jié)合其他的圖像處理技術(shù)和算法,以提高分割的準(zhǔn)確性和魯棒性
如下
matlab實(shí)現(xiàn):
clear,clc,close all;
Image=rgb2gray(imread('fruit.jpg'));
figure,imshow(Image),title('原始圖像');
hist=imhist(Image);
bottom=min(Image(:))+1;
top=max(Image(:))+1;
J=zeros(256,1);
for t=bottom+1:top-1
po=sum(hist(bottom:t));
pb=sum(hist(t+1:top));
ho=0;
hb=0;
for j=bottom:t
ho=ho-log(hist(j)/po+0.01)*hist(j)/po;
end
for j=t+1:top
hb=hb-log(hist(j)/pb+0.01)*hist(j)/pb;
end
J(t)=ho+hb;
end
[maxJ,pos]=max(J(:));
result=zeros(size(Image));
result(Image>pos)=1;
figure,imshow(result);
python實(shí)現(xiàn):
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 讀取圖像并轉(zhuǎn)換為灰度圖像
image = cv2.imread('fruit.jpg')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 顯示原始圖像
plt.figure()
plt.imshow(gray_image, cmap='gray')
plt.title('原始圖像')
# 計(jì)算圖像直方圖
hist = cv2.calcHist([gray_image], [0], None, [256], [0, 256])
bottom = np.min(gray_image) + 1
top = np.max(gray_image) + 1
J = np.zeros((256, 1))
for t in range(bottom + 1, top):
po = np.sum(hist[bottom:t])
pb = np.sum(hist[t+1:top])
ho = 0
hb = 0
for j in range(bottom, t):
ho = ho - np.log(hist[j] / po + 0.01) * hist[j] / po
for j in range(t+1, top):
hb = hb - np.log(hist[j] / pb + 0.01) * hist[j] / pb
J[t] = ho + hb
maxJ, pos = np.max(J), np.argmax(J)
# 分割圖像
result = np.zeros_like(gray_image)
result[gray_image > pos] = 255
# 顯示分割結(jié)果
plt.figure()
plt.imshow(result, cmap='gray')
# 顯示所有圖像
plt.show()
D:最小誤差法
最小誤差法:是一種常用的圖像分割方法之一,用于將圖像分割為不同的區(qū)域。它基于像素灰度值的統(tǒng)計(jì)特性,通過(guò)最小化分割中的誤差來(lái)選擇最佳的閾值,以實(shí)現(xiàn)最佳的分割效果。以下是最小誤差法的基本原理
- 計(jì)算直方圖:首先,計(jì)算圖像的灰度直方圖,統(tǒng)計(jì)不同灰度級(jí)別的像素?cái)?shù)量
- 初始化閾值:選擇一個(gè)初始閾值,可以是根據(jù)經(jīng)驗(yàn)確定的值,或者根據(jù)某種準(zhǔn)則選擇的初步估計(jì)
- 計(jì)算平均灰度值:根據(jù)當(dāng)前閾值,將圖像分割為兩個(gè)區(qū)域:低于閾值的區(qū)域?yàn)楸尘?,高于閾值的區(qū)域?yàn)榍熬?。?jì)算兩個(gè)區(qū)域的平均灰度值
- 更新閾值:根據(jù)前一步計(jì)算得到的平均灰度值,更新閾值。常見(jiàn)的更新方法包括取兩個(gè)區(qū)域平均灰度值的平均值或加權(quán)平均值
- 計(jì)算誤差:根據(jù)更新后的閾值,計(jì)算分割中的誤差。誤差可以根據(jù)不同的準(zhǔn)則定義,如均方誤差、交叉熵等
- 重復(fù)步驟3至5:迭代執(zhí)行步驟3至5,直到達(dá)到收斂條件,如閾值的變化小于某個(gè)閾值,或者誤差不再明顯改變
- 最佳閾值選擇:根據(jù)達(dá)到收斂的結(jié)果,選擇最佳的閾值作為圖像的分割閾值
最小誤差法能夠根據(jù)圖像的灰度分布特性自適應(yīng)地選擇最佳的分割閾值。通過(guò)迭代優(yōu)化的過(guò)程,該方法通過(guò)最小化分割中的誤差來(lái)實(shí)現(xiàn)最佳的圖像分割效果。需要注意的是,最小誤差法的性能受到初始閾值和收斂條件的選擇的影響。選擇合適的初始閾值和適當(dāng)?shù)氖諗織l件可以幫助提高分割的準(zhǔn)確性和效率。此外,對(duì)于復(fù)雜的圖像場(chǎng)景,可能需要結(jié)合其他的圖像處理技術(shù)和算法,以提高分割的準(zhǔn)確性和魯棒性
如下
matlab實(shí)現(xiàn):
clear,clc,close all;
Image=rgb2gray(imread('fruit.jpg'));
figure,imshow(Image),title('原始圖像');
hist=imhist(Image);
bottom=min(Image(:))+1;
top=max(Image(:))+1;
J=zeros(256,1);
J=J+100000;
alpha=0.25;
scope=find(hist>5);
minthresh=scope(1);
maxthresh=scope(end);
for t=minthresh+1:maxthresh-1
miuo=0;
sigmaho=0;
for j=bottom:t
miuo=miuo+hist(j)*double(j);
end
pixelnum=sum(hist(bottom:t));
miuo=miuo/pixelnum;
for j=bottom:t
sigmaho=sigmaho+(double(j)-miuo)^2*hist(j);
end
sigmaho=sigmaho/pixelnum;
miub=0;
sigmahb=0;
for j=t+1:top
miub=miub+hist(j)*double(j);
end
pixelnum=sum(hist(t+1:top));
miub=miub/pixelnum;
for j=t+1:top
sigmahb=sigmahb+(double(j)-miub)^2*hist(j);
end
sigmahb=sigmahb/pixelnum;
Epsilonb=0;
Epsilono=0;
for j=bottom:t
pb=exp(-(double(j)-miub)^2/(sigmahb*2+eps))/(sqrt(2*pi*sigmahb)+eps);
Epsilonb=Epsilonb+pb;
end
for j=t+1:top
po=exp(-(double(j)-miuo)^2/(sigmaho*2+eps))/(sqrt(2*pi*sigmaho)+eps);
Epsilono=Epsilono+po;
end
J(t)=alpha*Epsilono+(1-alpha)*Epsilonb;
end
[minJ,pos]=min(J(:));
result=zeros(size(Image));
result(Image>pos)=1;
figure,imshow(result),title('最小誤差閾值法');
python實(shí)現(xiàn):
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 讀取圖像并轉(zhuǎn)換為灰度圖像
image = cv2.imread('fruit.jpg')
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 顯示原始圖像
plt.figure()
plt.imshow(image_gray, cmap='gray')
plt.title('原始圖像')
# 計(jì)算直方圖
hist = cv2.calcHist([image_gray], [0], None, [256], [0, 256])
bottom = np.min(image_gray) + 1
top = np.max(image_gray) + 1
J = np.zeros((256, 1)) + 100000
alpha = 0.25
# 找到直方圖中像素?cái)?shù)大于5的范圍
scope = np.where(hist > 5)[0]
minthresh = scope[0]
maxthresh = scope[-1]
for t in range(minthresh + 1, maxthresh):
miuo = 0
sigmaho = 0
for j in range(bottom, t):
miuo += hist[j] * j
pixelnum = np.sum(hist[bottom:t])
miuo /= pixelnum
for j in range(bottom, t):
sigmaho += (j - miuo) ** 2 * hist[j]
sigmaho /= pixelnum
miub = 0
sigmahb = 0
for j in range(t + 1, top):
miub += hist[j] * j
pixelnum = np.sum(hist[t + 1:top])
miub /= pixelnum
for j in range(t + 1, top):
sigmahb += (j - miub) ** 2 * hist[j]
sigmahb /= pixelnum
Epsilonb = 0
Epsilono = 0
for j in range(bottom, t):
pb = np.exp(-(j - miub) ** 2 / (sigmahb * 2 + np.finfo(float).eps)) / (np.sqrt(2 * np.pi * sigmahb) + np.finfo(float).eps)
Epsilonb += pb
for j in range(t + 1, top):
po = np.exp(-(j - miuo) ** 2 / (sigmaho * 2 + np.finfo(float).eps)) / (np.sqrt(2 * np.pi * sigmaho) + np.finfo(float).eps)
Epsilono += po
J[t] = alpha * Epsilono + (1 - alpha) * Epsilonb
minJ, pos = np.min(J), np.argmin(J)
result = np.zeros(image_gray.shape)
# 根據(jù)閾值分割圖像
result[image_gray > pos] = 1
# 顯示分割結(jié)果
plt.figure()
plt.imshow(result, cmap='gray')
plt.title('最小誤差閾值法')
plt.show()
(5)其他閾值分割方法
A:基于迭代運(yùn)算的閾值選擇
基于迭代運(yùn)算的閾值選擇:是一種常用的圖像分割方法,它通過(guò)反復(fù)迭代來(lái)求解最佳的閾值,以將圖像分割為目標(biāo)和背景兩部分。該方法的基本思想是將圖像的灰度值根據(jù)閾值劃分為兩個(gè)區(qū)域,并根據(jù)兩個(gè)區(qū)域的平均灰度值來(lái)更新閾值,直到滿足某個(gè)終止條件為止。一般步驟如下
- 選擇初始閾值:可以是任意合理的值,例如圖像灰度值的中值
- 根據(jù)選定的閾值,將圖像分為兩個(gè)區(qū)域:一個(gè)區(qū)域包含大于閾值的像素,另一個(gè)區(qū)域包含小于或等于閾值的像素
- 計(jì)算兩個(gè)區(qū)域的平均灰度值:一個(gè)是大于閾值的像素的平均灰度值,另一個(gè)是小于或等于閾值的像素的平均灰度值
- 將平均灰度值的平均作為新的閾值
- 重復(fù)步驟2至步驟4,直到滿足某個(gè)停止準(zhǔn)則:常用的停止準(zhǔn)則包括閾值的變化小于某個(gè)預(yù)設(shè)閾值或迭代次數(shù)達(dá)到預(yù)設(shè)值
- 最終得到的閾值即為最佳閾值,將圖像根據(jù)該閾值進(jìn)行二值化分割
基于迭代運(yùn)算的閾值分割方法簡(jiǎn)單易懂,并且適用于大部分圖像,特別是對(duì)于灰度直方圖具有雙峰特征的圖像。然而,該方法對(duì)圖像噪聲和灰度分布不均勻的情況可能不夠穩(wěn)定和準(zhǔn)確,因此在實(shí)際應(yīng)用中可能需要進(jìn)行參數(shù)調(diào)整和優(yōu)化
如下
matlab實(shí)現(xiàn):
clear,clc,close all;
Image=im2double(rgb2gray(imread('lotus1.jpg')));
figure,imshow(Image),title('原始圖像');
T=(max(Image(:))+min(Image(:)))/2;
equal=false;
while ~equal
rb=find(Image>=T);
ro=find(Image<T);
NewT=(mean(Image(rb))+mean(Image(ro)))/2;
equal=abs(NewT-T)<1/256;
T=NewT;
end
result=im2bw(Image,T);
figure,imshow(result),title('迭代方法二值化圖像 ');
python實(shí)現(xiàn):
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 讀取圖像并轉(zhuǎn)換為灰度圖像
image = cv2.imread('lotus1.jpg')
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image_gray = image_gray.astype(float) / 255.0
# 顯示原始圖像
plt.figure()
plt.imshow(image_gray, cmap='gray')
plt.title('原始圖像')
# 初始化閾值
T = (np.max(image_gray) + np.min(image_gray)) / 2
equal = False
while not equal:
rb = np.where(image_gray >= T)
ro = np.where(image_gray < T)
NewT = (np.mean(image_gray[rb]) + np.mean(image_gray[ro])) / 2
equal = abs(NewT - T) < 1 / 256
T = NewT
# 根據(jù)閾值進(jìn)行二值化
result = (image_gray >= T).astype(np.uint8)
# 顯示二值化結(jié)果
plt.figure()
plt.imshow(result, cmap='gray')
plt.title('迭代方法二值化圖像')
plt.show()
B:基于模糊理論的閾值選擇
基于模糊理論的閾值選擇:與傳統(tǒng)二值化方法只使用一個(gè)固定閾值不同,基于模糊理論的閾值分割方法使用模糊集合來(lái)描述像素屬于目標(biāo)或背景的隸屬度,從而更靈活地處理圖像中的不確定性和復(fù)雜性。模糊度表示一個(gè)模糊集的模糊程度,模糊熵是一種度量模糊度的數(shù)量指標(biāo),用模糊熵作為目標(biāo)函數(shù),求解最佳閾值。步驟如下
- 確定模糊化方法:將原始圖像模糊化處理,常見(jiàn)的模糊化方法包括高斯模糊、均值模糊等。模糊化有助于降低噪聲的影響,并將圖像轉(zhuǎn)化為模糊集合
- 確定隸屬函數(shù):為圖像中的每個(gè)像素定義隸屬函數(shù),隸屬函數(shù)描述了該像素屬于目標(biāo)或背景的程度。常見(jiàn)的隸屬函數(shù)包括三角隸屬函數(shù)、高斯隸屬函數(shù)等
- 確定模糊閾值:選擇一個(gè)合適的模糊閾值,將像素根據(jù)隸屬函數(shù)劃分為目標(biāo)或背景。這個(gè)過(guò)程相當(dāng)于傳統(tǒng)二值化中的閾值確定,但基于模糊理論,閾值變得模糊,允許像素在目標(biāo)和背景之間具有模糊的隸屬度
- 模糊化反演:根據(jù)確定的模糊閾值,通過(guò)模糊化反演將模糊集合映射回到二值圖像,得到最終的分割結(jié)果
基于模糊理論的閾值分割方法相比傳統(tǒng)二值化方法具有更強(qiáng)的適應(yīng)性和魯棒性,特別適用于圖像中目標(biāo)和背景之間存在模糊邊界的情況。這種方法可以在處理噪聲較多或光照不均勻的圖像時(shí)表現(xiàn)更好,但在一些情況下可能需要更多的計(jì)算資源。因此,在應(yīng)用時(shí)需要根據(jù)具體情況選擇適當(dāng)?shù)膱D像分割方法
如下
matlab實(shí)現(xiàn):
clear,clc,close all;
Image=rgb2gray(imread('lotus1.jpg'));
figure,imshow(Image),title('原始圖像');
hist=imhist(Image);
bottom=min(Image(:))+1;
top=max(Image(:))+1;
C=double(top-bottom);
S=zeros(256,1);
J=10^10;
for t=bottom+1:top-1
miuo=0;
for j=bottom:t
miuo=miuo+hist(j)*double(j);
end
pixelnum=sum(hist(bottom:t));
miuo=miuo/pixelnum;
for j=bottom:t
miuf=1/(1+abs(double(j)-miuo)/C);
S(j)=-miuf*log(miuf)-(1-miuf)*log(1-miuf);
end
miub=0;
for j=t+1:top
miub=miub+hist(j)*double(j);
end
pixelnum=sum(hist(t+1:top));
miub=miub/pixelnum;
for j=t+1:top
miuf=1/(1+abs(double(j)-miub)/C);
S(j)=-miuf*log(miuf)-(1-miuf)*log(1-miuf);
end
currentJ=sum(hist(bottom:top).*S(bottom:top));
if currentJ<J
J=currentJ;
thresh=t;
end
end
result=zeros(size(Image));
result(Image>thresh)=1;
figure,imshow(result);
python實(shí)現(xiàn):
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fuzzy_threshold_segmentation(image):
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist([image_gray], [0], None, [256], [0, 256])
bottom = np.min(image_gray) + 1
top = np.max(image_gray) + 1
C = float(top - bottom)
S = np.zeros(256)
J = 10**10
for t in range(int(bottom + 1), int(top)):
miuo = 0
for j in range(int(bottom), int(t)):
miuo += hist[j] * float(j)
pixelnum = np.sum(hist[int(bottom):int(t)])
miuo = miuo / pixelnum
for j in range(int(bottom), int(t)):
miuf = 1 / (1 + abs(float(j) - miuo) / C)
S[j] = -miuf * np.log(miuf) - (1 - miuf) * np.log(1 - miuf)
miub = 0
for j in range(int(t + 1), int(top)):
miub += hist[j] * float(j)
pixelnum = np.sum(hist[int(t + 1):int(top)])
miub = miub / pixelnum
for j in range(int(t + 1), int(top)):
miuf = 1 / (1 + abs(float(j) - miub) / C)
S[j] = -miuf * np.log(miuf) - (1 - miuf) * np.log(1 - miuf)
currentJ = np.sum(hist[int(bottom):int(top)] * S[int(bottom):int(top)])
if currentJ < J:
J = currentJ
thresh = t
result = np.zeros_like(image_gray)
result[image_gray > thresh] = 255
return result
if __name__ == "__main__":
image = cv2.imread('lotus1.jpg')
segmented_image = fuzzy_threshold_segmentation(image)
plt.figure()
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('原始圖像')
plt.subplot(1, 2, 2)
plt.imshow(segmented_image, cmap='gray')
plt.title('分割結(jié)果')
plt.show()
三:邊界分割
(1)基于梯度的邊界閉合
基于梯度的邊界閉合:是一種圖像邊界分割技術(shù),旨在從圖像中找到封閉的邊界或物體輪廓。該方法利用圖像梯度信息來(lái)檢測(cè)邊緣,并通過(guò)將邊緣點(diǎn)連接起來(lái)形成封閉的輪廓。基本步驟如下
- 計(jì)算圖像梯度:首先,通過(guò)應(yīng)用梯度算子(如Sobel、Prewitt、或Canny算子)計(jì)算圖像的梯度。梯度表示圖像中灰度值變化的強(qiáng)度和方向
- 邊緣檢測(cè):根據(jù)梯度計(jì)算結(jié)果,選擇一個(gè)適當(dāng)?shù)拈撝祦?lái)檢測(cè)圖像中的邊緣??梢允褂瞄撝祷椒ǎㄈ绻潭ㄩ撝祷蜃赃m應(yīng)閾值)來(lái)將梯度圖像轉(zhuǎn)換為二值圖像,其中邊緣點(diǎn)被設(shè)置為白色,非邊緣點(diǎn)被設(shè)置為黑色
- 邊緣連接:在邊緣檢測(cè)后,可能會(huì)存在一些不完整的邊緣線段。為了得到封閉的輪廓,需要將邊緣點(diǎn)連接起來(lái)。這可以通過(guò)應(yīng)用邊緣跟蹤算法(如霍夫變換或其他邊緣追蹤方法)來(lái)實(shí)現(xiàn)。邊緣跟蹤算法可以找到相鄰的邊緣點(diǎn)并將它們連接成連續(xù)的邊緣線
- 邊緣閉合:邊緣連接后,通常會(huì)得到一個(gè)未完全封閉的邊界。為了使邊界封閉,可以使用形態(tài)學(xué)操作(如膨脹、閉操作)來(lái)填充邊界內(nèi)的空洞
- 可選的后處理:根據(jù)應(yīng)用需求,可以進(jìn)行一些后處理步驟,如去除小的噪聲區(qū)域、平滑邊界線等
(2)霍夫(Hough)變換
霍夫(Hough)變換:是一種在圖像處理和計(jì)算機(jī)視覺(jué)領(lǐng)域中廣泛使用的技術(shù)。它最初是由霍夫(Hough)于1962年提出,用于檢測(cè)圖像中的直線,但后來(lái)被擴(kuò)展用于檢測(cè)其他形狀,如圓、橢圓等?;舴蜃儞Q主要用于在圖像中檢測(cè)幾何形狀,并且對(duì)噪聲和不完整形狀邊緣具有較好的魯棒性。核心思想是建立一種點(diǎn)-線對(duì)偶關(guān)系,將圖像從圖像空間變換到參數(shù)空間,確定曲線的參數(shù),進(jìn)而確定圖像中的曲線。若邊界線形狀已知,通過(guò)檢測(cè)圖像中離散的邊界點(diǎn),確定曲線參數(shù),在圖像空間重繪邊界曲線,進(jìn)而改良邊界。步驟如下
- 邊緣檢測(cè):首先,需要對(duì)圖像進(jìn)行邊緣檢測(cè),以便在霍夫變換中處理邊緣點(diǎn)。可以使用Canny邊緣檢測(cè)等方法來(lái)獲取圖像的邊緣
- 參數(shù)空間表示:對(duì)于待檢測(cè)的幾何形狀(如直線),需要選擇適當(dāng)?shù)膮?shù)表示。例如,對(duì)于直線,通常使用極坐標(biāo)(ρ, θ)來(lái)表示,其中ρ表示從原點(diǎn)到直線的垂直距離,θ表示直線的傾斜角度
- 累加器數(shù)組:創(chuàng)建一個(gè)累加器數(shù)組,在參數(shù)空間中為每個(gè)可能的參數(shù)組合(ρ, θ)初始化計(jì)數(shù)為0
- 投票過(guò)程:對(duì)于邊緣圖像中的每個(gè)邊緣點(diǎn),根據(jù)其在參數(shù)空間中的可能參數(shù)(ρ, θ)對(duì)累加器數(shù)組進(jìn)行投票,即將對(duì)應(yīng)的計(jì)數(shù)值加一
- 閾值設(shè)定:根據(jù)累加器數(shù)組中的投票結(jié)果,可以設(shè)置一個(gè)閾值,用于確定檢測(cè)到的幾何形狀。只有當(dāng)累加器數(shù)組中的計(jì)數(shù)值大于設(shè)定的閾值時(shí),才被視為有效的幾何形狀
- 參數(shù)反變換:根據(jù)累加器數(shù)組中的有效投票,將參數(shù)反變換回原始圖像空間,得到檢測(cè)到的幾何形狀在圖像中的位置
霍夫變換在圖像中檢測(cè)直線、圓、橢圓等形狀方面具有很強(qiáng)的魯棒性和廣泛的應(yīng)用。然而,霍夫變換的計(jì)算復(fù)雜度較高,對(duì)于大規(guī)模圖像或復(fù)雜形狀的檢測(cè)可能需要較多的計(jì)算資源。因此,在實(shí)際應(yīng)用中,可以根據(jù)具體情況選擇使用霍夫變換或其他更高效的方法來(lái)檢測(cè)幾何形狀
如下
matlab實(shí)現(xiàn):
Image=rgb2gray(imread('houghsource.bmp'));
bw=edge(Image,'canny');
figure,imshow(bw);
[h,t,r]=hough(bw,'RhoResolution',0.5,'ThetaResolution',0.5);
figure,imshow(imadjust(mat2gray(h)),'XData',t,'YData',r,'InitialMagnification','fit');
xlabel('\theta'),ylabel('\rho');
axis on,axis normal,hold on;
P=houghpeaks(h,2);
x=t(P(:,2));
y=r(P(:,1));
plot(x,y,'s','color','r');
lines=houghlines(bw,t,r,P,'FillGap',5,'Minlength',7);
figure,imshow(Image);
hold on;
max_len=0;
for i=1:length(lines)
xy=[lines(i).point1;lines(i).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','g');
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','y');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','r');
end
python實(shí)現(xiàn):
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 讀取圖像并轉(zhuǎn)換為灰度圖像
image = cv2.imread('houghsource.bmp')
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 邊緣檢測(cè)
bw = cv2.Canny(image_gray, 100, 200)
# 顯示邊緣圖像
plt.figure()
plt.imshow(bw, cmap='gray')
plt.title('邊緣圖像')
plt.show()
# Hough變換
h, t, r = cv2.HoughLines(bw, rho=0.5, theta=np.pi/360, threshold=100)
# 顯示Hough變換結(jié)果
plt.figure()
plt.imshow(np.log(1 + h), extent=[np.rad2deg(t[-1]), np.rad2deg(t[0]), r[-1], r[0]],
cmap='gray', aspect=1/2)
plt.title('Hough變換結(jié)果')
plt.xlabel('Theta (degrees)')
plt.ylabel('Rho')
plt.show()
# 提取Hough變換的峰值點(diǎn)
P = cv2.HoughPeaks(h, 2, np.pi/360, threshold=100)
# 顯示提取的峰值點(diǎn)
plt.figure()
plt.imshow(np.log(1 + h), extent=[np.rad2deg(t[-1]), np.rad2deg(t[0]), r[-1], r[0]],
cmap='gray', aspect=1/2)
plt.title('Hough變換結(jié)果(峰值點(diǎn))')
plt.xlabel('Theta (degrees)')
plt.ylabel('Rho')
plt.plot(np.rad2deg(t[P[:, 1]]), r[P[:, 0]], 's', color='r')
plt.show()
# 提取直線并在原圖上繪制
lines = cv2.HoughLinesP(bw, 1, np.pi/180, threshold=100, minLineLength=7, maxLineGap=5)
plt.figure()
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('檢測(cè)到的直線')
plt.xlabel('x')
plt.ylabel('y')
plt.xlim(0, image.shape[1])
plt.ylim(image.shape[0], 0)
for line in lines:
x1, y1, x2, y2 = line[0]
plt.plot([x1, x2], [y1, y2], 'g-', linewidth=2)
plt.plot(x1, y1, 'yx', markersize=8)
plt.plot(x2, y2, 'rx', markersize=8)
plt.show()
(3)邊界跟蹤
邊界跟蹤:是一種在圖像處理和計(jì)算機(jī)視覺(jué)中用于提取物體輪廓的技術(shù)。邊界跟蹤的目標(biāo)是找到物體在圖像中的邊界像素,從而得到物體的輪廓信息。邊界跟蹤算法通常從一個(gè)起始點(diǎn)開(kāi)始,沿著物體的邊界像素依次進(jìn)行跟蹤,直到回到起始點(diǎn)為止。跟蹤過(guò)程根據(jù)像素的連通性進(jìn)行,從當(dāng)前像素找到下一個(gè)相鄰的邊界像素,然后跳轉(zhuǎn)到該像素進(jìn)行跟蹤,直到回到起始點(diǎn)為止。以下是一種簡(jiǎn)單的邊界跟蹤算法(8鄰域跟蹤算法)的基本步驟
- 選擇起始點(diǎn):選擇一個(gè)圖像中的像素點(diǎn)作為起始點(diǎn),該點(diǎn)應(yīng)該位于物體邊界上
- 8鄰域搜索:從起始點(diǎn)開(kāi)始,按照8鄰域的方式搜索相鄰像素。對(duì)于當(dāng)前像素,檢查其8個(gè)相鄰像素(上、下、左、右、左上、右上、左下、右下),找到第一個(gè)邊界像素(通常為非背景像素),然后將當(dāng)前像素更新為該邊界像素,并將該邊界像素添加到邊界點(diǎn)集合中
- 繼續(xù)跟蹤:重復(fù)步驟2,直到回到起始點(diǎn)
- 停止跟蹤:當(dāng)回到起始點(diǎn)時(shí),邊界跟蹤結(jié)束,此時(shí)邊界點(diǎn)集合中存儲(chǔ)的像素就是物體的輪廓信息
邊界跟蹤算法可以用于物體檢測(cè)、圖像分割、輪廓提取等應(yīng)用。不同的邊界跟蹤算法有不同的連通性要求和終止條件,常見(jiàn)的邊界跟蹤算法還包括4鄰域跟蹤算法和Moore-Neighbor跟蹤算法等。在實(shí)際應(yīng)用中,可以根據(jù)圖像的特點(diǎn)和應(yīng)用需求選擇合適的邊界跟蹤算法
如下
matlab實(shí)現(xiàn):
Image=im2bw(imread('algae.jpg'));
Image=1-Image; %bwboundaries函數(shù)以白色區(qū)域?yàn)槟繕?biāo),本圖中目標(biāo)暗,因此反色。
[B,L]=bwboundaries(Image);
figure,imshow(L),title('劃分的區(qū)域');
hold on;
for i=1:length(B)
boundary=B{i};
plot(boundary(:,2),boundary(:,1),'r','LineWidth',2);
end
python實(shí)現(xiàn):文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-587327.html
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 讀取圖像并轉(zhuǎn)換為二值圖像
image = cv2.imread('algae.jpg')
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, Image = cv2.threshold(image_gray, 128, 255, cv2.THRESH_BINARY)
# 反色處理
Image = 255 - Image
# 使用cv2.findContours函數(shù)獲取邊界點(diǎn)
contours, _ = cv2.findContours(Image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 繪制邊界
plt.figure()
plt.imshow(Image, cmap='gray')
plt.title('劃分的區(qū)域')
plt.xlabel('x')
plt.ylabel('y')
for contour in contours:
contour = contour.squeeze()
plt.plot(contour[:, 1], contour[:, 0], 'r', linewidth=2)
plt.show()
到了這里,關(guān)于(數(shù)字圖像處理MATLAB+Python)第十章圖像分割-第一、二節(jié):閾值分割和邊界分割的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!