|
|
|
|
#样品
|
from imutils import contours
|
import cv2
|
import os
|
|
def cv_show(name, img):
|
cv2.imshow(name, img)
|
cv2.waitKey(0)
|
cv2.destroyAllWindows()
|
|
|
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
|
dim = None
|
(h, w) = image.shape[:2]
|
if width is None and height is None:
|
return image
|
if width is None:
|
r = height / float(h)
|
dim = (int(w * r), height)
|
else:
|
r = width / float(w)
|
dim = (width, int(h * r))
|
resized = cv2.resize(image, dim, interpolation=inter)
|
return resized
|
|
|
def load_digits():
|
# 加载数字模板
|
path = numbers_address
|
filename = os.listdir(path)
|
for file in filename:
|
# print(file)
|
img = cv2.imread(
|
numbers_address + "\\" + file)
|
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
img_temp = cv2.threshold(
|
img_gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
|
cnt = cv2.findContours(img_temp, cv2.RETR_EXTERNAL,
|
cv2.CHAIN_APPROX_NONE)[0]
|
x, y, w, h = cv2.boundingRect(cnt[0])
|
digit_roi = cv2.resize(img_temp[y:y+h, x:x+w], (57, 88))
|
# 将数字模板存到列表中
|
digits.append(digit_roi)
|
|
|
def demo(index):
|
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 25))
|
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (6, 6))
|
target_path = now_dir + "\\" + "demo_" + str(index) + ".png"
|
img_origin = cv2.imread(target_path)
|
img_origin = resize(img_origin, width=300)
|
img_gray = cv2.cvtColor(img_origin, cv2.COLOR_BGR2GRAY)
|
gaussian = cv2.GaussianBlur(img_gray, (5, 5), 1)
|
img_temp = cv2.threshold(
|
gaussian, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
|
img_top = cv2.morphologyEx(img_temp, cv2.MORPH_TOPHAT, rectKernel)
|
img_sobel_x = cv2.Sobel(img_top, cv2.CV_64F, 1, 0, ksize=7)
|
img_sobel_x = cv2.convertScaleAbs(img_sobel_x)
|
img_sobel_y = cv2.Sobel(img_top, cv2.CV_64F, 0, 1, ksize=7)
|
img_sobel_y = cv2.convertScaleAbs(img_sobel_y)
|
img_sobel_xy = cv2.addWeighted(img_sobel_x, 1, img_sobel_y, 1, 0)
|
img_closed = cv2.morphologyEx(img_sobel_xy, cv2.MORPH_CLOSE, rectKernel)
|
thresh = cv2.threshold(
|
img_closed, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
|
img_closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
|
cnts = cv2.findContours(
|
img_closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
|
(cnts, boundingBoxes) = contours.sort_contours(cnts, "top-to-bottom")
|
draw_img = img_origin.copy()
|
draw_img = cv2.drawContours(draw_img, cnts, -1, (0, 0, 255), 1)
|
cv_show("666", draw_img)
|
|
# 存放正确数字序列(包含逗号)的轮廓,即过滤掉不需要的轮廓
|
right_loc = []
|
for c in cnts:
|
x, y, w, h = cv2.boundingRect(c)
|
ar = w/float(h)
|
if ar > 2:
|
right_loc.append((x, y, w, h))
|
for (gx, gy, gw, gh) in right_loc:
|
# 用于存放识别到的数字
|
digit_out = []
|
if (gy-10 < 0):
|
now_gy = gy
|
else:
|
now_gy = gy-10
|
if (gx - 10 < 0):
|
now_gx = gx
|
else:
|
now_gx = gx-10
|
img_digit = gaussian[now_gy:gy+gh+10, now_gx:gx+gw+10]
|
# 二值化处理
|
img_thresh = cv2.threshold(
|
img_digit, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
|
# 寻找轮廓 找出每个数字的轮廓(包含逗号) 正确的话应该有9个轮廓
|
digitCnts = cv2.findContours(
|
img_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
|
# 从左到右排列
|
(cnts, boundingBoxes) = contours.sort_contours(digitCnts, "left-to-right")
|
cnts = list(cnts)
|
flag = 0
|
if len(cnts) == 9:
|
del cnts[1]
|
del cnts[2]
|
del cnts[3]
|
del cnts[4]
|
cnts = tuple(cnts)
|
num_roi = []
|
for c in cnts:
|
x, y, w, h = cv2.boundingRect(c)
|
num_roi.append((x, y, w, h))
|
for (rx, ry, rw, rh) in num_roi:
|
roi = img_digit[ry:ry+rh, rx:rx+rw]
|
roi = cv2.resize(roi, (57, 88))
|
roi = cv2.GaussianBlur(roi, (5, 5), 1)
|
roi = cv2.threshold(
|
roi, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
|
source = []
|
for digitROI in digits:
|
res = cv2.matchTemplate(
|
roi, digitROI, cv2.TM_CCOEFF_NORMED)
|
max_val = cv2.minMaxLoc(res)[1]
|
source.append(max_val)
|
digit_out.append(str(source.index(max(source))))
|
cv2.rectangle(img_origin, (gx-5, gy-5),
|
(gx+gw+5, gy+gh+5), (0, 0, 255), 1)
|
print(digit_out)
|
else:
|
print("读取失败")
|
flag = 1
|
t = ''
|
with open(now_dir + "\\temp.txt", 'a+') as q:
|
if flag == 0:
|
for content in digit_out:
|
t = t + str(content) + " "
|
q.write(t.strip(" "))
|
q.write('\n')
|
t = ''
|
else:
|
q.write("读取失败")
|
q.write('\n')
|
|
|
if __name__ == "__main__":
|
# 存放数字模板列表
|
digits = []
|
# 当前运行目录
|
now_dir = os.getcwd()
|
print("当前运行目录:" + now_dir)
|
numbers_address = now_dir + "\\numbers"
|
load_digits()
|
times = input("请输入程序运行次数:")
|
for i in range(1, int(times) + 1):
|
demo(i)
|
print("输出成功,请检查本地temp.txt文件")
|
cv2.waitKey(0)
|
cv2.destroyAllWindows()
|
while True:
|
if input("输入小写‘q’并回车退出") == 'q':
|
break
|