Vs+opencv或者用halcon进行字符的精确定位?具体方法如图,可联系本人you chang的

 

图还没上传。或者图的连接在那里?

 

正在分解 5 和 2,它俩粘在一起了。

可以用 Tesseract 吗?

你的图只能算 12507, 没有其他数字。

Tesseract 失败,google 搞得什么玩意儿。

 

已经能扫到数字,还没有算出数字。

这2字有点难判断的。

1  1  1
0  0  1
0  1  1
1  1  0
1  1  1

下一个2:

0  1  1
0  0  1
0  1  0
1  1  0
1  1  1

import cv2
import imutils
import numpy as np

# 3x5 matrix
DIGITS_LOOKUP = (
    (0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1),  # 0
    (0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1),  # 1
    (0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1),  # 2
    (1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1),  # 5
    (1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0),  # 7
)

DIGITS_LIST = (0, 1, 2, 5, 7)
merged = False  # merge overlapped numbers


# compare scan list to data tuples
def get_digit(lst):
    sim, simIdx = 0, 0

    for mIdx, i in enumerate(DIGITS_LOOKUP):
        fit = 0
        for idx, j in enumerate(i):
            if j == lst[idx]:
                fit += 1
        ratio = fit / 15 * 100
        # print(f'idx: {mIdx} -- ratio: { format(ratio, ".2f") }')
        if ratio > sim:
            sim = ratio
            simIdx = mIdx

    # verify result
    verified = False
    digit = DIGITS_LIST[simIdx]
    while not verified:
        if digit == 7 and not verified:
            if lst[13] == 0 and lst[14] == 0:
                verified = True
                break
            else:
                digit = 5
        if digit == 5 and not verified:
            if lst[5] == 0 and lst[9] == 0:
                verified = True
                break
            else:
                digit = 2
        if digit == 2 and not verified:
            if lst[5] == 1 and lst[7] == 1 and lst[9] == 1:
                verified = True
                break
            else:
                digit = 1
        if digit == 1 and not verified:
            if lst[2] == 1 and lst[4] == 1 and lst[14] == 1:
                verified = True
                break
            else:
                digit = 1
        if digit == 0 and not verified:
            if lst[4] == 0 and lst[7] == 0 and lst[10] == 0:
                verified = True
                break
            else:
                digit = 1

    return digit


def union(a, b):
    x = min(a[0], b[0])
    y = min(a[1], b[1])
    w = max(a[0] + a[2], b[0] + b[2]) - x
    h = max(a[1] + a[3], b[1] + b[3]) - y
    return x, y, w, h


def intersection(a, b):
    x = max(a[0], b[0])
    y = max(a[1], b[1])
    w = min(a[0] + a[2], b[0] + b[2]) - x
    h = min(a[1] + a[3], b[1] + b[3]) - y
    if w < 0 or h < 0:
        return False
    return True


def combine_boxes(boxes):
    global merged
    new_array = []
    for boxa, boxb in zip(boxes, boxes[1:]):
        result = intersection(boxa, boxb)
        # print('compare boxa: ', boxa, '    boxb: ', boxb, '    intersected? ', result)
        if result:
            new_array.append(union(boxa, boxb))
            merged = True
        else:
            if not merged:
                new_array.append(boxa)
            else:
                merged = False
    if not merged:
        new_array.append(boxes[len(boxes) - 1])

    return np.array(new_array).astype('int')


def splitRects(img2, tRects, avgW):
    mList = []
    for r in tRects:
        x, y, w, h = r
        if w >= avgW * 2:
            # print("found big w: ", w, "  avg: ", avgW)
            roi = img2[y:y + h, x:x + w]
            row, col = roi.shape  # get row and column

            colWhites = []
            for i in range(col):
                whiteCnt = 0
                for j in range(row):
                    if roi[j][i] != 0:
                        whiteCnt += 1
                colWhites.append(whiteCnt)

            minWhite = min(i for i in colWhites if i > 0)
            idx = colWhites.index(minWhite)  # find the middle point

            rect1 = x, y, idx, h
            rect2 = x + idx, y, w - idx, h
            mList.append(rect1)
            mList.append(rect2)
        else:
            mList.append(r)
    return mList


def print10(lst):
    CREDBG2 = '\33[101m'
    CEND = '\33[0m'
    text = ''
    for i in lst:
        if i == 1:
            text += CREDBG2 + '  1' + CEND
        else:
            text += CEND + '  0'
    print(text)


