使用opencv和python隔离图片中的数字矩阵
Isolating matrix of numbers in a picture with opencv and python
我一直在尝试将矩阵的图片分割成各个单元格,这样我就可以对它们执行 OCR,但是 运行 遇到了很多麻烦。示例图片如下所示:
我一直在尝试结合使用 Canny 边缘检测、高斯模糊和轮廓——但运气不佳。我见过的大多数教程都假设感兴趣的项目周围有一个框,而对于矩阵,它通常是一个部分框。
一旦我可以裁剪矩阵,我相信执行类似的步骤 this tutorial here 就足够了。
谁能推荐一种算法来帮助裁剪出矩阵,然后裁剪出单个单元格?
到目前为止我的代码是:
import cv2
import numpy as np
import pickle
import imutils
if __name__ == '__main__':
image = cv2.imread('matrix.jpeg')
image = imutils.resize(image, height=500)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5,5), 0)
edged = cv2.Canny(blurred, 50, 200, 255)
# cv2.imwrite('test.jpeg', edged)
谢谢!
由于括号的形状是独一无二的,您可以使用它们来隔离方程的右轴。一种方法是使用下图 cv2.matchShapes()
。
使用cv2.matchShapes()
的好处是它是平移、旋转和缩放不变的。这意味着使用相同的支架图像,我们可以在任何比例下检测两个支架(一个旋转 180 度)。现在我们已经找到代表括号的轮廓,我们简单地 trim 图像到最小和最大 x 坐标,结果如下图
同样可以用下面的代码实现
import cv2
import numpy as np
img1 = cv2.imread('bracket.png',0)
img2 = cv2.imread('test.png',0)
ret, thresh = cv2.threshold(img1, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)
_, contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
_, contours,hierarchy = cv2.findContours(thresh2,2,1)
match_values = []
for i in range(len(contours)):
cnt2 = contours[i]
ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
match_values.append(ret)
# Un-comment the next set of lines if you would like to see the match rate of each contour
# print(ret)
# img = cv2.cvtColor(img2, cv2.COLOR_GRAY2BGR)
# cv2.drawContours(img, contours, i, (255,255,0), 3)
# cv2.imshow('contour', img)
# cv2.waitKey(0)
best_matches = np.argsort(match_values)[-3:][::-1]
limits = np.vstack(( contours[best_matches[0]].reshape(-1,2), contours[best_matches[1]].reshape(-1,2))).reshape(-1,2)
cropped_img = img2[:, np.min(limits[:,0]):np.max(limits[:,0]) ]
cv2.imwrite('cropped_img.png', cropped_img)
我一直在尝试将矩阵的图片分割成各个单元格,这样我就可以对它们执行 OCR,但是 运行 遇到了很多麻烦。示例图片如下所示:
我一直在尝试结合使用 Canny 边缘检测、高斯模糊和轮廓——但运气不佳。我见过的大多数教程都假设感兴趣的项目周围有一个框,而对于矩阵,它通常是一个部分框。
一旦我可以裁剪矩阵,我相信执行类似的步骤 this tutorial here 就足够了。
谁能推荐一种算法来帮助裁剪出矩阵,然后裁剪出单个单元格?
到目前为止我的代码是:
import cv2
import numpy as np
import pickle
import imutils
if __name__ == '__main__':
image = cv2.imread('matrix.jpeg')
image = imutils.resize(image, height=500)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5,5), 0)
edged = cv2.Canny(blurred, 50, 200, 255)
# cv2.imwrite('test.jpeg', edged)
谢谢!
由于括号的形状是独一无二的,您可以使用它们来隔离方程的右轴。一种方法是使用下图 cv2.matchShapes()
。
使用cv2.matchShapes()
的好处是它是平移、旋转和缩放不变的。这意味着使用相同的支架图像,我们可以在任何比例下检测两个支架(一个旋转 180 度)。现在我们已经找到代表括号的轮廓,我们简单地 trim 图像到最小和最大 x 坐标,结果如下图
同样可以用下面的代码实现
import cv2
import numpy as np
img1 = cv2.imread('bracket.png',0)
img2 = cv2.imread('test.png',0)
ret, thresh = cv2.threshold(img1, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)
_, contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
_, contours,hierarchy = cv2.findContours(thresh2,2,1)
match_values = []
for i in range(len(contours)):
cnt2 = contours[i]
ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
match_values.append(ret)
# Un-comment the next set of lines if you would like to see the match rate of each contour
# print(ret)
# img = cv2.cvtColor(img2, cv2.COLOR_GRAY2BGR)
# cv2.drawContours(img, contours, i, (255,255,0), 3)
# cv2.imshow('contour', img)
# cv2.waitKey(0)
best_matches = np.argsort(match_values)[-3:][::-1]
limits = np.vstack(( contours[best_matches[0]].reshape(-1,2), contours[best_matches[1]].reshape(-1,2))).reshape(-1,2)
cropped_img = img2[:, np.min(limits[:,0]):np.max(limits[:,0]) ]
cv2.imwrite('cropped_img.png', cropped_img)