如何select修正六位数字组的轮廓
How to select correct contour the group of six digits
我有一批截图如下:
然后我尝试用六位数字检测区域并识别它们。第二部分就像一个魅力。我在检测正确区域时遇到问题,因为它可以根据屏幕尺寸进行移位放置。例如,裁剪图像如下所示:
看起来还不错,但我必须在代码中添加一些变通方法到 select 正确的位置。
我的代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 6))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 8))
# Load and resize image to standard size
img0 = Image.open('./data/test.png')
img0.thumbnail((720, 1423))
img = np.array(img0)
# The magic from https://www.pyimagesearch.com/2017/07/17/credit-card-ocr-with-opencv-and-python/
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradX = np.absolute(gradX)
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype("uint8")
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
locs = []
for (i, c) in enumerate(cnts):
(x, y, w, h) = cv2.boundingRect(c)
ar = w / h
if x > 140 and x < 220 and w > 100 and h > 12 and h < 20 and ar >= 4 and ar <= 6:
locs.append((x, y, w, h))
# Calculate the crop rectangle
LEFT_TOP = (181, 316)
RIGHT_BOTTOM = (299, 346)
if len(locs) > 0:
(x, y, w, h) = locs[0]
LEFT_TOP = (x - 5, y - 5) # workaround place
RIGHT_BOTTOM = (x + w + 5, y + h) # workaround place
print(LEFT_TOP, RIGHT_BOTTOM)
img1 = img0.crop(LEFT_TOP + RIGHT_BOTTOM)
选择的轮廓看起来像:
它select是一个比实际区域小的等高线。为什么?如何解决?
谢谢!
测试文件:
软件没有魔法...
不合适的过滤器“吃掉”了您的部分数字。
- 删除顶帽过滤器。
- 删除 Sobel 过滤器。
- 将
cv2.THRESH_BINARY
替换为 cv2.THRESH_BINARY_INV
。
- 增加
sqKernel
的大小。
我建议你绘制等高线,并显示(或保存)中间结果以进行测试。
修改后的代码如下:
import cv2
import numpy as np
#from matplotlib import pyplot as plt
from PIL import Image
#rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 6))
#sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 8))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 11))
# Load and resize image to standard size
img0 = Image.open('./data/test.png')
img0.thumbnail((720, 1423))
img = np.array(img0)
# The magic from https://www.pyimagesearch.com/2017/07/17/credit-card-ocr-with-opencv-and-python/
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
#gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
#gradX = np.absolute(gradX)
#(minVal, maxVal) = (np.min(gradX), np.max(gradX))
#gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
#gradX = gradX.astype("uint8")
#gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
#thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
locs = []
# Draw contours for testing
tmp_im = cv2.cvtColor(img, cv2.COLOR_RGBA2BGR)
cv2.drawContours(tmp_im, cnts, -1, (0, 255, 0), 1) # Draw green line around the contour
cv2.imshow('tmp_im', tmp_im)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('./data/tmp_im.png', tmp_im)
for (i, c) in enumerate(cnts):
(x, y, w, h) = cv2.boundingRect(c)
ar = w / h
if x > 140 and x < 220 and w > 100 and h > 12 and h < 20 and ar >= 4 and ar <= 6:
locs.append((x, y, w, h))
# Calculate the crop rectangle
LEFT_TOP = (181, 316)
RIGHT_BOTTOM = (299, 346)
if len(locs) > 0:
(x, y, w, h) = locs[0]
#LEFT_TOP = (x - 5, y - 5) # workaround place
#RIGHT_BOTTOM = (x + w + 5, y + h) # workaround place
LEFT_TOP = (x, y) # workaround place
RIGHT_BOTTOM = (x + w, y + h) # workaround place
print(LEFT_TOP, RIGHT_BOTTOM)
img1 = img0.crop(LEFT_TOP + RIGHT_BOTTOM)
img1.show()
img1.save('./data/digits.png')
结果:
tmp_img
(用于测试):
我有一批截图如下:
然后我尝试用六位数字检测区域并识别它们。第二部分就像一个魅力。我在检测正确区域时遇到问题,因为它可以根据屏幕尺寸进行移位放置。例如,裁剪图像如下所示:
看起来还不错,但我必须在代码中添加一些变通方法到 select 正确的位置。
我的代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 6))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 8))
# Load and resize image to standard size
img0 = Image.open('./data/test.png')
img0.thumbnail((720, 1423))
img = np.array(img0)
# The magic from https://www.pyimagesearch.com/2017/07/17/credit-card-ocr-with-opencv-and-python/
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradX = np.absolute(gradX)
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype("uint8")
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
locs = []
for (i, c) in enumerate(cnts):
(x, y, w, h) = cv2.boundingRect(c)
ar = w / h
if x > 140 and x < 220 and w > 100 and h > 12 and h < 20 and ar >= 4 and ar <= 6:
locs.append((x, y, w, h))
# Calculate the crop rectangle
LEFT_TOP = (181, 316)
RIGHT_BOTTOM = (299, 346)
if len(locs) > 0:
(x, y, w, h) = locs[0]
LEFT_TOP = (x - 5, y - 5) # workaround place
RIGHT_BOTTOM = (x + w + 5, y + h) # workaround place
print(LEFT_TOP, RIGHT_BOTTOM)
img1 = img0.crop(LEFT_TOP + RIGHT_BOTTOM)
选择的轮廓看起来像:
它select是一个比实际区域小的等高线。为什么?如何解决?
谢谢!
测试文件:
软件没有魔法...
不合适的过滤器“吃掉”了您的部分数字。
- 删除顶帽过滤器。
- 删除 Sobel 过滤器。
- 将
cv2.THRESH_BINARY
替换为cv2.THRESH_BINARY_INV
。 - 增加
sqKernel
的大小。
我建议你绘制等高线,并显示(或保存)中间结果以进行测试。
修改后的代码如下:
import cv2
import numpy as np
#from matplotlib import pyplot as plt
from PIL import Image
#rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 6))
#sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 8))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 11))
# Load and resize image to standard size
img0 = Image.open('./data/test.png')
img0.thumbnail((720, 1423))
img = np.array(img0)
# The magic from https://www.pyimagesearch.com/2017/07/17/credit-card-ocr-with-opencv-and-python/
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
#gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
#gradX = np.absolute(gradX)
#(minVal, maxVal) = (np.min(gradX), np.max(gradX))
#gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
#gradX = gradX.astype("uint8")
#gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
#thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
locs = []
# Draw contours for testing
tmp_im = cv2.cvtColor(img, cv2.COLOR_RGBA2BGR)
cv2.drawContours(tmp_im, cnts, -1, (0, 255, 0), 1) # Draw green line around the contour
cv2.imshow('tmp_im', tmp_im)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('./data/tmp_im.png', tmp_im)
for (i, c) in enumerate(cnts):
(x, y, w, h) = cv2.boundingRect(c)
ar = w / h
if x > 140 and x < 220 and w > 100 and h > 12 and h < 20 and ar >= 4 and ar <= 6:
locs.append((x, y, w, h))
# Calculate the crop rectangle
LEFT_TOP = (181, 316)
RIGHT_BOTTOM = (299, 346)
if len(locs) > 0:
(x, y, w, h) = locs[0]
#LEFT_TOP = (x - 5, y - 5) # workaround place
#RIGHT_BOTTOM = (x + w + 5, y + h) # workaround place
LEFT_TOP = (x, y) # workaround place
RIGHT_BOTTOM = (x + w, y + h) # workaround place
print(LEFT_TOP, RIGHT_BOTTOM)
img1 = img0.crop(LEFT_TOP + RIGHT_BOTTOM)
img1.show()
img1.save('./data/digits.png')
结果:
tmp_img
(用于测试):