def digitRecognition(img2, rects):
    # help = [2, 0, 1, 7, 0, 5, 2, 1, 1]
    # print('\nDigit Recognition:')

    returnList = []
    for idx, r in enumerate(rects):
        x, y, w, h = r
        # print(f'\n==> {help[idx]}: x: {x}   y: {y}    w: {w}    h: {h}')

        roi = img2[y:y + h, x:x + w]
        (roiH, roiW) = roi.shape
        (dW, dH) = (int(roiW / 3), int(roiH / 5))

        # print(f'h-row: {roiH}    w-col: {roiW}')
        # print('dW: ', dW, '    dH: ', dH)

        # define the set of 7 segments
        segments = [
            # ((0, 0), (w, h)),  # all

            ((0, 0), (dW, dH)),  # top l
            ((dW, 0), (dW, dH)),  # top 2
            ((dW + dW, 0), (dW, dH)),  # top 3

            ((0, dH), (dW, dH)),  # 2-1
            ((dW, dH), (dW, dH)),  # 2-2
            ((dW + dW, dH), (dW, dH)),  # 2-3

            ((0, 2 * dH), (dW, dH)),  # 3-1
            ((dW, 2 * dH), (dW, dH)),  # 3-2
            ((dW + dW, 2 * dH), (dW, dH)),  # 3-3

            ((0, 3 * dH), (dW, dH)),  # 4-1
            ((dW, 3 * dH), (dW, dH)),  # 4-2
            ((dW + dW, 3 * dH), (dW, dH)),  # 4-3

            ((0, 4 * dH), (dW, dH)),  # 4-1
            ((dW, 4 * dH), (dW, dH)),  # 4-2
            ((dW + dW, 4 * dH), (dW, dH)),  # 4-3
        ]
        on = [0] * len(segments)

        # loop over the segments
        for (index, ((xA, yA), (xB, yB))) in enumerate(segments):
            # the area of the segment
            segROI = roi[yA:yA + yB, xA:xA + xB]
            row, col = segROI.shape
            area = row * col

            # if index == 9 or index == 10 or index == 11:
            #     print("index: ", index)
            #     for i in range(row):
            #         lst = []
            #         for j in range(col):
            #             if segROI[i][j] > 0:
            #                 lst.append(1)
            #             else:
            #                 lst.append(0)
            #         print10(lst)

            total = cv2.countNonZero(segROI)
            if total > 0:
                ratio = total / area * 100
                # print(f'total( {total} )  /  area( {area} ) = ratio( {ratio} )')

                if ratio > 16:
                    on[index] = 1

        # lookup the digit and draw it on the image
        digit = get_digit(on)
        returnList.append(digit)

        # print("Guess Digit: ", digit)
        # stop = len(on)
        # ctr = 0
        # while ctr < stop:
        #     print(f'{on[ctr]}  {on[ctr + 1]}  {on[ctr + 2]}')
        #     ctr += 3
    return returnList


def findDigit(mImg):
    mImg = imutils.resize(mImg, width=500)
    mClone = mImg.copy()

    gray = cv2.cvtColor(mImg, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(blurred, 50, 200, 255)

    # find contours in the edge map, then sort them by their
    # size in descending order
    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)

    rects = []
    # loop over the contours
    for cnt in cnts:
        area = cv2.contourArea(cnt)

        if area > 36:
            x, y, w, h = cv2.boundingRect(cnt)
            cv2.rectangle(mImg, (x, y), (x + w, y + h), (0, 255, 0), 2)
            # print((x + w) / 2, (y + h) / 2, ',  area: ', area)
            rects.append([x, y, w, h])

    rects.sort(key=lambda tup: tup[0])  # sort by x axis
    comRects = combine_boxes(rects)

    # print('before: ', len(rects), '  --  after: ', len(comRects))
    totalWidth = 0
    for rect in comRects:
        x, y, w, h = rect
        totalWidth += w

    avgWidth = totalWidth / len(comRects)
    # print('average width: ', avgWidth)

    thresh = gray.copy()
    cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY, thresh)
    rects = splitRects(thresh, comRects, avgWidth)
    foundList = digitRecognition(thresh, rects)

    for idx, rect in enumerate(rects):
        x, y, w, h = rect
        cv2.rectangle(mClone, (x, y), (x + w, y + h), (125, 0, 255), 2)
        text = str(foundList[idx])
        cv2.putText(mClone, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 125, 255), 2)

    return mImg, mClone


# =====================================
# main
# =====================================
# load the example image
image = cv2.imread(".\\test\\product_date.jpg")
imgCp = image.copy()

# =====================================
# Window 窗口: Demo
# =====================================
demo_win = 'Demo'
cv2.namedWindow(demo_win)
cv2.moveWindow(demo_win, 805, 80)
# image = findDigit(image)

# =====================================
# Window 窗口: Selected
# =====================================
select_win = 'Selected'
cv2.namedWindow(select_win)
cv2.moveWindow(select_win, 805, 300)
# image = findDigit(image)

