图像分割——超像素(Superpixels)分割(Matlab)
生活随笔
收集整理的這篇文章主要介紹了
图像分割——超像素(Superpixels)分割(Matlab)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原圖與分割結果
? ? ? ? ??
主程序:
clc; clear all; close all; %用Superpixels算法對圖像進行分割 I=imread('D:\Gray Files\lena.jpg');%提取各顏色分量 B = double(I(:,:,3)); G = double(I(:,:,2)); R = double(I(:,:,1)); %種子點數量 num_seeds=200; %顏色與空間距離相關性 compactness=40; %計算超像素 labels=SLIC(num_seeds,compactness,R,G,B); %邊界線檢測 points=FindAroundLine(labels); %將邊界點設置為白色 while ~isempty(points)p=points(1,:);R(p(1),p(2))=255;G(p(1),p(2))=255; B(p(1),p(2))=255; points(1,:)=[]; end I(:,:,1)=R; I(:,:,2)=G; I(:,:,3)=B; imshow(I) % imwrite(I,'D:\Gray Files\10-52-Superpixel.tif','tif');超像素計算函數,SLIC如下:
%SLIC算法 %輸入參數: %I 為RGB圖像 %numseeds 種子點數量 %compactness 顏色與空間距離相關性 function [labels]=SLIC(num_seeds,compactness,R,G,B)[M,N]=size(R);%圖像總的像素數量n_tp=M*N;%步進的間隔,補0.5的誤差step=floor(sqrt(n_tp/num_seeds)+0.5); %計算種子點及數量[seeds,num_seeds]=GetSeeds(step,M,N,R,G,B);%計算超像素集合[seeds,labels]=SuperpixelSLIC(seeds,num_seeds,M,N,step,compactness,R,G,B);%強制類別連通k=floor(M*N/(step*step));labels=EnforceLabelConnectivity(labels,M,N,num_seeds,k); end %%調整圖像的種子點 %輸入參數: % step 步進間隔 % M 圖像的高度 % N 圖像的寬度 % R 顏色R分量 % G 顏色G分量 % B 顏色B分量 function [seeds,num_seeds]=GetSeeds(step,M,N,R,G,B)%種子點集合,分別為R,G,B,x,yseeds=zeros(1,5);%注意,這里的x,y與實際相反%計算坐標誤差xstrips=floor(M/step);ystrips=floor(N/step);%計算x坐標誤差xerr=floor(M-step*xstrips);if xerr<0xstrips=xstrips-1;xerr=floor(M-step*xstrips);end%計算y坐標誤差yerr=floor(N-step*ystrips);if yerr<0ystrips=ystrips-1;yerr=floor(N-step*ystrips);end xerrperstrip=xerr/xstrips;yerrperstrip=yerr/ystrips;xoff=floor(step/2);yoff=floor(step/2);%種子點計數器n=1;%實際的種子點數量num_seeds=xstrips*ystrips;for x=0:xstrips-1xe=floor(x*xerrperstrip);for y=0:ystrips-1ye=floor(y*yerrperstrip);%種子點的y坐標seedy=floor(y*step+yoff+ye);%種子點的x坐標seedx=floor(x*step+xoff+xe);seeds(n,1)=R(seedx,seedy);seeds(n,2)=G(seedx,seedy);seeds(n,3)=B(seedx,seedy);seeds(n,4)=seedx;seeds(n,5)=seedy;n=n+1;endend end %計算超像素集合 function [seeds,labels]=SuperpixelSLIC(seeds,num_seeds,M,N,step,compactness,R,G,B)%每個像素的距離設定,正無窮大d=Inf(M,N);%圖像像素點的類別矩陣labels=-1*ones(M,N);%偏移量offset=step;if step<8offset=step*1.5;endinvwt=1/(step/compactness)^2;%迭代計算中心種子點for itr=1:10for i=1:num_seeds%計算x的最小區間x_min=seeds(i,4)-offset;if x_min<1;x_min=1;end%計算x的最大區間x_max=seeds(i,4)+offset;if x_max>Mx_max=M;end%計算y的最小區間y_min=seeds(i,5)-offset;if y_min<1;y_min=1;end%計算y的最大區間y_max=seeds(i,5)+offset;if y_max>Ny_max=N;end %計算2step*2step范圍內的混合距離for x=x_min:x_maxfor y=y_min:y_max%這里計算平方,不開方,只是為了比較大小,節省計算開銷d_color=(seeds(i,1)-R(x,y))^2+(seeds(i,2)-G(x,y))^2+(seeds(i,3)-B(x,y))^2;d_space=(seeds(i,4)-x)^2+(seeds(i,5)-y)^2;D=d_color+d_space*invwt;%更為精確的計算% D=sqrt(d_color)+sqrt(d_space*invwt);if D<d(x,y)d(x,y)=D;labels(x,y)=i;endendend%重新計算該種子點的中心點endend%創建新的種子點集合,分別為R,G,B,x,y,第6列為簇的大小new_seeds=zeros(num_seeds,6);for x=1:Mfor y=1:N%圖像x,y所在位置的類別號label=labels(x,y);%將當前類別號在x,y點的R,G,B,x,y值進行累加new_seeds(label,1)=new_seeds(label,1)+R(x,y);new_seeds(label,2)=new_seeds(label,2)+G(x,y);new_seeds(label,3)=new_seeds(label,3)+B(x,y);new_seeds(label,4)=new_seeds(label,4)+x; new_seeds(label,5)=new_seeds(label,5)+y;new_seeds(label,6)=new_seeds(label,6)+1;endend%計算新的種子點for i=1:num_seedsseeds(i,:)=new_seeds(i,1:5)/new_seeds(i,6);end end %強制類別連通 function [labels,numlabels]=EnforceLabelConnectivity(labels,M,N,num_seeds,k)%nlabels=-1*ones(M,N);numlabels=num_seeds;sz=M*N;supsz=floor(sz/k);label=1; % oindex=1;%鄰接類別adjlabel=1;for x=1:Mfor y=1:Nif nlabels(x,y)<0%將點x,y類別號賦值nlabels(x,y)=label;%查找x,y周圍是否有鄰接類別if x-1>=1 && nlabels(x-1,y)>=1adjlabel=nlabels(x-1,y);elseif x+1<=M && nlabels(x+1,y)>=1adjlabel=nlabels(x+1,y);elseif y-1>=1 && nlabels(x,y-1)>=1adjlabel=nlabels(x,y-1);elseif y+1<=N && nlabels(x,y+1)>=1adjlabel=nlabels(x,y+1);end%查找所有與點x,y 4連通的點%連通點(簇)計數器count=1;%連通點堆棧points=[x,y];ps_back=[x,y];while ~isempty(points)%取出堆棧中第一個點,并以此為中心開始搜索類別相同的點p=points(1,:);%上點if p(1)-1>=1if nlabels(p(1)-1,p(2))<0 && labels(p(1)-1,p(2))==labels(x,y)points=cat(1,points,[p(1)-1,p(2)]);ps_back=cat(1,ps_back,[p(1)-1,p(2)]);nlabels(p(1)-1,p(2))=label;count=count+1;endend%下點if p(1)+1<=Mif nlabels(p(1)+1,p(2))<0 && labels(p(1)+1,p(2))==labels(x,y)points=cat(1,points,[p(1)+1,p(2)]);ps_back=cat(1,ps_back,[p(1)+1,p(2)]);nlabels(p(1)+1,p(2))=label;count=count+1;endend %左點if p(2)-1>=1if nlabels(p(1),p(2)-1)<0 && labels(p(1),p(2)-1)==labels(x,y)points=cat(1,points,[p(1),p(2)-1]);ps_back=cat(1,ps_back,[p(1),p(2)-1]);nlabels(p(1),p(2)-1)=label;count=count+1;endend%右點if p(2)+1<=Nif nlabels(p(1),p(2)+1)<0 && labels(p(1),p(2)+1)==labels(x,y)points=cat(1,points,[p(1),p(2)+1]);ps_back=cat(1,ps_back,[p(1),p(2)+1]);nlabels(p(1),p(2)+1)=label;count=count+1;endend points(1,:)=[];end%如果簇的規模小于閾值,則將其合并到鄰接類別中if count<=supsz/4while ~isempty(ps_back)p=ps_back(1,:);nlabels(p(1),p(2))=adjlabel;ps_back(1,:)=[];end%合并類別時,標號需要減1label=label-1;end%類別標簽加1label=label+1;endendendnumlabels=label;labels=nlabels; end邊界線檢測函數,FindAroundLine如下:
%查找邊界線 function [points]=FindAroundLine(labels)[M,N]=size(labels);%初始化邊界點矩陣points=zeros(1,2);%八連通點dx=[-1, -1, 0, 1, 1, 1, 0, -1];dy=[0, -1, -1, -1, 0, 1, 1, 1];%計數器n=1;%尋找超像素的邊界線,用八連通性來判斷for x=1:Mfor y=1:N%周圍點類別不同計數器np=0;for i=1:length(dx)xx=x+dx(i);yy=y+dy(i);if (xx>=1 && xx<=M) && (yy>=1 && yy<=N)if labels(xx,yy)~=labels(x,y)np=np+1;endendendif np>1points(n,:)=[x,y];n=n+1;endendend end?
總結
以上是生活随笔為你收集整理的图像分割——超像素(Superpixels)分割(Matlab)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有效解决0x0000011b共享打印机无
- 下一篇: php处理跨域访问