使用OpenCV检测数字的小点或小数点

时间:2019-04-05 14:06:38

标签: python opencv computer-vision hough-transform

我正在关注Adrian Rosebrock的关于识别RPi上的数字的教程,因此不要进行tesseract或其他任何操作: https://www.pyimagesearch.com/2017/02/13/recognizing-digits-with-opencv-and-python/

但是它不能识别小数点,因此我一直在努力创建一个有助于实现此目的的零件。我想我已经接近了,但是我不确定自己做错了什么。

这是经过预处理的我的照片

enter image description here

这就是尝试识别部分之后发生的事情

enter image description here

如您所见,我在某处做错了。已经尝试在houghCircles中调整param1和param2

更多示例:

enter image description here

enter image description here

有人可以指导我该怎么做吗?我真的在这里迷路了

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

我正在使用的图像 enter image description here

enter image description here

我正在使用的代码

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)

2 个答案:

答案 0 :(得分:1)

由于小数点可能是正方形而不是圆形,因此使用cv2.HoughCircles()可能不是最佳选择。此外,由于您可能会有背景噪音,因此尝试查找连接的组件可能会给您带来假阳性结果。

这是一种使用cv2.boundingRect()cv2.contourArea()检测小数的方法。我们可以设置最小和最大阈值区域,这样它不仅可以检测小数,而且可以避免检测到噪声。

试图在图像上进行检测

enter image description here enter image description here

enter image description here enter image description here

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

DIGITS_LOOKUP = {
    (1, 1, 1, 0, 1, 1, 1): 0,
    (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
}

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))

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

digit_cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
digit_cnts = imutils.grab_contours(digit_cnts)

threshold_max_area = 25
threshold_min_area = 5
contour_image = thresh.copy()

for c in digit_cnts:
    (x,y,w,h) = cv2.boundingRect(c)
    area = cv2.contourArea(c) 
    if area < threshold_max_area and area > threshold_min_area:
        cv2.drawContours(contour_image,[c], 0, (100,5,10), 3)

cv2.imshow("detect decimal", contour_image)
cv2.waitKey(0)

答案 1 :(得分:0)

对此进行了处理,指的是:How to remove small connected objects using OpenCV

将这些作为结果 enter image description here enter image description here

但是它们不是很好或不能稳定使用。如果点突然比以前大(例如,超过9个像素,或者图像已调整大小),则无法再使用它,因此这不是动态答案,这很不好。但是,如果有人感兴趣,我就把这留在这里

代码

 NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
   navigationView.setNavigationItemSelectedListener(this); 
   navigationView.setItemIconTintList(null); // <-- HERE add this code for icon color