while True:
    cv2.imshow(demo_win, image)
    cv2.imshow(select_win, imgCp)
    # keyboard control
    key = cv2.waitKey(1)
    if key == ord("q") or key == ord("Q"):
        break
    if key == ord("f") or key == ord("F"):
        image, imgCp = findDigit(image)

cv2.destroyAllWindows()

3x5 测量版

import cv2
import imutils
import numpy as np

# 3x5 matrix
DIGITS_LOOKUP = (
    (0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1),  # 0
    (0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1),  # 1
    (0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1),  # 2
    (1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1),  # 5
    (1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0),  # 7
)

DIGITS_LIST = (0, 1, 2, 5, 7)
merged = False  # merge overlapped numbers


# compare scan list to data tuples
def get_digit(lst):
    sim, simIdx = 0, 0

    for mIdx, i in enumerate(DIGITS_LOOKUP):
        fit = 0
        for idx, j in enumerate(i):
            if j == lst[idx]:
                fit += 1
        ratio = fit / 15 * 100
        # print(f'idx: {mIdx} -- ratio: { format(ratio, ".2f") }')
        if ratio > sim:
            sim = ratio
            simIdx = mIdx

    # verify result
    verified = False
    digit = DIGITS_LIST[simIdx]
    while not verified:
        if digit == 7 and not verified:
            if lst[13] == 0 and lst[14] == 0:
                verified = True
                break
            else:
                digit = 5
        if digit == 5 and not verified:
            if lst[5] == 0 and lst[9] == 0:
                verified = True
                break
            else:
                digit = 2
        if digit == 2 and not verified:
            if lst[5] == 1 and lst[7] == 1 and lst[9] == 1:
                verified = True
                break
            else:
                digit = 1
        if digit == 1 and not verified:
            if lst[2] == 1 and lst[4] == 1 and lst[14] == 1:
                verified = True
                break
            else:
                digit = 1
        if digit == 0 and not verified:
            if lst[4] == 0 and lst[7] == 0 and lst[10] == 0:
                verified = True
                break
            else:
                digit = 1

    return digit


def union(a, b):
    x = min(a[0], b[0])
    y = min(a[1], b[1])
    w = max(a[0] + a[2], b[0] + b[2]) - x
    h = max(a[1] + a[3], b[1] + b[3]) - y
    return x, y, w, h


def intersection(a, b):
    x = max(a[0], b[0])
    y = max(a[1], b[1])
    w = min(a[0] + a[2], b[0] + b[2]) - x
    h = min(a[1] + a[3], b[1] + b[3]) - y
    if w < 0 or h < 0:
        return False
    return True


def combine_boxes(boxes):
    global merged
    new_array = []
    for boxa, boxb in zip(boxes, boxes[1:]):
        result = intersection(boxa, boxb)
        # print('compare boxa: ', boxa, '    boxb: ', boxb, '    intersected? ', result)
        if result:
            new_array.append(union(boxa, boxb))
            merged = True
        else:
            if not merged:
                new_array.append(boxa)
            else:
                merged = False
    if not merged:
        new_array.append(boxes[len(boxes) - 1])

    return np.array(new_array).astype('int')


def splitRects(img2, tRects, avgW):
    mList = []
    for r in tRects:
        x, y, w, h = r
        if w >= avgW * 2:
            # print("found big w: ", w, "  avg: ", avgW)
            roi = img2[y:y + h, x:x + w]
            row, col = roi.shape  # get row and column

            colWhites = []
            for i in range(col):
                whiteCnt = 0
                for j in range(row):
                    if roi[j][i] != 0:
                        whiteCnt += 1
                colWhites.append(whiteCnt)

            minWhite = min(i for i in colWhites if i > 0)
            idx = colWhites.index(minWhite)  # find the middle point

            rect1 = x, y, idx, h
            rect2 = x + idx, y, w - idx, h
            mList.append(rect1)
            mList.append(rect2)
        else:
            mList.append(r)
    return mList


def print10(lst):
    CREDBG2 = '\33[101m'
    CEND = '\33[0m'
    text = ''
    for i in lst:
        if i == 1:
            text += CREDBG2 + '  1' + CEND
        else:
            text += CEND + '  0'
    print(text)


