从图像

时间:2015-07-08 20:31:07

标签: matlab image-processing

我有这张图片 - enter image description here

我想删除这些标有黄色圆圈的点 - enter image description here

所以,基本上我想删除所有那些几乎等距的点,几乎在任何给定的两点之间的同一条线上。

这就是我所尝试过的。我找到了任意两点之间的等式,并删除了那条线上的所有点。这就是我试过的 -

clc;
I=imread('untitled.png');
imshow(I);
I=im2bw(I);

L = bwlabel(I,8) ;  %Calculating connected components
mx=max(max(L));

for i=1:mx
    [r1,c1] = find(L==i);

    x1=mean(c1);
    y1=mean(r1);
    for j=1:mx
        if i~=j
            [r2,c2] = find(L==j);
            x2=mean(c2);
            y2=mean(r2);
            slope=(y2-y1)./(x2-x1);
            for k=1:mx
                [r,c] = find(L==k);
                rc = [r,c];                
                x3=mean(c);
                y3=mean(r);
                temp=((y3-y2)-(slope).*(x3-x2));
                if k~=i & k~=j
                   if temp >=-0.5 & temp <=0.5
                       for l=1:r
                           for m=1:c
                               I(l,m)=0;
                           end
                       end
                   end
                end
            end
        end
    end
end
figure,imshow(I);

但是在这里,它将删除所有位于线上的点而不仅仅是等距点。此外,时间复杂度为O(N ^ 5),因此该算法即使对于小值也不会起作用。我甚至可以如果输入图像耗费太多时间,请不要检查上面的输入图像代码。那么,有什么方法可以做到这一点吗?

2 个答案:

答案 0 :(得分:0)

不只是你的代码是O(n ^ 5),而且find命令特别慢。

我认为您可以在O(n ^ 3)中轻松完成此操作,只需最少使用find命令。

这看起来像是:

1)生成Nx2点阵列,将图像缩小为一系列数据点。

nPoints = max(L(:));
points = zeros(nPoints, 2);
for ix = 1:nPoints
    [r1,c1] = find(L==ix);
    points(ix,:) = [r1,c1];
end

那应该非常快。

2)现在,对于每个点,检查它是否几乎在任何两个其他点之间。

maskRemove = false(nPoints,1);
for ixPoint = 1:nPoints
    for ixEndA = 1:nPoints
        for ixEndB = 1:(ixEndA-1)  %We don't need to check both directions
            rcCheck = points(ixPoint,:);
            rcEndA   = points(ixEndA ,:);
            rcEndB   = points(ixEndB ,:);

            %We want to see if the "check" point is near the average 
            %of the endpoints
            meanOfEnds = mean([rcEndA; rcEndB], 2);  

            %This is a MAX norm, you can use a circular distance 
            %check if you want.
            distanceFromMean = max(abs(meanOfEnds - rcCheck ) );

            %Mark the result in the results mask
            maskRemove(ixPoint)= distanceFromMean  < thresholdValue;
        end
    end
end

%Now, "maskRemove" should be a logical TRUE for any point that needs 
%to be removed.

答案 1 :(得分:0)

我认为这样做的好方法就是这样做。它是〜O(N),圆圈数

>> TimingFunction(1000, 2)
Elapsed time is 0.103834 seconds.
>> TimingFunction(1000, 4)
Elapsed time is 0.179529 seconds.
>> TimingFunction(1000, 8)
Elapsed time is 0.270225 seconds.
>> TimingFunction(1000, 16)
Elapsed time is 0.601423 seconds.
>> TimingFunction(1000, 32)
Elapsed time is 1.070139 seconds.

和O(N ^ 2)的图像大小(我使用正方形来测试)

>> TimingFunction(500, 16)
Elapsed time is 0.139831 seconds.
>> TimingFunction(1000, 16)
Elapsed time is 0.531034 seconds.
>> TimingFunction(2000, 16)
Elapsed time is 1.974798 seconds.

功能是:

function TimingFunction(SquareSize, NumberCircles)
%This is generating a sample "image"
I = ones(SquareSize);

%This is generating sample circles
X = randi(round(0.9*size(I, 2)), NumberCircles, 1);
Y = randi(round(0.9*size(I, 1)), NumberCircles, 1);
R = randi(round(min(size(I)) / 20), NumberCircles, 1);

%this is timing
tic
Ip = circleErase(I, X, Y, R);
toc

%Just to allow for visualization
surf(Ip)

end

%this is the actual code
function I = circleErase(I, X, Y, R)
%I is the image, if it's RGB rather than a matrix you will need to modify the last line slightly
%X is a vector of the x coordinates of the center of the circle
%Y is a vector of the y coordinates of the center of the circle
%R is a vector of the circles radii

%Assign x,y coordinates to each point
[GridX, GridY] = meshgrid(1:size(I, 2), 1:size(I, 1));

%Want points within 1 unit
Within = 1;

%Finds the points within one unit for each circle edge
closeEnough = arrayfun(@(x, y, r) abs(r - sqrt((x - GridX).^2 + (y - GridY).^2)) <= Within, X, Y, R, 'uni', 0);

%Changes from a cell array to a 3D array (using:
%   http://www.mathworks.com/matlabcentral/answers/35766-cell-array-into-3d-matrix)
%   then finds if points intersect with any of the circles
eraseIt = any(permute(reshape(cell2mat(closeEnough).',size(closeEnough{1}, 1),size(closeEnough{1},2),[]),[3 2 1]), 1);

%Then erases it
I(eraseIt) = 0;
end