7

I am working with emguCV for finding contours essential points then saving this point in a file and user redraw this shape in future. so, my goal is this image:

example
example

my solution is this: 1. import image to picturebox 2. edge detection with canny algorithm 3. finding contours and save points

I found a lot of points with below codes but i can't drawing first shape with this point!

using Emgu.CV;
using Emgu.Util;

private void button1_Click(object sender, EventArgs e)          
{
    Bitmap bmp = new Bitmap(pictureBox1.Image);
    Image<Bgr, Byte> img = new Image<Bgr, byte>(bmp);

    Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

    Gray cannyThreshold = new Gray(80);
    Gray cannyThresholdLinking = new Gray(120);
    Gray circleAccumulatorThreshold = new Gray(120);

    Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking).Not();

    Bitmap color;
    Bitmap bgray;
    IdentifyContours(cannyEdges.Bitmap, 50, true, out bgray, out color);

    pictureBox1.Image = color;
}

public void IdentifyContours(Bitmap colorImage, int thresholdValue, bool invert, out Bitmap processedGray, out Bitmap processedColor)
{
    Image<Gray, byte> grayImage = new Image<Gray, byte>(colorImage);
    Image<Bgr, byte> color = new Image<Bgr, byte>(colorImage);

    grayImage = grayImage.ThresholdBinary(new Gray(thresholdValue), new Gray(255));

    if (invert)
    {
        grayImage._Not();
    }

    using (MemStorage storage = new MemStorage())
    {
        for (Contour<Point> contours = grayImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext)
        {
            Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.015, storage);
            if (currentContour.BoundingRectangle.Width > 20)
            {
                CvInvoke.cvDrawContours(color, contours, new MCvScalar(255), new MCvScalar(255), -1, 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, new Point(0, 0));
                color.Draw(currentContour.BoundingRectangle, new Bgr(0, 255, 0), 1);
            }

            Point[] pts = currentContour.ToArray();
            foreach (Point p in pts)
            {
                //add points to listbox
                listBox1.Items.Add(p);
            }
       }
  }

   processedColor = color.ToBitmap();
   processedGray = grayImage.ToBitmap();
}
Banana
  • 2,435
  • 7
  • 34
  • 60
tamson
  • 71
  • 1
  • 1
  • 2

1 Answers1

1

In your code you have added contour approximation operation

Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.015, storage);

This contour approximation will approximate your Contour to a nearest polygon & so your actual points got shifted. If you want to reproduce the same image you need not to do any approximation.

Refer this thread.

Community
  • 1
  • 1
Balaji R
  • 1,805
  • 22
  • 41
  • 1
    thanks, i change that section and returned point become less and this is a progress for me. let me explain on attached image: this image exported from a font creator program(high logic font crator) if you see to this image below (mark as 2), this program return a set of points that builds lines (example: blue line in left hand) and bezier(for example red bezier in right hand with only 3 points). briefly my code return 188 points for image 1 and font creator returned 47 points. and my code only return points that i can draw straight line with this points and no bezier or curve. thanks – tamson Jul 28 '14 at 08:33
  • 1
    I think your problem is fitting your contour in a Bézier curve.http://en.wikipedia.org/wiki/B%C3%A9zier_curve, use the following reference with source code to proceed further. https://github.com/thenatefisher/OpenCV-Beziers – Balaji R Jul 28 '14 at 09:46
  • 1
    thanks, yes exactly i want implement this: http://www.yourfonts.com/quality.html (first approach). unfortunatly i dont know c++. – tamson Jul 28 '14 at 15:16