def digitRecognition(img2, rects):
    # help = [2, 0, 1, 7, 0, 5, 2, 1, 1]
    # print('\nDigit Recognition:')

    returnList = []
    for idx, r in enumerate(rects):
        x, y, w, h = r
        # print(f'\n==> {help[idx]}: x: {x}   y: {y}    w: {w}    h: {h}')

        roi = img2[y:y + h, x:x + w]
        (roiH, roiW) = roi.shape
        (dW, dH) = (int(roiW / 3), int(roiH / 5))

        # print(f'h-row: {roiH}    w-col: {roiW}')
        # print('dW: ', dW, '    dH: ', dH)

        # define the set of 7 segments
        segments = [
            # ((0, 0), (w, h)),  # all

            ((0, 0), (dW, dH)),  # top l
            ((dW, 0), (dW, dH)),  # top 2
            ((dW + dW, 0), (dW, dH)),  # top 3

            ((0, dH), (dW, dH)),  # 2-1
            ((dW, dH), (dW, dH)),  # 2-2
            ((dW + dW, dH), (dW, dH)),  # 2-3

            ((0, 2 * dH), (dW, dH)),  # 3-1
            ((dW, 2 * dH), (dW, dH)),  # 3-2
            ((dW + dW, 2 * dH), (dW, dH)),  # 3-3

            ((0, 3 * dH), (dW, dH)),  # 4-1
            ((dW, 3 * dH), (dW, dH)),  # 4-2
            ((dW + dW, 3 * dH), (dW, dH)),  # 4-3

            ((0, 4 * dH), (dW, dH)),  # 4-1
            ((dW, 4 * dH), (dW, dH)),  # 4-2
            ((dW + dW, 4 * dH), (dW, dH)),  # 4-3
        ]
        on = [0] * len(segments)

        # loop over the segments
        for (index, ((xA, yA), (xB, yB))) in enumerate(segments):
            # the area of the segment
            segROI = roi[yA:yA + yB, xA:xA + xB]
            row, col = segROI.shape
            area = row * col

            # if index == 9 or index == 10 or index == 11:
            #     print("index: ", index)
            #     for i in range(row):
            #         lst = []
            #         for j in range(col):
            #             if segROI[i][j] > 0:
            #                 lst.append(1)
            #             else:
            #                 lst.append(0)
            #         print10(lst)

            total = cv2.countNonZero(segROI)
            if total > 0:
                ratio = total / area * 100
                # print(f'total( {total} )  /  area( {area} ) = ratio( {ratio} )')

                if ratio > 16:
                    on[index] = 1

        # lookup the digit and draw it on the image
        digit = get_digit(on)
        returnList.append(digit)

        # print("Guess Digit: ", digit)
        # stop = len(on)
        # ctr = 0
        # while ctr < stop:
        #     print(f'{on[ctr]}  {on[ctr + 1]}  {on[ctr + 2]}')
        #     ctr += 3
    return returnList


def findDigit(mImg):
    mImg = imutils.resize(mImg, width=500)
    mClone = mImg.copy()

    gray = cv2.cvtColor(mImg, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(blurred, 50, 200, 255)

    # find contours in the edge map, then sort them by their
    # size in descending order
    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)

    rects = []
    # loop over the contours
    for cnt in cnts:
        area = cv2.contourArea(cnt)

        if area > 36:
            x, y, w, h = cv2.boundingRect(cnt)
            cv2.rectangle(mImg, (x, y), (x + w, y + h), (0, 255, 0), 2)
            # print((x + w) / 2, (y + h) / 2, ',  area: ', area)
            rects.append([x, y, w, h])

    rects.sort(key=lambda tup: tup[0])  # sort by x axis
    comRects = combine_boxes(rects)

    # print('before: ', len(rects), '  --  after: ', len(comRects))
    totalWidth = 0
    for rect in comRects:
        x, y, w, h = rect
        totalWidth += w

    avgWidth = totalWidth / len(comRects)
    # print('average width: ', avgWidth)

    thresh = gray.copy()
    cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY, thresh)
    rects = splitRects(thresh, comRects, avgWidth)
    foundList = digitRecognition(thresh, rects)

    for idx, rect in enumerate(rects):
        x, y, w, h = rect
        cv2.rectangle(mClone, (x, y), (x + w, y + h), (125, 0, 255), 2)
        text = str(foundList[idx])
        cv2.putText(mClone, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 125, 255), 2)

    return mImg, mClone


# =====================================
# main
# =====================================
# load the example image
image = cv2.imread(".\\test\\product_date.jpg")
imgCp = image.copy()

# =====================================
# Window 窗口: Demo
# =====================================
demo_win = 'Demo'
cv2.namedWindow(demo_win)
cv2.moveWindow(demo_win, 805, 80)
# image = findDigit(image)

# =====================================
# Window 窗口: Selected
# =====================================
select_win = 'Selected'
cv2.namedWindow(select_win)
cv2.moveWindow(select_win, 805, 300)
# image = findDigit(image)

