霍夫变换来检测和删除行

4 matlab image-processing

我想使用霍夫变换来检测图像中的线条,但不想绘制线条,而是要删除原始图像中检测到的每条线条。

image=imread('image.jpg');
image = im2bw(image);
BW=edge(image,'canny');
imshow(BW);
figure,imshow(BW);
[H,T,R] = hough(BW);
P  = houghpeaks(H,100,'threshold',ceil(0.3*max(H(:))));
lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
Run Code Online (Sandbox Code Playgroud)

现在,在此之后,我已经掌握了所有要求。但是我想从原始图像中删除所有这些行,并像以前一样保留其余图像。有什么办法可以做到这一点?

编辑我正在上传图像,我想删除所有线条并保留圆形部分,这只是一个示例图像,基本上我的目标是删除线段并保留其余图像 在此处输入图片说明

kku*_*lla 5

您遇到的问题是您的线条粗于一个像素。霍夫变换中的线条似乎只有一个像素粗,这无济于事。

我建议您首先删除从Hough变换中获得的行。这样可以将曲棍球场的任何部分划分为易于处理的段。

然后用标记每个细分bwlabel。对于每个对象,找到端点并在端点之间拟合一条线。如果线和对象的共同像素多于某个阈值,那么我们说该对象是线,则将其从图像中删除。

您可能需要尝试霍夫变换的阈值。

这种技术虽然有一些缺陷。它将删除一个已填充的正方形,矩形或圆形,但是您没有任何一个,因此您应该可以。

结果

在此处输入图片说明在此处输入图片说明


说明

这是我修改的代码。我删除了渐变,因为它更容易处理实体对象。渐变产生非常细的线条。我还处理补码图像,因为bw函数使用1作为补偿,而不是原始图像中的0。

org_image_bw=im2bw(double(imread('http://i.stack.imgur.com/hcphc.png')));
image = imcomplement(org_image_bw);
[H,T,R] = hough(image);
P  = houghpeaks(H,100,'threshold',ceil(0.27*max(H(:))));
lines = houghlines(image,T,R,P,'FillGap',5,'MinLength',7);
Run Code Online (Sandbox Code Playgroud)

循环浏览已有的行并将其删除

processed_image = image;
for k = 1:length(lines)
   xy = [lines(k).point1; lines(k).point2];

    % // Use the question of a line y = kx + m to calulate x,y

    % // Calculate the maximum number of elements in a line
   numOfElems = max(max(xy(:,1))-min(xy(:,1)),max(xy(:,2))-min(xy(:,2)) ) ;

   % // Cater for the special case where the equation of a line is
   % // undefined, i.e. there is only one x value.
   % // We use linspace rather than the colon operator because we want
   % // x and y to have the same length and be evenly spaced.
   if (diff(xy(:,1)) == 0)           
       y = round(linspace(min(xy(:,2)),max(xy(:,2)),numOfElems));
       x = round(linspace(min(xy(:,1)),max(xy(:,1)),numOfElems));      
   else

       k = diff(xy(:,2)) ./ diff(xy(:,1)); % // the slope
       m = xy(1,2) - k.*xy(1,1); % // The crossing of the y-axis

       x = round(linspace(min(xy(:,1)), max(xy(:,1)), numOfElems));
       y = round(k.*x + m); % // the equation of a line
   end

   processed_image(y,x) = 0; % // delete the line
end
Run Code Online (Sandbox Code Playgroud)

这是我们删除检测到的行后图像的外观。请注意,原来的冰球场又被分为多个对象。

在此处输入图片说明

标记剩余的对象

L = bwlabel(processed_image);
Run Code Online (Sandbox Code Playgroud)

遍历每个对象并找到终点。然后在上面装一条线。假设80%的拟合线覆盖了对象,那么它就是一条线。

拟合线可能看起来像这样。蓝色斜线表示拟合线,并且覆盖了大部分对象(白色区域)。因此,我们说对象是一条线。

在此处输入图片说明

% // Set the threshold
th = 0.8;

