当前位置:   article > 正文

python OpenCV 信用卡数字识别_"method=\"left-to-right"

"method=\"left-to-right"

myutils.py

  1. import cv2
  2. def sort_contours(cnts, method="left-to-right"):
  3. reverse = False
  4. i = 0
  5. if method == "right-to-left" or method == "bottom-to-top":
  6. reverse = True
  7. if method == "top-to-bottom" or method == "bottom-to-top":
  8. i = 1
  9. boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一个最小的矩形,把找到的形状包起来x,y,h,w
  10. (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
  11. key=lambda b: b[1][i], reverse=reverse))
  12. return cnts, boundingBoxes
  13. def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
  14. dim = None
  15. (h, w) = image.shape[:2]
  16. if width is None and height is None:
  17. return image
  18. if width is None:
  19. r = height / float(h)
  20. dim = (int(w * r), height)
  21. else:
  22. r = width / float(w)
  23. dim = (width, int(h * r))
  24. resized = cv2.resize(image, dim, interpolation=inter)
  25. return resized

ocr_template_match.py

  1. # 导入工具包
  2. from imutils import contours
  3. import numpy as np
  4. import argparse
  5. import cv2
  6. import myutils
  7. # 设置参数
  8. ap = argparse.ArgumentParser()
  9. ap.add_argument("-i", "--image", default='images/credit_card_01.png',
  10. help="path to input image")
  11. ap.add_argument("-t", "--template", default='ocr_a_reference.png',
  12. help="path to template OCR-A image")
  13. args = vars(ap.parse_args())
  14. # 指定信用卡类型
  15. FIRST_NUMBER = {
  16. "3": "American Express",
  17. "4": "Visa",
  18. "5": "MasterCard",
  19. "6": "Discover Card"
  20. }
  21. # 绘图展示
  22. def cv_show(name,img):
  23. cv2.imshow(name, img)
  24. cv2.waitKey(0)
  25. cv2.destroyAllWindows()
  26. # 读取一个模板图像
  27. img = cv2.imread(args["template"])
  28. cv_show('img',img)
  29. # 灰度图
  30. ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  31. cv_show('ref',ref)
  32. # 二值图像
  33. ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
  34. cv_show('ref',ref)
  35. # 计算轮廓
  36. #cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
  37. #返回的list中每个元素都是图像中的一个轮廓
  38. ref_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
  39. cv2.drawContours(img,refCnts,-1,(0,0,255),3)
  40. cv_show('img',img)
  41. print (np.array(refCnts).shape)
  42. refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0] #排序,从左到右,从上到下
  43. digits = {}
  44. # 遍历每一个轮廓
  45. for (i, c) in enumerate(refCnts):
  46. # 计算外接矩形并且resize成合适大小
  47. (x, y, w, h) = cv2.boundingRect(c)
  48. roi = ref[y:y + h, x:x + w]
  49. roi = cv2.resize(roi, (57, 88))
  50. # 每一个数字对应每一个模板
  51. digits[i] = roi
  52. # 初始化卷积核
  53. rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
  54. sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
  55. #读取输入图像,预处理
  56. image = cv2.imread(args["image"])
  57. cv_show('image',image)
  58. image = myutils.resize(image, width=300)
  59. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  60. cv_show('gray',gray)
  61. #礼帽操作,突出更明亮的区域
  62. tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
  63. cv_show('tophat',tophat)
  64. #
  65. gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的
  66. ksize=-1)
  67. gradX = np.absolute(gradX)
  68. (minVal, maxVal) = (np.min(gradX), np.max(gradX))
  69. gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
  70. gradX = gradX.astype("uint8")
  71. print (np.array(gradX).shape)
  72. cv_show('gradX',gradX)
  73. #通过闭操作(先膨胀,再腐蚀)将数字连在一起
  74. gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
  75. cv_show('gradX',gradX)
  76. #THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
  77. thresh = cv2.threshold(gradX, 0, 255,
  78. cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
  79. cv_show('thresh',thresh)
  80. #再来一个闭操作
  81. thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作
  82. cv_show('thresh',thresh)
  83. # 计算轮廓
  84. thresh_, threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
  85. cv2.CHAIN_APPROX_SIMPLE)
  86. cnts = threshCnts
  87. cur_img = image.copy()
  88. cv2.drawContours(cur_img,cnts,-1,(0,0,255),3)
  89. cv_show('img',cur_img)
  90. locs = []
  91. # 遍历轮廓
  92. for (i, c) in enumerate(cnts):
  93. # 计算矩形
  94. (x, y, w, h) = cv2.boundingRect(c)
  95. ar = w / float(h)
  96. # 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
  97. if ar > 2.5 and ar < 4.0:
  98. if (w > 40 and w < 55) and (h > 10 and h < 20):
  99. #符合的留下来
  100. locs.append((x, y, w, h))
  101. # 将符合的轮廓从左到右排序
  102. locs = sorted(locs, key=lambda x:x[0])
  103. output = []
  104. # 遍历每一个轮廓中的数字
  105. for (i, (gX, gY, gW, gH)) in enumerate(locs):
  106. # initialize the list of group digits
  107. groupOutput = []
  108. # 根据坐标提取每一个组
  109. group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
  110. cv_show('group',group)
  111. # 预处理
  112. group = cv2.threshold(group, 0, 255,
  113. cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
  114. cv_show('group',group)
  115. # 计算每一组的轮廓
  116. group_,digitCnts,hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,
  117. cv2.CHAIN_APPROX_SIMPLE)
  118. digitCnts = contours.sort_contours(digitCnts,
  119. method="left-to-right")[0]
  120. # 计算每一组中的每一个数值
  121. for c in digitCnts:
  122. # 找到当前数值的轮廓,resize成合适的的大小
  123. (x, y, w, h) = cv2.boundingRect(c)
  124. roi = group[y:y + h, x:x + w]
  125. roi = cv2.resize(roi, (57, 88))
  126. cv_show('roi',roi)
  127. # 计算匹配得分
  128. scores = []
  129. # 在模板中计算每一个得分
  130. for (digit, digitROI) in digits.items():
  131. # 模板匹配
  132. result = cv2.matchTemplate(roi, digitROI,
  133. cv2.TM_CCOEFF)
  134. (_, score, _, _) = cv2.minMaxLoc(result)
  135. scores.append(score)
  136. # 得到最合适的数字
  137. groupOutput.append(str(np.argmax(scores)))
  138. # 画出来
  139. cv2.rectangle(image, (gX - 5, gY - 5),
  140. (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
  141. cv2.putText(image, "".join(groupOutput), (gX, gY - 15),
  142. cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
  143. # 得到结果
  144. output.extend(groupOutput)
  145. # 打印结果
  146. print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
  147. print("Credit Card #: {}".format("".join(output)))
  148. cv2.imshow("Image", image)
  149. cv2.waitKey(0)

 

ocr_a_reference.png

credit_card_01.png

 

credit_card_02.png

 

检测结果: 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/103818
推荐阅读
相关标签
  

闽ICP备14008679号