while True:
    cv2.imshow(demo_win, image)
    cv2.imshow(select_win, imgCp)
    # keyboard control
    key = cv2.waitKey(1)
    if key == ord("q") or key == ord("Q"):
        break
    if key == ord("f") or key == ord("F"):
        image, imgCp = findDigit(image)

cv2.destroyAllWindows()

3x5 测量版

import cv2
import imutils
import numpy as np

# 3x5 matrix
DIGITS_LOOKUP = (
    (0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1),  # 0
    (0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1),  # 1
    (0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1),  # 2
    (1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1),  # 5
    (1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0),  # 7
)

DIGITS_LIST = (0, 1, 2, 5, 7)
merged = False  # merge overlapped numbers


# compare scan list to data tuples
def get_digit(lst):
    sim, simIdx = 0, 0

    for mIdx, i in enumerate(DIGITS_LOOKUP):
        fit = 0
        for idx, j in enumerate(i):
            if j == lst[idx]:
                fit += 1
        ratio = fit / 15 * 100
        # print(f'idx: {mIdx} -- ratio: { format(ratio, ".2f") }')
        if ratio > sim:
            sim = ratio
            simIdx = mIdx

    # verify result
    verified = False
    digit = DIGITS_LIST[simIdx]
    while not verified:
        if digit == 7 and not verified:
            if lst[13] == 0 and lst[14] == 0:
                verified = True
                break
            else:
                digit = 5
        if digit == 5 and not verified:
            if lst[5] == 0 and lst[9] == 0:
                verified = True
                break
            else:
                digit = 2
        if digit == 2 and not verified:
            if lst[5] == 1 and lst[7] == 1 and lst[9] == 1:
                verified = True
                break
            else:
                digit = 1
        if digit == 1 and not verified:
            if lst[2] == 1 and lst[4] == 1 and lst[14] == 1:
                verified = True
                break
            else:
                digit = 1
        if digit == 0 and not verified:
            if lst[4] == 0 and lst[7] == 0 and lst[10] == 0:
                verified = True
                break
            else:
                digit = 1

    return digit


def union(a, b):
    x = min(a[0], b[0])
    y = min(a[1], b[1])
    w = max(a[0] + a[2], b[0] + b[2]) - x
    h = max(a[1] + a[3], b[1] + b[3]) - y
    return x, y, w, h


def intersection(a, b):
    x = max(a[0], b[0])
    y = max(a[1], b[1])
    w = min(a[0] + a[2], b[0] + b[2]) - x
    h = min(a[1] + a[3], b[1] + b[3]) - y
    if w < 0 or h < 0:
        return False
    return True


def combine_boxes(boxes):
    global merged
    new_array = []
    for boxa, boxb in zip(boxes, boxes[1:]):
        result = intersection(boxa, boxb)
        # print('compare boxa: ', boxa, '    boxb: ', boxb, '    intersected? ', result)
        if result:
            new_array.append(union(boxa, boxb))
            merged = True
        else:
            if not merged:
                new_array.append(boxa)
            else:
                merged = False
    if not merged:
        new_array.append(boxes[len(boxes) - 1])

    return np.array(new_array).astype('int')


def splitRects(img2, tRects, avgW):
    mList = []
    for r in tRects:
        x, y, w, h = r
        if w >= avgW * 2:
            # print("found big w: ", w, "  avg: ", avgW)
            roi = img2[y:y + h, x:x + w]
            row, col = roi.shape  # get row and column

            colWhites = []
            for i in range(col):
                whiteCnt = 0
                for j in range(row):
                    if roi[j][i] != 0:
                        whiteCnt += 1
                colWhites.append(whiteCnt)

            minWhite = min(i for i in colWhites if i > 0)
            idx = colWhites.index(minWhite)  # find the middle point

            rect1 = x, y, idx, h
            rect2 = x + idx, y, w - idx, h
            mList.append(rect1)
            mList.append(rect2)
        else:
            mList.append(r)
    return mList


def print10(lst):
    CREDBG2 = '\33[101m'
    CEND = '\33[0m'
    text = ''
    for i in lst:
        if i == 1:
            text += CREDBG2 + '  1' + CEND
        else:
            text += CEND + '  0'
    print(text)