% // Loop through the objects
for objNr=1:max(L(:))
   [objy, objx] = find(L==objNr);

   % Find the end points
   endpoints = [min(objx) min(objy) ...
       ;max(objx) max(objy)];

   % Fit a line to it. y = kx + m
   numOfElems = max(max(endpoints(:,1))-min(endpoints(:,1)),max(endpoints(:,2))-min(endpoints(:,2)) ) ;

   % // Cater for the special case where the equation of a line is
   % // undefined, i.e. there is only one x value
   if (diff(endpoints(:,1)) == 0)           
       y = round(linspace(min(endpoints(:,2)),max(endpoints(:,2)),numOfElems));
       x = round(linspace(min(endpoints(:,1)),max(endpoints(:,1)),numOfElems));      
   else
       k = diff(endpoints(:,2)) ./ diff(endpoints(:,1)); % the slope
       m = endpoints(1,2) - k.*endpoints(1,1); % The crossing of the y-axis           
       x = round(linspace(min(endpoints(:,1)), max(endpoints(:,1)), numOfElems));

       y = round(k.*x + m);
       % // Set any out of boundary items to the boundary
       y(y>size(L,1)) = size(L,1);
   end

   % // Convert x and y to an index for easy comparison with the image
   % // We sort them so that we are comparing the same pixels
   fittedInd = sort(sub2ind(size(L),y,x)).';
   objInd = sort(sub2ind(size(L),objy,objx));

   % // Calculate the similarity. Intersect returns unique entities so we
   % // use unique on fittedInd
   fitrate = numel(intersect(fittedInd,objInd)) ./ numel(unique(fittedInd));
   if (fitrate >= th)
       L(objInd) = 0;
       processed_image(objInd) = 0;
       % // figure(1),imshow(processed_image)
   end       
end
Run Code Online (Sandbox Code Playgroud)

显示结果

figure,imshow(image);title('Original');
figure,imshow(processed_image);title('Processed image');
Run Code Online (Sandbox Code Playgroud)

完整的例子

org_image_bw=im2bw(double(imread('http://i.stack.imgur.com/hcphc.png')));
image = imcomplement(org_image_bw);

[H,T,R] = hough(image);
P  = houghpeaks(H,100,'threshold',ceil(0.27*max(H(:))));
lines = houghlines(image,T,R,P,'FillGap',5,'MinLength',7);

processed_image = image;
    for k = 1:length(lines)
       xy = [lines(k).point1; lines(k).point2];

        % // Use the question of a line y = kx + m to calulate x,y

        %Calculate the maximum number of elements in a line
        numOfElems = max(max(xy(:,1))-min(xy(:,1)),max(xy(:,2))-min(xy(:,2)) ) ;

       % // Cater for the special case where the equation of a line is
       % // undefined, i.e. there is only one x value.
       % // We use linspace rather than the colon operator because we want
       % // x and y to have the same length and be evenly spaced.
       if (diff(xy(:,1)) == 0)           
           y = round(linspace(min(xy(:,2)),max(xy(:,2)),numOfElems));
           x = round(linspace(min(xy(:,1)),max(xy(:,1)),numOfElems));      
       else

           k = diff(xy(:,2)) ./ diff(xy(:,1)); % the slope
           m = xy(1,2) - k.*xy(1,1); % The crossing of the y-axis

           x = round(linspace(min(xy(:,1)), max(xy(:,1)), numOfElems));
           y = round(k.*x + m); % // the equation of a line
       end

       processed_image(y,x) = 0; % // delete the line
    end


    % // Label the remaining objects
    L = bwlabel(processed_image);

    % // Run through each object and find the end points.
    % // Then fit a line to it. If, let's say 80% the fitted line covers
    % // the object, then it is a line.

    % // Set the threshold
    th = 0.8;

    % // Loop through the objects
    for objNr=1:max(L(:))
       [objy, objx] = find(L==objNr);

       % Find the end points
       endpoints = [min(objx) min(objy) ...
           ;max(objx) max(objy)];

       % Fit a line to it. y = kx + m
       numOfElems = max(max(endpoints(:,1))-min(endpoints(:,1)),max(endpoints(:,2))-min(endpoints(:,2)) ) ;

       % Cater for the special case where the equation of a line is
       % undefined, i.e. there is only one x value
       if (diff(endpoints(:,1)) == 0)           
           y = round(linspace(min(endpoints(:,2)),max(endpoints(:,2)),numOfElems));
           x = round(linspace(min(endpoints(:,1)),max(endpoints(:,1)),numOfElems));      
       else
           k = diff(endpoints(:,2)) ./ diff(endpoints(:,1)); % the slope
           m = endpoints(1,2) - k.*endpoints(1,1); % The crossing of the y-axis           
           x = round(linspace(min(endpoints(:,1)), max(endpoints(:,1)), numOfElems));

           y = round(k.*x + m);
           % // Set any out of boundary items to the boundary
           y(y>size(L,1)) = size(L,1);
       end

       % // Convert x and y to an index for easy comparison with the image
       % // We sort them so that we are comparing the same pixels
       fittedInd = sort(sub2ind(size(L),y,x)).';
       objInd = sort(sub2ind(size(L),objy,objx));

       % Calculate the similarity. Intersect returns unique entities so we
       % use unique on fittedInd
       fitrate = numel(intersect(fittedInd,objInd)) ./ numel(unique(fittedInd));
       if (fitrate >= th)
           L(objInd) = 0;
           processed_image(objInd) = 0;
           % // figure(1),imshow(processed_image)
       end       
    end

   % // Display the result 
   figure,imshow(image);title('Original');
   figure,imshow(processed_image);title('Processed image');
Run Code Online (Sandbox Code Playgroud)