Ask Your Question
0

Detect decimal or small dot in image

asked 2019-04-05 08:47:08 -0600

updated 2019-04-05 08:49:52 -0600

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

Original

and this is what happens after the processing

image description

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

More examples:

image description

image description

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

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

The images i'm using image description

image description

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 = cv2.imread("10.jpg")

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)

circles = cv2.HoughCircles(warped, cv2.HOUGH_GRADIENT, 7, 14, param1=0.1, param2=20, minRadius=3, maxRadius=7)

# 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 flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2019-04-15 07:18:19 -0600

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.

image description

edit flag offensive delete link more

Comments

This is an interesting solution, thanks!

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

Question Tools

1 follower

Stats

Asked: 2019-04-05 08:47:08 -0600

Seen: 1,617 times

Last updated: Apr 15 '19