def digitRecognition(img2, rects):
    # help = [2, 0, 1, 7, 0, 5, 2, 1, 1]
    # print('\nDigit Recognition:')

    returnList = []
    for idx, r in enumerate(rects):
        x, y, w, h = r
        # print(f'\n==> {help[idx]}: x: {x}   y: {y}    w: {w}    h: {h}')

        roi = img2[y:y + h, x:x + w]
        (roiH, roiW) = roi.shape
        (dW, dH) = (int(roiW / 3), int(roiH / 5))

        # print(f'h-row: {roiH}    w-col: {roiW}')
        # print('dW: ', dW, '    dH: ', dH)

        # define the set of 7 segments
        segments = [
            # ((0, 0), (w, h)),  # all

            ((0, 0), (dW, dH)),  # top l
            ((dW, 0), (dW, dH)),  # top 2
            ((dW + dW, 0), (dW, dH)),  # top 3

            ((0, dH), (dW, dH)),  # 2-1
            ((dW, dH), (dW, dH)),  # 2-2
            ((dW + dW, dH), (dW, dH)),  # 2-3

            ((0, 2 * dH), (dW, dH)),  # 3-1
            ((dW, 2 * dH), (dW, dH)),  # 3-2
            ((dW + dW, 2 * dH), (dW, dH)),  # 3-3

            ((0, 3 * dH), (dW, dH)),  # 4-1
            ((dW, 3 * dH), (dW, dH)),  # 4-2
            ((dW + dW, 3 * dH), (dW, dH)),  # 4-3

            ((0, 4 * dH), (dW, dH)),  # 4-1
            ((dW, 4 * dH), (dW, dH)),  # 4-2
            ((dW + dW, 4 * dH), (dW, dH)),  # 4-3
        ]
        on = [0] * len(segments)

        # loop over the segments
        for (index, ((xA, yA), (xB, yB))) in enumerate(segments):
            # the area of the segment
            segROI = roi[yA:yA + yB, xA:xA + xB]
            row, col = segROI.shape
            area = row * col

            # if index == 9 or index == 10 or index == 11:
            #     print("index: ", index)
            #     for i in range(row):
            #         lst = []
            #         for j in range(col):
            #             if segROI[i][j] > 0:
            #                 lst.append(1)
            #             else:
            #                 lst.append(0)
            #         print10(lst)

            total = cv2.countNonZero(segROI)
            if total > 0:
                ratio = total / area * 100
                # print(f'total( {total} )  /  area( {area} ) = ratio( {ratio} )')

                if ratio > 16:
                    on[index] = 1

        # lookup the digit and draw it on the image
        digit = get_digit(on)
        returnList.append(digit)

        # print("Guess Digit: ", digit)
        # stop = len(on)
        # ctr = 0
        # while ctr < stop:
        #     print(f'{on[ctr]}  {on[ctr + 1]}  {on[ctr + 2]}')
        #     ctr += 3
    return returnList


def findDigit(mImg):
    mImg = imutils.resize(mImg, width=500)
    mClone = mImg.copy()

    gray = cv2.cvtColor(mImg, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(blurred, 50, 200, 255)

    # find contours in the edge map, then sort them by their
    # size in descending order
    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)

    rects = []
    # loop over the contours
    for cnt in cnts:
        area = cv2.contourArea(cnt)

        if area > 36:
            x, y, w, h = cv2.boundingRect(cnt)
            cv2.rectangle(mImg, (x, y), (x + w, y + h), (0, 255, 0), 2)
            # print((x + w) / 2, (y + h) / 2, ',  area: ', area)
            rects.append([x, y, w, h])

    rects.sort(key=lambda tup: tup[0])  # sort by x axis
    comRects = combine_boxes(rects)

    # print('before: ', len(rects), '  --  after: ', len(comRects))
    totalWidth = 0
    for rect in comRects:
        x, y, w, h = rect
        totalWidth += w

    avgWidth = totalWidth / len(comRects)
    # print('average width: ', avgWidth)

    thresh = gray.copy()
    cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY, thresh)
    rects = splitRects(thresh, comRects, avgWidth)
    foundList = digitRecognition(thresh, rects)

    for idx, rect in enumerate(rects):
        x, y, w, h = rect
        cv2.rectangle(mClone, (x, y), (x + w, y + h), (125, 0, 255), 2)
        text = str(foundList[idx])
        cv2.putText(mClone, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 125, 255), 2)

    return mImg, mClone


# =====================================
# main
# =====================================
# load the example image
image = cv2.imread(".\\test\\product_date.jpg")
imgCp = image.copy()

# =====================================
# Window 窗口: Demo
# =====================================
demo_win = 'Demo'
cv2.namedWindow(demo_win)
cv2.moveWindow(demo_win, 805, 80)
# image = findDigit(image)

# =====================================
# Window 窗口: Selected
# =====================================
select_win = 'Selected'
cv2.namedWindow(select_win)
cv2.moveWindow(select_win, 805, 300)
# image = findDigit(image)

while True:
    cv2.imshow(demo_win, image)
    cv2.imshow(select_win, imgCp)
    # keyboard control
    key = cv2.waitKey(1)
    if key == ord("q") or key == ord("Q"):
        break
    if key == ord("f") or key == ord("F"):
        image, imgCp = findDigit(image)

