去除图像中的倾斜水平线

Removing slant horizontal lines in image

我有一张图像,其中文本下面有一条水平线;通过各种技术按顺序应用后HoughLineP 和 HoughLine 以及这段代码

 image = cv2.imread('D:\detect_words.jpg')
 gray = 255 - cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 for row in range(gray.shape[0]):
    avg = np.average(gray[row, :] > 16)
    if avg > 0.25:
        cv2.line(image, (0, row), (gray.shape[1]-1, row), (0, 0, 255))
        cv2.line(gray, (0, row), (gray.shape[1]-1, row), (0, 0, 0), 1)
  cv2.imwrite('D:\words\final_removed.jpg',image)

我可以做到这一点

在这个阶段之后;我正在应用腐蚀和膨胀

kernel = np.ones((3,3), np.uint8) 
img_erosion = cv2.erode(255-gray, kernel, iterations=1) 
img_dilation = cv2.dilate(img_erosion, kernel, iterations=1) 
cv2.imwrite('D:\words\final_removed4.jpg',255-img_dilation)

我的问题是;删除水平线虽然删除但单词有像素损失;并没有删除所有的水平线。有没有一种新的方法可以最小化这种损失并删除所有水平线(这里 AGE 以上的水平线仍然存在)。

这是一个方法:

  • 将图像转换为灰度
  • Otsu 获取二值图像的阈值
  • 创建水平内核并变形打开以检测线条
  • 查找等高线并绘制检测到的线

转换成灰度后,我们Otsu的阈值得到二值图像

image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

现在我们创建一个特殊的水平内核来检测水平线,然后变形打开以获得检测到的线的掩码

horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (45,1))
detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)

这是在原始图像上绘制的检测到的线条

从这里我们找到这个蒙版上的轮廓并绘制它们以有效去除水平线以获得我们的结果

cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

for c in cnts:
    cv2.drawContours(image, [c], -1, (255,255,255), 3)

既然水平线已被删除,要修复文本,您可以尝试 cv2.MORPH_CLOSE 使用 cv2.MORPH_CROSS 内核并尝试各种内核大小。在扩张太多与关闭漏洞之间需要权衡,因为文本中的细节将会丢失。另一种方法是使用 image inpainting 来填补漏洞。这一步交给你

完整代码

import cv2

image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (45,1))
detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)

cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

for c in cnts:
    cv2.drawContours(image, [c], -1, (255,255,255), 3)

cv2.imshow('thresh', thresh)
cv2.imshow('detected_lines', detected_lines)
cv2.imshow('image', image)
cv2.waitKey()