图还没上传。或者图的连接在那里?
正在分解 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 测量版