如何检测和计算螺旋的转弯

时间:2012-11-26 11:27:08

标签: c# wpf emgucv counting

我需要检测螺旋形弹簧并计算其线圈圈数。

我尝试过如下:

Image<Bgr, Byte> ProcessImage(Image<Bgr, Byte> img)
{ 
    Image<Bgr, Byte> imgClone = new Image<Bgr,byte>( img.Width, img.Height);
    imgClone = img.Clone();
    Bgr bgrRed = new Bgr(System.Drawing.Color.Red);


    #region Algorithm 1


    imgClone.PyrUp();
    imgClone.PyrDown();
    imgClone.PyrUp();
    imgClone.PyrDown();
    imgClone.PyrUp();
    imgClone.PyrDown();

    imgClone._EqualizeHist();
    imgClone._Dilate(20);
    imgClone._EqualizeHist();
    imgClone._Erode(10);

    imgClone.PyrUp();
    imgClone.PyrDown();
    imgClone.PyrUp();
    imgClone.PyrDown();
    imgClone.PyrUp();
    imgClone.PyrDown();

    imgClone._EqualizeHist();
    imgClone._Dilate(20);
    imgClone._EqualizeHist();
    imgClone._Erode(10);


    Image<Gray, Byte> imgCloneGray = new Image<Gray, byte>(imgClone.Width, imgClone.Height);

    CvInvoke.cvCvtColor(imgClone, imgCloneGray, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_BGR2GRAY);

    imgCloneGray = imgCloneGray.Canny(c_thresh, c_threshLink);//, (int)c_threshSize);

    Contour<System.Drawing.Point> pts = imgCloneGray.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL);

    CvInvoke.cvCvtColor(imgCloneGray, imgCloneYcc, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_GRAY2BGR);

    if (null != pts)
    {
        imgClone.Draw(pts, bgrRed, 2);
        imgClone.Draw(pts.BoundingRectangle, bgrRed, 2);
    }

    #endregion 

    return imgClone; 
}

Input Image OutputImage

我有些能够获得弹簧但是如何获得计数。我正在寻找算法。 我目前不寻求速度优化。

这类似于计数手指。弹簧螺旋很薄,无法使用轮廓。还有什么可以做的。 http://www.luna-arts.de/others/misc/HandsNew.zip

1 个答案:

答案 0 :(得分:3)

你在那里有一个很好的最终二值化,但它看起来太局限于这个案例了。我会做一个相对简单但可能更强大的预处理来实现相对良好的二值化。根据数学形态学,存在称为h-dome的变换,其用于通过抑制高度的最小值/最大值来消除不相关的最小值/最大值。 h。您的图像处理库中可能无法使用此操作,但实现起来并不困难。为了对这个预处理过的图像进行二值化,我选择了Otsu的方法,因为它是自动和统计上最优的。

这是h-dome转换后的输入图像和二进制图像:

enter image description here enter image description here

现在,为了计算“螺旋转弯”的数量,我做了一些非常简单的事情:我将螺旋分开,这样我就可以将它们视为连接组件。为了分割它们,我做了一个带有垂直线的形态开口,接着是一个基本方形的单一扩张。这会产生以下图像:

enter image description here

计算组件给出15.由于你有13个不太接近,这种方法都可以正确计算它们。左侧和右侧的组被计为单个组。

用于执行这些步骤的完整Matlab代码:

f = rgb2gray(imread('http://i.stack.imgur.com/i7x7L.jpg'));
% For this image, the two next lines are optional as they will to lead
% basically the same binary image.
f1 = imhmax(f, 30);
f2 = imhmin(f1, 30);
bin1 = ~im2bw(f2, graythresh(f2));

bin2 = bwmorph(imopen(bin1, strel('line', 15, 90)), 'dilate');