霍夫变换以检测和删除线
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。
我想使用 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。