如何在不丢失opencv信息的情况下分割手写和印刷数字?
How to Segment handwritten and printed digit without losing information in opencv?
我已经编写了一个算法来检测印刷和手写数字并对其进行分割,但是在使用 ski-image 包中的 clear_border 删除外部矩形手写数字时会丢失。任何阻止信息的建议。
样本:
如何分别获取全部5个字符?
eroded/cropped手写数字问题:
你可以在识别步骤中解决这个问题,甚至在图像改进步骤中(识别之前)。
- 如果只有一小部分数字被裁剪(例如您的图像示例),将图像填充 1 或 2 个像素就足以使分割过程变得容易。或者一些 morpho 过滤器(扩张)甚至可以在填充后改善你的数字。 (这些解决方案在 Opencv 中可用)
- 如果裁剪了足够好的数字部分,则需要将 degraded/cropped 数字模式添加到用于数字识别算法的训练数据集中,(即数字 3 以及所有可能的裁剪情况等) )
字符分隔问题:
opencv 提供的 blob 检测算法可以很好地解决您的问题(为凹凸参数选择正确的值)
opencv 还提供轮廓检测器(canny() 函数),它有助于检测角色的轮廓,然后您可以找到合适的边界( Opencv 也提供:cv2.approxPolyDP(contour,..,..)) box around each character
从图像中分割字符 -
接近 -
- 阈值图像(将其转换为 BW)
- 执行扩张
- 检查轮廓是否足够大
- 查找矩形轮廓
- 获取ROI并保存角色
Python代码-
# import the necessary packages
import numpy as np
import cv2
import imutils
# load the image, convert it to grayscale, and blur it to remove noise
image = cv2.imread("sample1.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)
# threshold the image
ret,thresh1 = cv2.threshold(gray ,127,255,cv2.THRESH_BINARY_INV)
# dilate the white portions
dilate = cv2.dilate(thresh1, None, iterations=2)
# find contours in the image
cnts = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
orig = image.copy()
i = 0
for cnt in cnts:
# Check the area of contour, if it is very small ignore it
if(cv2.contourArea(cnt) < 100):
continue
# Filtered countours are detected
x,y,w,h = cv2.boundingRect(cnt)
# Taking ROI of the cotour
roi = image[y:y+h, x:x+w]
# Mark them on the image if you want
cv2.rectangle(orig,(x,y),(x+w,y+h),(0,255,0),2)
# Save your contours or characters
cv2.imwrite("roi" + str(i) + ".png", roi)
i = i + 1
cv2.imshow("Image", orig)
cv2.waitKey(0)
首先,我对图像进行了阈值处理,将其转换为黑白。我得到图像白色部分的字符和黑色背景。然后我放大图像使字符(白色部分)变粗,这样可以很容易地找到合适的轮廓。然后 find findContours 方法用于查找轮廓。然后我们需要检查轮廓是否足够大,如果轮廓不够大则忽略它(因为那个轮廓是噪声)。然后使用 boundingRect 方法找到轮廓的矩形。最后,保存并绘制检测到的轮廓。
输入图像-
阈值 -
膨胀 -
轮廓 -
保存的字符 -
我已经编写了一个算法来检测印刷和手写数字并对其进行分割,但是在使用 ski-image 包中的 clear_border 删除外部矩形手写数字时会丢失。任何阻止信息的建议。
样本:
如何分别获取全部5个字符?
eroded/cropped手写数字问题: 你可以在识别步骤中解决这个问题,甚至在图像改进步骤中(识别之前)。
- 如果只有一小部分数字被裁剪(例如您的图像示例),将图像填充 1 或 2 个像素就足以使分割过程变得容易。或者一些 morpho 过滤器(扩张)甚至可以在填充后改善你的数字。 (这些解决方案在 Opencv 中可用)
- 如果裁剪了足够好的数字部分,则需要将 degraded/cropped 数字模式添加到用于数字识别算法的训练数据集中,(即数字 3 以及所有可能的裁剪情况等) )
字符分隔问题:
opencv 提供的 blob 检测算法可以很好地解决您的问题(为凹凸参数选择正确的值)
opencv 还提供轮廓检测器(canny() 函数),它有助于检测角色的轮廓,然后您可以找到合适的边界( Opencv 也提供:cv2.approxPolyDP(contour,..,..)) box around each character
从图像中分割字符 -
接近 -
- 阈值图像(将其转换为 BW)
- 执行扩张
- 检查轮廓是否足够大
- 查找矩形轮廓
- 获取ROI并保存角色
Python代码-
# import the necessary packages
import numpy as np
import cv2
import imutils
# load the image, convert it to grayscale, and blur it to remove noise
image = cv2.imread("sample1.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)
# threshold the image
ret,thresh1 = cv2.threshold(gray ,127,255,cv2.THRESH_BINARY_INV)
# dilate the white portions
dilate = cv2.dilate(thresh1, None, iterations=2)
# find contours in the image
cnts = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
orig = image.copy()
i = 0
for cnt in cnts:
# Check the area of contour, if it is very small ignore it
if(cv2.contourArea(cnt) < 100):
continue
# Filtered countours are detected
x,y,w,h = cv2.boundingRect(cnt)
# Taking ROI of the cotour
roi = image[y:y+h, x:x+w]
# Mark them on the image if you want
cv2.rectangle(orig,(x,y),(x+w,y+h),(0,255,0),2)
# Save your contours or characters
cv2.imwrite("roi" + str(i) + ".png", roi)
i = i + 1
cv2.imshow("Image", orig)
cv2.waitKey(0)
首先,我对图像进行了阈值处理,将其转换为黑白。我得到图像白色部分的字符和黑色背景。然后我放大图像使字符(白色部分)变粗,这样可以很容易地找到合适的轮廓。然后 find findContours 方法用于查找轮廓。然后我们需要检查轮廓是否足够大,如果轮廓不够大则忽略它(因为那个轮廓是噪声)。然后使用 boundingRect 方法找到轮廓的矩形。最后,保存并绘制检测到的轮廓。
输入图像-
阈值 -
膨胀 -
轮廓 -
保存的字符 -