霍夫变换以检测和删除线

Hough transform to detect and delete lines

我想使用 Hough 变换 来检测我的 image.But 中的线条,而不是绘制线条 我想删除在原始图像中检测到的每条线条。

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);

现在我已经掌握了所有台词。但我想从我的原始图像中删除所有这些行,保持图像的其余部分像以前一样。有什么办法可以做到这一点吗?

编辑我正在上传image.I想删除所有行并保留循环part.This只是一个例子image.Basically我的objective是删除线段,保留图像的其余部分

您遇到的问题是您的线条比一个像素粗。 霍夫变换的线条似乎只有一个像素粗, 那没用。

我建议您先删除从霍夫变换中得到的线条。 这将把曲棍球场分成几部分 这样会更容易处理。

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

您可能需要尝试使用 Hough 变换的阈值。

虽然这种技术有一些缺陷。它将删除一个填充的正方形, 矩形或圆形,但你没有这些,所以你应该没问题。

结果


说明

这是您的代码,我稍微修改了一下。我删除了渐变,因为它 使用实体对象更容易。渐变给出了非常细的线条。 我还处理补充图像,因为 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);

遍历你得到的行并删除它们

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

这是我们删除检测到的线条后的图像。请注意,原来的曲棍球场被分成了多个对象。

标记剩余的对象

L = bwlabel(processed_image);

运行遍历每个对象,找到终点。 然后给它配一条线。如果假设 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

显示结果

figure,imshow(image);title('Original');
figure,imshow(processed_image);title('Processed image');

完整示例

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');

您可以使用 J. E. Bresenham 的算法。下面是A.Wetzler实现的matlab function,我自己测试过

假设您将提供线的起点和终点,该算法将为您提供线所在位置的像素坐标,这已在上面的代码中 lines 中给出。

这是我使用的代码,它使用了上面引用的 matlab 函数:

%This is your code above ========
image=imread('hcphc.png');
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);
% =========

% Proposed solution:

% This will work for as many lines as you detected

for k=1:length(lines)

    % Call Bresenham's algorithm
    [x, y] = bresenham(lines(k).point1(1), lines(k).point1(2), ...
                       lines(k).point2(1), lines(k).point2(2));

    % This is where you replace the line, here I use 0, but you can use
    % whatever you want. However, note that if you use BW, you should only
    % replace with 0 or 1, because is a logical image. If you want to use 
    % the original image, well, you know what to do.
    BW(y, x) = 0;

    % And now watch the lines disapear!  (you can remove this line)
    imagesc(BW), drawnow; pause(1);
end

记住,先下载matlab function