4

I have a set of hiragana characters and I would like to count the number of end points/ tips the character have.

example: input image:

enter image description here

desired output image:

enter image description here

I have tried using convex hull

enter image description here

code: (based on opencv tutorial here)

    findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    vector<vector<Point> >hull(contours.size());

    for (int i = 0; i < contours.size(); i++)
    {
        convexHull(Mat(contours[i]), hull[i], false);
    }

    Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);
    for (int i = 0; i< contours.size(); i++)
    {
        if (hierarchy[i][3] == 0) {
            Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
            drawContours(drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point());
        }
    }

then conrnerHarris() but it returned too many undesired corners

enter image description here

code: (based on opencv tutorial here)

    int blockSize = 2;
    int apertureSize = 3;

    /// Detecting corners
    drawing = binarizeImage(drawing); // otsu's
    cornerHarris(drawing, dst, blockSize, apertureSize, 0.04, BORDER_DEFAULT);

    /// Normalizing
    normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
    convertScaleAbs(dst_norm, dst_norm_scaled);

    int countCorner = 0;

    /// Drawing a circle around corners
    for (int j = 0; j < dst_norm.rows; j++)
    {
        for (int i = 0; i < dst_norm.cols; i++)
        {
            if ((int)dst_norm.at<float>(j, i) > 50)
            {
                circle(output, Point(i, j), 2, Scalar::all(255), -1, 8, 0);
                countCorner++;
            }
        }
    }

It detected 11 corners.

I'm thinking that this might be the same as a finger tip detection, but I don't know how to do it.

[I'm using OpenCV 2.4.9.]

user1803551
  • 12,965
  • 5
  • 47
  • 74
R.A.
  • 101
  • 7

1 Answers1

5

I don't tend to use OpenCV as I can get what I need with ImageMagick, which is free and installed on most Linux distros and also available for OSX and Windows. So, I had a try with ImageMagick and maybe you can adapt my methods - this is just done at the command line.

# Thin input image down to a skeleton
convert char.jpg -threshold 50% -negate -morphology Thinning:-1 Skeleton skeleton.jpg

enter image description here

# Find line-ends, using Hit-or-Miss morphology, and make them green (lime). Save as "lineends.jpg"
convert skeleton.jpg -morphology HMT LineEnds -threshold 50% -fill lime -opaque white lineends.jpg

enter image description here

# Find line-junctions, using Hit-or-Miss morphology, and make them red. Save as "line junctions.jpg"
convert skeleton.jpg -morphology HMT LineJunctions -threshold 50% -fill red -opaque white linejunctions.jpg

enter image description here

# Superpose the line-ends and line junctions into a result
convert lineends.jpg linejunctions.jpg -compose lighten -composite result.jpg

enter image description here

Now you will have a red and two green dots near your line ends, and just red dots near junctions, but no matching green ones. So, you will count red dots that have green dots nearby.

I'll just show the skeleton with the dots superimposed, so you can see how they relate:

composite -blend 30% skeleton.jpg result.jpg z.jpg

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432