cv2.destroyAllWindows()

3x5 测量版

import cv2
import imutils
import numpy as np

# 3x5 matrix
DIGITS_LOOKUP = (
    (0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1),  # 0
    (0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1),  # 1
    (0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1),  # 2
    (1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1),  # 5
    (1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0),  # 7
)

DIGITS_LIST = (0, 1, 2, 5, 7)
merged = False  # merge overlapped numbers


# compare scan list to data tuples
def get_digit(lst):
    sim, simIdx = 0, 0

    for mIdx, i in enumerate(DIGITS_LOOKUP):
        fit = 0
        for idx, j in enumerate(i):
            if j == lst[idx]:
                fit += 1
        ratio = fit / 15 * 100
        # print(f'idx: {mIdx} -- ratio: { format(ratio, ".2f") }')
        if ratio > sim:
            sim = ratio
            simIdx = mIdx

    # verify result
    verified = False
    digit = DIGITS_LIST[simIdx]
    while not verified:
        if digit == 7 and not verified:
            if lst[13] == 0 and lst[14] == 0:
                verified = True
                break
            else:
                digit = 5
        if digit == 5 and not verified:
            if lst[5] == 0 and lst[9] == 0:
                verified = True
                break
            else:
                digit = 2
        if digit == 2 and not verified:
            if lst[5] == 1 and lst[7] == 1 and lst[9] == 1:
                verified = True
                break
            else:
                digit = 1
        if digit == 1 and not verified:
            if lst[2] == 1 and lst[4] == 1 and lst[14] == 1:
                verified = True
                break
            else:
                digit = 1
        if digit == 0 and not verified:
            if lst[4] == 0 and lst[7] == 0 and lst[10] == 0:
                verified = True
                break
            else:
                digit = 1

    return digit


def union(a, b):
    x = min(a[0], b[0])
    y = min(a[1], b[1])
    w = max(a[0] + a[2], b[0] + b[2]) - x
    h = max(a[1] + a[3], b[1] + b[3]) - y
    return x, y, w, h


def intersection(a, b):
    x = max(a[0], b[0])
    y = max(a[1], b[1])
    w = min(a[0] + a[2], b[0] + b[2]) - x
    h = min(a[1] + a[3], b[1] + b[3]) - y
    if w < 0 or h < 0:
        return False
    return True


def combine_boxes(boxes):
    global merged
    new_array = []
    for boxa, boxb in zip(boxes, boxes[1:]):
        result = intersection(boxa, boxb)
        # print('compare boxa: ', boxa, '    boxb: ', boxb, '    intersected? ', result)
        if result:
            new_array.append(union(boxa, boxb))
            merged = True
        else:
            if not merged:
                new_array.append(boxa)
            else:
                merged = False
    if not merged:
        new_array.append(boxes[len(boxes) - 1])

    return np.array(new_array).astype('int')


def splitRects(img2, tRects, avgW):
    mList = []
    for r in tRects:
        x, y, w, h = r
        if w >= avgW * 2:
            # print("found big w: ", w, "  avg: ", avgW)
            roi = img2[y:y + h, x:x + w]
            row, col = roi.shape  # get row and column

            colWhites = []
            for i in range(col):
                whiteCnt = 0
                for j in range(row):
                    if roi[j][i] != 0:
                        whiteCnt += 1
                colWhites.append(whiteCnt)

            minWhite = min(i for i in colWhites if i > 0)
            idx = colWhites.index(minWhite)  # find the middle point

            rect1 = x, y, idx, h
            rect2 = x + idx, y, w - idx, h
            mList.append(rect1)
            mList.append(rect2)
        else:
            mList.append(r)
    return mList


def print10(lst):
    CREDBG2 = '\33[101m'
    CEND = '\33[0m'
    text = ''
    for i in lst:
        if i == 1:
            text += CREDBG2 + '  1' + CEND
        else:
            text += CEND + '  0'
    print(text)


