在MATLAB中查找图像的边缘和拐角值

时间:2010-04-09 14:53:23

标签: matlab image-processing

我正在追踪图像的轮廓并将其绘制到DXF文件中。我想使用bwboundaries函数查找图像边缘的坐标,使用cornermetric函数找到角坐标,然后删除任何不是角点的边坐标。

我需要做的重要事情是保持从bwboundaries获得的角元素的顺序,以便该部分正确地跟踪。我所拥有的DXF函数,从坐标绘制,在彼此相邻的坐标之间绘制线条,因此线条必须“围绕”该部分而不是直接在角点之间绘制。

我这样做的原因是因为这种方式获得的坐标较少,因此修改DXF文件更容易(因为操作的点数较少)。

我到目前为止的代码是:

%# Shape to be traced
bw = zeros(200);

bw(20:40,20:180) = 1;
bw(20:180,90:110) = 1;
bw(140:180,20:185) = 1;

%# Boundary finding section
[Boundary] = bwboundaries(bw); %Traces the boundary of each section.

figure, imshow(bw); hold on;
colors=['b' 'g' 'r' 'c' 'm' 'y'];

for k = 1:length(Boundary)
   perim = Boundary{k}; %Obtains perimeter coordinates (as a 2D matrix) from the cell array.
   cidx = mod(k,length(colors))+1;% Obtains colours for the plot
   plot(perim(:,2), perim(:,1),...
          colors(cidx),'LineWidth',2);
end

Coordmat = cell2mat(Boundary) %Converts the traced regions to a matrix.

X = Coordmat(:,1)
Y = Coordmat(:,2) % This gives the edge coordinates in matrix form.

%% Corner finding section (from Jonas' answer to a previous question.

%# Get corners
cornerProbability = cornermetric(bw);

cornerIdx = find(cornerProbability==max(cornerProbability(:)));

%# Label the image. bwlabel puts 1 for the first feature, 2 for the second, etc.
%# Since concave corners are placed just outside the feature, grow the features.
%# A little before labeling
bw2 = imdilate(bw,ones(3));
labeledImage = bwlabel(bw2);

%# Read the feature number associated with the corner.
cornerLabels = labeledImage(cornerIdx);

%# Find all corners that are associated with feature 1.
corners_1 = cornerIdx(cornerLabels==1)

[Xcorners, Ycorners] = ind2sub(200,corners_1) % Convert subscripts

我的代码是,为最终的x坐标(位于边缘和拐角处)提供矩阵Xfin

Xfin = zeros(length(X),1)

for i = Xcorners
    XFin(i) = Xcorners
    if i~= Xcorners
        XFin(i) = []
    end
end

但是,这不能正常工作,因为解决方案中的值按顺序排序,并且每个值中只有一个保留。正如我所说,我希望角元素的顺序与从bwboundaries获得的顺序相同,以使图像能够正确地跟踪。

(这个问题链接到我在这里提出的另外两个问题。)

1 个答案:

答案 0 :(得分:0)

这是一段代码,可以完成您想要做的事情。对于每个角,它找到最近的边界像素,并记住坐标的索引。

为了使其工作,你必须将边界作为4连接边界(即写Boundary = bwboundaries(bw,4);。如果由于某种原因不能使用4连接边界,则角提取变得有点复杂,因为在这种情况下,凹角不是边界的一部分(注意,当你看到绿线时,8个连接的边界,内角是'圆的')。

修改

这是适合我的完整代码

%# Shape to be traced
% bw = zeros(200);
% 
% bw(20:40,20:180) = 1;
% bw(20:180,90:110) = 1;
% bw(140:180,20:185) = 1;

%# alternative shape
bw = zeros(100); 
bw(40:80,40:80) = 1;


%# Boundary Finding Section
[Boundary] = bwboundaries(bw,4); %Traces the boundary of each section

figure, imshow(bw); hold on;
colors=['b' 'g' 'r' 'c' 'm' 'y'];

for k=1:length(Boundary)
 perim = Boundary{k}; %Obtains perimeter coordinates (as a 2D matrix) from the cell array
 cidx = mod(k,length(colors))+1;% Obtains colours for the plot
 plot(perim(:,2), perim(:,1),...
        colors(cidx),'LineWidth',2);

end

Coordmat = cell2mat(Boundary) %Converts the traced regions to a matrix

X = Coordmat(:,1)
Y = Coordmat(:,2) % This gives the edge coordinates in matrix form



%% Corner Finding Section (from Jonas' answer to a previous question
%# get corners
cornerProbability = cornermetric(bw);


cornerIdx = find(cornerProbability==max(cornerProbability(:)));

%# Label the image. bwlabel puts 1 for the first feature, 2 for the second, etc.
%# Since concave corners are placed just outside the feature, grow the features 
%# a little before labeling
bw2 = imdilate(bw,ones(3));
labeledImage = bwlabel(bw2);

%# read the feature number associated with the corner
cornerLabels = labeledImage(cornerIdx);

%# find all corners that are associated with feature 1
corners_1 = cornerIdx(cornerLabels==1)

[Xcorners, Ycorners] = ind2sub(size(bw),corners_1) % Convert subscripts

%% Here comes the new part

%# count corners
nCorners = length(Xcorners);
%# corner2boundaryIdx will contain the index of the boundary pixel
%# corresponding to a given corner
corner2boundaryIdx = zeros(nCorners,1);

%# remove last entry of Coordmat, because the first and the last pixel are
%# repeated
Coordmat(end,:) = [];

%# loop since we need to tread convex and concave corners differently
for i = 1:nCorners
    %# find distance of corner to boundary
    dist = sqrt((Coordmat(:,1)-Xcorners(i)).^2 + (Coordmat(:,2)-Ycorners(i)).^2);
    %# find index of closest boundary pixel. Use find
    %# instead of 2nd output of min, because we need to know how
    %# many closest indices there are in order to distinguish
    %# concave and convex corners. Convex corners are directly
    %# on the boundary, thus there is one minimum distance (0).
    %# Concave corners are just outside the boundary, thus, there
    %# are two minimum distances (1)
    minDistIdx = find(dist == min(dist));

    %# count how many minimum distances we have
    switch length(minDistIdx)
        case 1
            %# convex corners. Everything is simple
            corner2boundaryIdx(i) = minDistIdx;
        case 2
            %# concave corners. Take the index right in the middle. Note
            %# for this to work, you need to have 4-connected boundaries,
            %# otherwise, the concave corner is not part of the boundary
            %# becasue the boundary jumps along the diagonal. 
            %# If you have to use 8-connected boundaries, the 'good'
            %# difference is 1, and you need to calculate the coordinate of
            %# the concave corner from the "corner" and the two adjacent 
            %# boundary pixels.
            if diff(minDistIdx) == 2
            corner2boundaryIdx(i) = mean(minDistIdx);
            else
                error('boundary starts/stops at concave corner - case not handled yet')
            end
        otherwise
            error('%i minDist found for corner # %i',length(minDistIdx),i)
    end
end

%# All that is left to do is read the boundary pixel coordinates in the 
%# right order
corner2boundaryIdx = sort(corner2boundaryIdx);
orderedCorners = Coordmat(corner2boundaryIdx,:);

%# plot corner numbers for confirmation
hold on
for i = 1:nCorners
    text(orderedCorners(i,2),orderedCorners(i,1),num2str(i),'Color','r')
end