# Detect decimal or small dot in image

I'm following Adrian Rosebrock's tutorial on recognising digits: https://www.pyimagesearch.com/2017/02...

But it doesn't recognise decimal points, so I've been trying really hard to create a part that would help to do that. I think I've gotten close, but I'm not sure what I've done wrong.

This is my image after preprocessing

and this is what happens after the processing

As you can see, I'm doing something wrong somewhere

More examples:

Can anyone guide me on what I should do? I'm really lost here

================================================================

The images i'm using

The code I'm using

from imutils.perspective import four_point_transform
from imutils import contours
import imutils
import cv2
import numpy

DIGITS_LOOKUP = {
# Old Library
#(1, 1, 1, 0, 1, 1, 1): 0, # same as new 8
(0, 0, 1, 0, 0, 1, 0): 1,
(1, 0, 1, 1, 1, 1, 0): 2,
(1, 0, 1, 1, 0, 1, 1): 3,
(0, 1, 1, 1, 0, 1, 0): 4,
(1, 1, 0, 1, 0, 1, 1): 5,
#(1, 1, 0, 1, 1, 1, 1): 6,
(1, 0, 1, 0, 0, 1, 0): 7,
(1, 1, 1, 1, 1, 1, 1): 8,
(1, 1, 1, 1, 0, 1, 1): 9,

# New Digital Library
(0, 0, 1, 1, 1, 0, 1): 0,
(1, 0, 1, 0, 0, 1, 1): 2,

(0, 0, 1, 1, 0, 1, 1): 4,
(0, 0, 0, 0, 0, 1, 1): 4,

(1, 1, 0, 0, 0, 1, 1): 5,
(1, 1, 0, 1, 1, 0, 1): 5,
(1, 0, 0, 0, 0, 1, 1): 5,

(1, 1, 1, 0, 0, 0, 0): 7,

(1, 1, 0, 1, 1, 1, 1): 8,
(1, 1, 1, 0, 1, 1, 1): 8
}

image = imutils.resize(image, height=100)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 120, 255, 1)
cv2.imshow("1", edged)

cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
displayCnt = None

for c in cnts:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)

if len(approx) == 4:
displayCnt = approx
break

warped = four_point_transform(gray, displayCnt.reshape(4, 2))
output = four_point_transform(image, displayCnt.reshape(4, 2))

thresh = cv2.threshold(warped, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("2", thresh)
print(thresh.shape)

# ensure at least some circles were found
if circles is not None:
circles = numpy.round(circles[0, :]).astype("int")

for (x, y, r) in circles:
cv2.circle(output, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)

# show the output image
cv2.imshow("test", output)
cv2.waitKey(0)

edit retag close merge delete

Sort by ยป oldest newest most voted

Another solution may be to threshold the image, do a few iterations of dilation to join the pixels, then look for contours. The dot will have a contour of a certain area and aspect ratio.

more

This is an interesting solution, thanks!

( 2019-04-15 11:36:51 -0600 )edit

Official site

GitHub

Wiki

Documentation