def digitRecognition(img2, rects):
    # help = [2, 0, 1, 7, 0, 5, 2, 1, 1]
    # print('\nDigit Recognition:')

    returnList = []
    for idx, r in enumerate(rects):
        x, y, w, h = r
        # print(f'\n==> {help[idx]}: x: {x}   y: {y}    w: {w}    h: {h}')

        roi = img2[y:y + h, x:x + w]
        (roiH, roiW) = roi.shape
        (dW, dH) = (int(roiW / 3), int(roiH / 5))

        # print(f'h-row: {roiH}    w-col: {roiW}')
        # print('dW: ', dW, '    dH: ', dH)

        # define the set of 7 segments
        segments = [
            # ((0, 0), (w, h)),  # all

            ((0, 0), (dW, dH)),  # top l
            ((dW, 0), (dW, dH)),  # top 2
            ((dW + dW, 0), (dW, dH)),  # top 3

            ((0, dH), (dW, dH)),  # 2-1
            ((dW, dH), (dW, dH)),  # 2-2
            ((dW + dW, dH), (dW, dH)),  # 2-3

            ((0, 2 * dH), (dW, dH)),  # 3-1
            ((dW, 2 * dH), (dW, dH)),  # 3-2
            ((dW + dW, 2 * dH), (dW, dH)),  # 3-3

            ((0, 3 * dH), (dW, dH)),  # 4-1
            ((dW, 3 * dH), (dW, dH)),  # 4-2
            ((dW + dW, 3 * dH), (dW, dH)),  # 4-3

            ((0, 4 * dH), (dW, dH)),  # 4-1
            ((dW, 4 * dH), (dW, dH)),  # 4-2
            ((dW + dW, 4 * dH), (dW, dH)),  # 4-3
        ]
        on = [0] * len(segments)

        # loop over the segments
        for (index, ((xA, yA), (xB, yB))) in enumerate(segments):
            # the area of the segment
            segROI = roi[yA:yA + yB, xA:xA + xB]
            row, col = segROI.shape
            area = row * col

            # if index == 9 or index == 10 or index == 11:
            #     print("index: ", index)
            #     for i in range(row):
            #         lst = []
            #         for j in range(col):
            #             if segROI[i][j] > 0:
            #                 lst.append(1)
            #             else:
            #                 lst.append(0)
            #         print10(lst)

            total = cv2.countNonZero(segROI)
            if total > 0:
                ratio = total / area * 100
                # print(f'total( {total} )  /  area( {area} ) = ratio( {ratio} )')

                if ratio > 16:
                    on[index] = 1

        # lookup the digit and draw it on the image
        digit = get_digit(on)
        returnList.append(digit)

        # print("Guess Digit: ", digit)
        # stop = len(on)
        # ctr = 0
        # while ctr < stop:
        #     print(f'{on[ctr]}  {on[ctr + 1]}  {on[ctr + 2]}')
        #     ctr += 3
    return returnList


def findDigit(mImg):
    mImg = imutils.resize(mImg, width=500)
    mClone = mImg.copy()

    gray = cv2.cvtColor(mImg, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(blurred, 50, 200, 255)

    # find contours in the edge map, then sort them by their
    # size in descending order
    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)

    rects = []
    # loop over the contours
    for cnt in cnts:
        area = cv2.contourArea(cnt)

        if area > 36:
            x, y, w, h = cv2.boundingRect(cnt)
            cv2.rectangle(mImg, (x, y), (x + w, y + h), (0, 255, 0), 2)
            # print((x + w) / 2, (y + h) / 2, ',  area: ', area)
            rects.append([x, y, w, h])

    rects.sort(key=lambda tup: tup[0])  # sort by x axis
    comRects = combine_boxes(rects)

    # print('before: ', len(rects), '  --  after: ', len(comRects))
    totalWidth = 0
    for rect in comRects:
        x, y, w, h = rect
        totalWidth += w

    avgWidth = totalWidth / len(comRects)
    # print('average width: ', avgWidth)

    thresh = gray.copy()
    cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY, thresh)
    rects = splitRects(thresh, comRects, avgWidth)
    foundList = digitRecognition(thresh, rects)

    for idx, rect in enumerate(rects):
        x, y, w, h = rect
        cv2.rectangle(mClone, (x, y), (x + w, y + h), (125, 0, 255), 2)
        text = str(foundList[idx])
        cv2.putText(mClone, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 125, 255), 2)

    return mImg, mClone


# =====================================
# main
# =====================================
# load the example image
image = cv2.imread(".\\test\\product_date.jpg")
imgCp = image.copy()

# =====================================
# Window 窗口: Demo
# =====================================
demo_win = 'Demo'
cv2.namedWindow(demo_win)
cv2.moveWindow(demo_win, 805, 80)
# image = findDigit(image)

# =====================================
# Window 窗口: Selected
# =====================================
select_win = 'Selected'
cv2.namedWindow(select_win)
cv2.moveWindow(select_win, 805, 300)
# image = findDigit(image)

while True:
    cv2.imshow(demo_win, image)
    cv2.imshow(select_win, imgCp)
    # keyboard control
    key = cv2.waitKey(1)
    if key == ord("q") or key == ord("Q"):
        break
    if key == ord("f") or key == ord("F"):
        image, imgCp = findDigit(image)

cv2.destroyAllWindows()

3x5 测量版