超像素分割算法SLIC的matlab实现
生活随笔
收集整理的這篇文章主要介紹了
超像素分割算法SLIC的matlab实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
SLIC是一種基于網格化KMeans聚類的超像素分割算法,其計算復雜度為O(N),其中N為像素點個數。SLIC的原理比較簡單精致,具體的原理我這里就不介紹了,推薦大家自己去讀原始論文加深理解(但我以為看下面這個算法流程圖就足夠理解原理了)。SLIC的算法流程如下:
如所有其他聚類算法一樣,SLIC不能保證連通性,所以需要后處理將旁生的連通域合并到鄰近的主連通域上,但是論文中并未給出具體的后處理方法。我給出的方法是按照輪廓接觸點個數最多原則合并連通域。由于每個聚類都有自己的“勢力范圍”,即每個標簽覆蓋的區域不會超過聚類時限定的范圍(一般是2S*2S大小,邊緣柵格的聚類例外),所以合并處理時只需要在該范圍內操作即可。
?下面給出本人實現的SLIC算法程序(控制色域與空域權重比例的系數wDs應設為函數形參,這里就不改了。注意!迭代中限定聚類的柵格是不變的!!!):
function Label=SLIC(img,s,errTh,wDs) % 基于KMeans的超像素分割 % img為輸入圖像,維度不限,最大值為255 % s x s為超像素尺寸 % errTh為控制迭代結束的聯合向量殘差上限 m=size(img,1); n=size(img,2);%% 計算柵格頂點與中心的坐標 h=floor(m/s); w=floor(n/s); rowR=floor((m-h*s)/2); %多余部分首尾均分 colR=floor((n-w*s)/2); rowStart=(rowR+1):s:(m-s+1); rowStart(1)=1; rowEnd=rowStart+s; rowEnd(1)=rowR+s; rowEnd(end)=m; colStart=(colR+1):s:(n-s+1); colStart(1)=1; colEnd=colStart+s; colEnd(1)=colR+s; colEnd(end)=n; rowC=floor((rowStart+rowEnd-1)/2); colC=floor((colStart+colEnd-1)/2); % 顯示劃分結果 temp=zeros(m,n); temp(rowStart,:)=1; temp(:,colStart)=1; for i=1:hfor j=1:wtemp(rowC(i),colC(j))=1;end end figure,imshow(temp); imwrite(temp,'柵格.bmp');%% 計算梯度圖像,使用sobel算子和歐式距離 img=double(img)/255; r=img(:,:,1); g=img(:,:,2); b=img(:,:,3); Y=0.299 * r + 0.587 * g + 0.114 * b;f1=fspecial('sobel'); f2=f1'; gx=imfilter(Y,f1); gy=imfilter(Y,f2); G=sqrt(gx.^2+gy.^2); %% 選擇柵格中心點3*3鄰域中梯度最小點作為起始點 rowC_std=repmat(rowC',[1,w]); colC_std=repmat(colC,[h,1]); rowC=rowC_std; colC=colC_std; for i=1:hfor j=1:wblock=G(rowC(i,j)-1:rowC(i,j)+1,colC(i,j)-1:colC(i,j)+1);[minVal,idxArr]=min(block(:));jOffset=floor((idxArr(1)+2)/3);iOffset=idxArr(1)-3*(jOffset-1);rowC(i,j)=rowC(i,j)+iOffset;colC(i,j)=colC(i,j)+jOffset;end end%% KMeans超像素分割 Label=zeros(m,n)-1; dis=Inf*ones(m,n); M=reshape(img,m*n,size(img,3)); %像素值重排 % 聯合色域值和空域值 colorC=zeros(h,w,size(img,3)); for i=1:hfor j=1:wcolorC(i,j,:)=img(rowC(i),colC(j),:);end end uniMat=cat(3,colorC,rowC,colC); uniMat=reshape(uniMat,h*w,size(img,3)+2); iter=1; while(1)uniMat_old=uniMat; % rowC_old=rowC; % colC_old=colC;for k=1:h*wc=floor((k-1)/h)+1;r=k-h*(c-1);rowCidx=rowC(r,c);colCidx=colC(r,c); %聚類中心坐標%聚類限定的柵格(中心點始終是原s x s柵格的中心點)rowStart=max(1,rowC_std(r,c)-s);rowEnd=min(m,rowC_std(r,c)+s-1);colStart=max(1,colC_std(r,c)-s);colEnd=min(n,colC_std(r,c)+s); % colorC=uniMat(k,1:size(img,3));colorC=M((colCidx-1)*m+rowCidx,:);for i=rowStart:rowEndfor j=colStart:colEndcolorCur=M((j-1)*m+i,:);dc=norm(colorC-colorCur);ds=norm([i-rowCidx,j-colCidx]);d=dc^2+wDs*(ds/s)^2;if d<dis(i,j)dis(i,j)=d;Label(i,j)=k;endendendend%顯示聚類結果temp=mod(Label,20)+1;figure;imagesc(label2rgb(temp-1,'jet','w','shuffle')) ;axis image ; axis off ;% 錄制gifF=getframe(gcf);I=frame2im(F);[I,map]=rgb2ind(I,256);if iter == 1imwrite(I,map,'test.gif','gif','Loopcount',inf,'DelayTime',0.2);elseimwrite(I,map,'test.gif','gif','WriteMode','append','DelayTime',0.2);enditer=iter+1;% 更新聚類中心colorC=zeros(h,w,size(img,3));for k=1:h*wnum=0;sumColor=zeros(1,size(img,3)); sumR=0;sumC=0;c=floor((k-1)/h)+1;r=k-h*(c-1);rowCidx=rowC_std(r,c);colCidx=colC_std(r,c);rowStart=max(1,rowCidx-s);rowEnd=min(m,rowCidx+s-1);colStart=max(1,colCidx-s);colEnd=min(n,colCidx+s);for row=rowStart:rowEndfor col=colStart:colEndif Label(row,col)==knum=num+1;sumR=sumR+row;sumC=sumC+col;color=reshape(img(row,col,:),1,size(img,3));sumColor=sumColor+color;endendendcolorC(r,c,:)=sumColor/num;rowC(r,c)=round(sumR/num);colC(r,c)=round(sumC/num);enduniMat=cat(3,colorC,rowC,colC);uniMat=reshape(uniMat,h*w,size(img,3)+2);diff=uniMat-uniMat_old;diff(:,1:2)=sqrt(wDs)*diff(:,1:2)/s;err=norm(diff)/sqrt(h*w);if err<errTh %殘差低于閾值,結束迭代break;end end%% 后處理, 按照邊界接觸點數最多原則分配小連通域的標簽 for k=1:h*wc=floor((k-1)/h)+1;r=k-h*(c-1);rowCidx=rowC_std(r,c);colCidx=colC_std(r,c);rowStart=max(1,rowCidx-s);rowEnd=min(m,rowCidx+s-1);colStart=max(1,colCidx-s);colEnd=min(n,colCidx+s);block=Label(rowStart:rowEnd,colStart:colEnd);block(block~=k)=0;block(block==k)=1;label=bwlabel(block);szlabel=max(label(:)); %標簽個數bh=rowEnd-rowStart+1;bw=colEnd-colStart+1; %block的寬高if szlabel<2 %無伴生連通域,略過continue;endlabelC=label(rowCidx-rowStart+1,colCidx-colStart+1); %主連通域的標記值top=max(1,rowStart-1);bottom=min(m,rowEnd+1);left=max(1,colStart-1);right=min(n,colEnd+1);for i=1:szlabel %遍歷連通域if i==labelC %主連通域不處理continue;endmarker=zeros(bottom-top+1,right-left+1); %生成一個外擴一圈的marker,標記哪些點已經被統計過接觸情況bw=label;bw(bw~=i)=0;bw(bw==i)=1; %當前連通域標記圖contourBW=bwperim(bw); %求取外輪廓% figure,imshow(contourBW);idxArr=find(double(contourBW)==1);labelArr=zeros(4*length(idxArr),1); %記錄輪廓點的4鄰域點標記值的向量num=0;for idx=1:size(idxArr) %遍歷輪廓點,統計其4鄰域點的標記值bc=floor((idxArr(idx)-1)/bh)+1;br=idxArr(idx)-bh*(bc-1); %輪廓點在block中的行列信息row=br+rowStart-1;col=bc+colStart-1; %輪廓點在大圖中的行列信息rc=[row-1,col;...row+1,col;...row,col-1;...row,col+1];for p=1:4row=rc(p,1);col=rc(p,2);if ~(row>=1 && row<=m && col>=1 && col<=n && Label(row,col)~=k)continue;endif marker(row-top+1,col-left+1)==0 %未被統計過marker(row-top+1,col-left+1)=1;num=num+1;labelArr(num)=Label(row,col);endendendlabelArr(find(labelArr==0))=[]; %去除零元素uniqueLabel=unique(labelArr);numArr=zeros(length(uniqueLabel),1);for p=1:length(uniqueLabel)idx=find(labelArr==uniqueLabel(p));numArr(p)=length(idx);endidx=find(numArr==max(numArr));maxnumLabel=uniqueLabel(idx(1)); %接觸最多的標簽for row=rowStart:rowEndfor col=colStart:colEndif bw(row-rowStart+1,col-colStart+1)==0continue;endLabel(row,col)=maxnumLabel;endendend end% 顯示連通域處理后聚類結果 temp=mod(Label,20)+1; figure; imagesc(label2rgb(temp-1,'jet','w','shuffle')) ; axis image ; axis off ;腳本文件:
close all;clc; I=imread('1.jpg'); figure,imshow(I);s=15; errTh=10^-2; wDs=0.5^2; Label=SLIC(I,s,errTh,wDs);%% 顯示輪廓 marker=zeros(size(Label)); [m,n]=size(Label); for i=1:mfor j=1:ntop=Label(max(1,i-1),j);bottom=Label(min(m,i+1),j);left=Label(i,max(1,j-1));right=Label(i,min(n,j+1));if ~(top==bottom && bottom==left && left==right)marker(i,j)=1;endend end figure,imshow(marker);I2=I; for i=1:mfor j=1:nif marker(i,j)==1I2(i,j,:)=0;endend end figure,imshow(I2);測試圖像:
柵格劃分結果:
聚類過程:
?聚類最終結果:
連通域合并后的結果:
原圖+輪廓線:
?
具體的我就不解釋了,自覺程序寫得還是很有條理的,讀者自己跟蹤程序運行進行理解吧。?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的超像素分割算法SLIC的matlab实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 德标螺纹规格对照表_(完整word版)德
- 下一篇: 每周分享第 34 期