benderto
benderto

Reputation: 921

Detect points in image and compare them

I am trying to extract points from image that makes up some sign.

original picture

First of all I am applying adaptive threshold:

adaptive

Then I try to detect blobs and ignore all that don't make up the sign with measuring distances and blobs radius.

detection

But that doesn't do it precisly (different original image) and many artefacts are detected. I tried all variations of parameters, but none fits for :

enter image description here

Is there some better way to it?

The picture comes from camera and I am trying to detect missing dots in sign. If dots are missing, they missing from the bottom and affect entire row (so they affect total height of sign). Now I am creating template with no missing dots and compare it to actual image every few frames, but that doesn't work, because the error that missing dots create is smaller than error between frames.

Any ideas for better approach to this problem?

Upvotes: 1

Views: 354

Answers (3)

Result

enter image description hereI have implemented the code as per the direction @FiReTiTi. Please check out.!!

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;

int main(){
    Mat src = imread("7.png",1);
    imshow("src",src);
    src = src + Scalar (75,75,75);
    Mat erosion_dst;
    Mat dilation_dst;
    Mat dilation_dst1;
    int erosion_size = 8;   
cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS,
                      cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1), 
                      cv::Point(erosion_size, erosion_size) );
    erode( src, erosion_dst, element );
    erode(  erosion_dst, erosion_dst, element );
    erode(  erosion_dst, erosion_dst, element );
    dilate(erosion_dst, dilation_dst1, element );

    dilate(dilation_dst1, dilation_dst, element );
    dilate(dilation_dst, dilation_dst, element );
    dilate(dilation_dst, dilation_dst, element );
    erode( dilation_dst, dilation_dst, element );

    imshow("opening of image",dilation_dst);

    Mat topHat= src-dilation_dst;
    //topHat = topHat + 255;
    imshow("tophat image",topHat);

for(int i=0;i<topHat.rows;i++)
 {
  for(int j=0;j<topHat.cols;j++)
  {
   if(topHat.at<uchar>(i,j) > 2 )
    {
     //originalImage.at<Vec3b>(i,j) = 255;
        topHat.at<uchar>(i,j)=255;

        //   cout << i<<" " <<j<< endl; 
     }
   }
 }
//

imshow("Final image",topHat);
    waitKey();
}

Upvotes: -1

FiReTiTi
FiReTiTi

Reputation: 5898

Here is what I've just tested and it gives good results:

  1. Opening + closing with a small structuring element radius in order to clean a little bit your image
  2. Big white top hat in order to extract your text.

It gives a better result than an automatic thresholding.

[EDIT] here is a result, but with just an opening and a white top-hat of size 13: result

Upvotes: 0

Lamar Latrell
Lamar Latrell

Reputation: 1670

I dealt with a similar problem, my approach was longer, but it gave more parameters to tune (a benefit as much as it can be a curse) - anyways:

  1. GaussianBlur (if required)
  2. Canny filter
  3. Dilate (if required to close the 'rings' from the Canny step)
  4. findContours

Play around with the initial image processing so that it errs on the side of giving (slightly) more candidates contours than you should - then filter according to the characteristics of your targets vs. false positives.

If you haven't used contours and moment analysis before, now is the time to read up on it...

In my case I implemented:

  • A 'hierarchical' filter based on how nested the contours were within each other.
  • A 'morphological' filter that looked for contours that had perimeter to area ratios close to what an ideal circle has (this looks relevant to your task).

Upvotes: 2

Related Questions