我正在尝试设计一种检测此管道曲率的方法。我尝试应用霍夫变换并发现检测到的线但是它们不是沿着管道的表面放置,因此将其平滑以适应beizer曲线是行不通的。请为这样的图像建议一些好方法。[{{0 }}
通过霍夫变换获得的用于检测线的图像如下 [ 我正在使用标准Matlab代码进行概率性霍夫变换线检测,该检测生成围绕结构的线段。基本上,管道的形状类似于抛物线,但对于霍布抛物线检测,我需要在检测之前提供该点的偏心率。请建议一个很好的方法来找到可以适合抛物线的曲率上的离散点。我已经给opencv和ITK提供了标签,所以如果有可以在这个特定图片上实现的功能,请建议我将尝试看看结果的功能。
img = imread('test2.jpg');
rawimg = rgb2gray(img);
[accum, axis_rho, axis_theta, lineprm, lineseg] = Hough_Grd(bwtu, 8, 0.01);
figure(1); imagesc(axis_theta*(180/pi), axis_rho, accum); axis xy;
xlabel('Theta (degree)'); ylabel('Pho (pixels)');
title('Accumulation Array from Hough Transform');
figure(2); imagesc(bwtu); colormap('gray'); axis image;
DrawLines_2Ends(lineseg);
title('Raw Image with Line Segments Detected');
图像的边缘图如下,并且在边缘图上应用Hough变换后生成的结果也不好。我在想一个像这条曲线那样进行一般参数形状检测的解决方案可以表示为一系列抛物线,因此我们进行曲线拟合来估计系数,因为它会弯曲以分析它的曲率。我需要设计一个实时程序,所以请向这个方向提出建议。
答案 0 :(得分:13)
我建议采用以下方法:
第一阶段:生成管道分段。
第二阶段 - 提取曲线
在此阶段,您应提取曲线的点以执行Beizer拟合。 您可以在顶部边缘或底部边缘执行此计算。 另一种选择是在管道分割的骨架上进行。
<强>结果
管道分段。顶部和底部边缘分别用蓝色和红色标记。
<强>代码强>
I = mat2gray(imread('ILwH7.jpg'));
im = rgb2gray(I);
%constant values to be used later on
BW_THRESHOLD = 0.64;
MIN_CC_SIZE = 50;
VAR_THRESHOLD = 2;
SIMILAR_SIZE_THRESHOLD = 0.85;
%stage 1 - thresholding & noise cleaning
bwIm = im>BW_THRESHOLD;
bwIm = imfill(bwIm,'holes');
bwIm = imopen(bwIm,strel('disk',1));
CC = bwconncomp(bwIm);
%iterates over the CC list, and searches for the CC which represents the
%pipe
for ii=1:length(CC.PixelIdxList)
%ignore small CC
if(length(CC.PixelIdxList{ii})<50)
continue;
end
%extracts CC edges
ccMask = zeros(size(bwIm));
ccMask(CC.PixelIdxList{ii}) = 1;
ccMaskEdges = edge(ccMask);
%finds connected components in the edges mat(there should be two).
%these are the top and bottom parts of the pipe.
CC2 = bwconncomp(ccMaskEdges);
if length(CC2.PixelIdxList)~=2
continue;
end
%tests that the top and bottom edges has similar sizes
s1 = length(CC2.PixelIdxList{1});
s2 = length(CC2.PixelIdxList{2});
if(min(s1,s2)/max(s1,s2) < SIMILAR_SIZE_THRESHOLD)
continue;
end
%calculate the masks of these two connected compnents
topEdgeMask = false(size(ccMask));
topEdgeMask(CC2.PixelIdxList{1}) = true;
bottomEdgeMask = false(size(ccMask));
bottomEdgeMask(CC2.PixelIdxList{2}) = true;
%tests that the variance of the distances between the points is low
topEdgeDists = bwdist(topEdgeMask);
bottomEdgeDists = bwdist(bottomEdgeMask);
var1 = std(topEdgeDists(bottomEdgeMask));
var2 = std(bottomEdgeDists(topEdgeMask));
%if the variances are low - we have found the CC of the pipe. break!
if(var1<VAR_THRESHOLD && var2<VAR_THRESHOLD)
pipeMask = ccMask;
break;
end
end
%performs median filtering on the top and bottom boundaries.
MEDIAN_SIZE =5;
[topCorveY, topCurveX] = find(topEdgeMask);
topCurveX = medfilt1(topCurveX);
topCurveY = medfilt1(topCurveY);
[bottomCorveY, bottomCurveX] = find(bottomEdgeMask);
bottomCurveX = medfilt1(bottomCurveX);
bottomCorveY = medfilt1(bottomCorveY);
%display results
imshow(pipeMask); hold on;
plot(topCurveX,topCorveY,'.-');
plot(bottomCurveX,bottomCorveY,'.-');
<强>评论强>
在这个具体的例子中,通过阈值处理获取管道分割相对容易。在某些场景中,它可能更复杂。在这些情况下,您可能希望使用区域增长算法来生成管道分段。
检测代表管道的连通组件可以通过使用更多的数据来完成。例如 - 它的边界的局部曲率应该很低。
答案 1 :(得分:5)
您可以找到倒置边缘图图像的连通分量(CC)。然后,您可以使用region-properties以某种方式过滤这些组件,例如,基于它们的像素数。以下是使用给定Octave代码获得的连接组件。 现在,您可以使用nlinfit或任何合适的方法为每个CC拟合模型。
im = imread('uFBtU.png');
gr = rgb2gray(uint8(im));
er = imerode(gr, ones(3)) < .5;
[lbl, n] = bwlabel(er, 8);
imshow(label2rgb(lbl))