我有这张图片 -
我想删除这些标有黄色圆圈的点 -
所以,基本上我想删除所有那些几乎等距的点,几乎在任何给定的两点之间的同一条线上。
这就是我所尝试过的。我找到了任意两点之间的等式,并删除了那条线上的所有点。这就是我试过的 -
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),因此该算法即使对于小值也不会起作用。我甚至可以如果输入图像耗费太多时间,请不要检查上面的输入图像代码。那么,有什么方法可以做到这一点吗?
答案 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