matlab实现bwlabel函数

大家都知道bwlabel可以将二值图中的连通区域划分并标记出来

那么如何实现bwlabel算法呢

1、一行一行的遍历图片,寻找该行的连通区域,计作run区域,并用记录其起止位置和行号

2、看当前行的run区域是否与上一行的连通

- 不连通:给标新号

- 只与一个连通:将号替换成连通的那个号

- 与多个连通:都要换成同一个编号

比如cell{1}和cell{2}连通,则让cell{2} = [cell{2} cell{1}],再将cell{1}滞空

若要删掉不连续的标号,就删掉为空的cell即可

注意考虑边界和多个run区域与前一行连通

3、根据标号给图片赋值


具体代码如下,不过以下代码感觉还可以继续优化,,思路大致没问题,之后有机会再改改(不过我感觉我也懒得改了哈哈哈哈哈哈)

img = imread('rice.png');
[rows,cols,colors] = size(img);
imgBinary=imbinarize(img);

%bwlabel遍历每一行
%确定每一行的连通区域run,记录每个run区域所在行标和起止点位置
%sc = 1:count; %开始列标
%ec = 1:count; %结束列标
r = 1:rows;   %所在行标
pre = 0;
idx = 1;
for m = 1 : rows
    for n = 1 : cols
        if(imgBinary(m,n) ~= pre)
            if(pre == 0)
                sc(idx) = n;
                r(idx) = m; 
                pre = 1;
            else
                ec(idx) = n - 1;
                idx = idx + 1;
                pre = 0;
            end
            
        end
        if(n == cols && pre ==1)
            ec(idx) = n;
            idx = idx + 1;
            pre = 0;
        end
    end
    
end
count = idx - 1;

%判断下一行和上一行的是不是在八连通区域
cur_row = r(1); %当前有run的行
first_run_on_prev_row = -1;  %前一行的第一个run
last_run_on_prev_row = -1;   %前一行的最后一个run
first_run_on_this_row = 1;   %当前行的第一个run
equal_idx = 1;
labels = {}; 
equal_i = zeros(1,count);
equal_j = zeros(1,count);
offset = 1;
next_label = 1;
for i = 1 : count
   labels{i} = i; 
end
for k = 1 : count
    %上一行有run考虑连通
    if(r(k) == cur_row + 1)
        first_run_on_prev_row = first_run_on_this_row;
        first_run_on_this_row = k;
        last_run_on_prev_row = k - 1;
        cur_row = r(k);
    %上一行无run 分配新标签  给这一行的第一个run分配标签为k,将该行置为当前行
    else
        if(r(k) > cur_row + 1)
            first_run_on_prev_row = -1;
            last_run_on_prev_row = -1;
            first_run_on_this_row = k;  
            cur_row = r(k);
        end
    end
    if(first_run_on_prev_row >= 0)
        p = first_run_on_prev_row;
        %遍历前一行的所有run区域,看是否有区域和该行run区域连通
        %判断八连通就是判断前一排首位在下一排末位之前,前一排末位在后一排首位之后
        while(p <= last_run_on_prev_row && sc(p) <= (ec(k) + offset))
            if(sc(k) <= ec(p) + offset) 
                if(~isempty(labels{p}))
                    labels{k} = [labels{k} labels{p}];
                    labels{p} = [];
                else
                    for pk = p+1 : k-1
                        if(ismember(p,labels{pk}))
                            labels{k} = [labels{k} labels{pk}];
                            labels{pk} = []; 
                        end
                    end
                end
            end
            p = p + 1;
        end
    end
end


%删掉空的labels
labels(cellfun(@isempty,labels))=[];
imgBinary2 = zeros(rows,cols);
for x = 1 : length(labels)
    for y = 1 : length(labels{x})
        for z = sc(labels{x}(y)) : ec(labels{x}(y))
             imgBinary2(r(labels{x}(y)),z) = x;
        end
    end
end

figure;
imshow(imgBinary2);

imgBinary1=imbinarize(img);
[re,num] = bwlabel(imgBinary1);
figure;
imshow(re);

你可能感兴趣的:(图像处理)