4

I am working on a project of coin identification. First thing I with that I am stuck is correct coin extraction from the image, even from very simple image. There are exists alot of good working methods for coin detection but all of them as I see need manual check after applying. I have tested two of them:

cv2.HoughCircles and threshold with findig countours after it .

Here some successfull examples of processing:

cv2.HoughCircles, good result

enter image description here

cv2.HoughCircles, bad result

enter image description here

But for the second image works great solution of threshloding and finding countours after it:

something like this:

gray = cv2.GaussianBlur(gray, (15, 15), 0)

#gray = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV, 11, 1)
    (_,gray) = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
  contours, hierarchy = cv2.findContours(gray, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

for i,cnt in enumerate(contours):
    ellipse = cv2.fitEllipse(cnt)
    print ellipse,type(ellipse)
    cv2.ellipse(color_img, ellipse, (0,255,0), 2)

produces very good result:

enter image description here

But for some other image it works very pure,

enter image description here

this has happened because coins are to close one from the other and bluring has merged them. It is very simple cas and for it i can just check if result is only one contour decline it . But sometimes it's more complicated. I want to implement some algo that tryes diferent metods of segmentation and chooses the best one. But its hard to encode for me this metric - has anybody Ideas how to do it ?

Original images from example: this 3 are rather qute , but actually is not the rule - some of them has background some of them even not coins - thats why I am thinking about some postchecking process.

enter coin1

enter coin2

enter coin3

enter coin4

enter image description here

Oleg
  • 3,080
  • 3
  • 40
  • 51
  • do you mean something like ( without otsu and some decreased max thresh value ) cv2.threshold(gray,0,250,cv2.THRESH_BINARY_INV) – Oleg Aug 28 '15 at 12:33
  • cv2.threshold(gray,160, 255,cv2.THRESH_BINARY_INV) works for this case but only for this one – Oleg Aug 28 '15 at 13:06
  • is there always exactly one coint (2 sides) on the image? If you are able to use that information to find exactly 2 (nearly same sized) contours, the task should be very easy to solve. – Micka Aug 28 '15 at 13:12
  • would it help to divide the images in 2 partitioning sub images? before circle/ellipse detection? – Micka Aug 28 '15 at 13:16
  • > is there always exactly one coint (2 sides) on the image - actually not , but i can find out this information from height / width of my object with a huge probability. – Oleg Aug 28 '15 at 13:35
  • > would it help to divide the images in 2 partitioning sub images? before circle/ellipse detection. it was my first approach - to divide the image on two equal parts bot it does not work. some times coins are not good placed and this dividing broke coin layout – Oleg Aug 28 '15 at 13:36
  • @OlegGolovanov on a side note, these coins seems interesting looking? what are these coins? – Samer Aug 28 '15 at 14:07
  • @Samer: It is an old roman coins. – Oleg Aug 28 '15 at 14:48
  • @Micka: I think you are right first step must be a more or less realiable splitting. But how to do it – Oleg Aug 28 '15 at 14:48

1 Answers1

2

I had success using a blob detector with the following parameters:

Ptr<SimpleBlobDetector> detector;
SimpleBlobDetector::Params params;
params.minThreshold = 150;
params.maxThreshold = 230;
params.filterByArea = true;
params.minArea = 50;
params.maxArea = 50000;
params.filterByConvexity = true;
params.minConvexity = 0.9;
params.maxConvexity = 1.0;

params.filterByCircularity = false;
params.filterByInertia = false;
params.filterByColor = false;
detector = SimpleBlobDetector::create(params);

And then find the blobs and draw the circles:

Mat SearchImage; // set to whatever picture contains coins
Mat DrawImage; // image to draw on with drawKeypoints
SearchImage.copyTo(DrawImage);
vector<cv::KeyPoint> keypoints;
detector->detect(SearchImage, keypoints);
drawKeypoints(SearchImage, keypoints, DrawImage, Scalar(0, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

EDIT: This example code is in C++. For the Python interface see here for examples.

Benjamin-M-Dale
  • 131
  • 1
  • 6
  • Thanks for BlobDetector I like this approach . But the problem is anyway exists . In some cases it works in some not. I must fine tune threshold params for correct answer. And actually - brutferoce on minThreshold is not a bad idea but its not clear how to check results of algo - what is good answer and what is bad. No keypoints is bad . But one keypoint may be also bad answer (like in 3rd example )but may be not . – Oleg Dec 07 '15 at 08:40