如何在图像中提取白色区域

时间:2015-10-05 05:13:15

标签: python opencv image-processing computer-vision

我有一个像这样的样本图片

enter image description here

我正在寻找一种方法来消除图像中的噪音,这样我最终得到的图像在白色背景上只有黑色文字,这样我就可以将它发送到tesseract。

我尝试用

进行变形
kernel = np.ones((4,4),np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imshow("opening", opening)

但它似乎不起作用。

我也试图找到轮廓

img = cv2.cvtColor(rotated, cv2.COLOR_BGR2GRAY)
(cnts, _) = cv2.findContours(img, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    roi=rotated[y:y+h,x:x+w].copy()
    cv2.imwrite("roi.png", roi)

使用上面的代码,我得到以下轮廓:

enter image description here

在裁剪时会导致此图像:

enter image description here

仍然不够好。我想要在白色背景上的黑色文字,以便我可以将它发送到tesseract OCR并具有良好的成功率。

还有什么我可以尝试的吗?

更新

这是一个额外的类似图像。这个有点容易,因为它有一个光滑的矩形

enter image description here

3 个答案:

答案 0 :(得分:4)

以下适用于您的示例,但可能需要针对更广泛的图像进行调整。

import numpy as np
import cv2

image_src = cv2.imread("input.png")
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY)
ret, gray = cv2.threshold(gray, 250,255,0)

image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
largest_area = sorted(contours, key=cv2.contourArea)[-1]
mask = np.zeros(image_src.shape, np.uint8)
cv2.drawContours(mask, [largest_area], 0, (255,255,255,255), -1)
dst = cv2.bitwise_and(image_src, mask)
mask = 255 - mask
roi = cv2.add(dst, mask)

roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
ret, gray = cv2.threshold(roi_gray, 250,255,0)
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

max_x = 0
max_y = 0
min_x = image_src.shape[1]
min_y = image_src.shape[0]

for c in contours:
    if 150 < cv2.contourArea(c) < 100000:
        x, y, w, h = cv2.boundingRect(c)
        min_x = min(x, min_x)
        min_y = min(y, min_y)
        max_x = max(x+w, max_x)
        max_y = max(y+h, max_y)

roi = roi[min_y:max_y, min_x:max_x]
cv2.imwrite("roi.png", roi)

为您提供以下类型的输出图像:

enter image description here

和...

enter image description here

代码的工作原理是首先找到最大的轮廓区域。由此创建掩模,该掩模用于首先仅选择内部区域,即文本。然后将掩模的反转添加到图像中,以将掩模外的区域转换为白色。

最后再次找到这张新图像的轮廓。丢弃适当大小范围之外的任何轮廓区域(这用于忽略任何小的噪声区域),并且为每个区域找到边界矩形。对于每个矩形,计算所有剩余轮廓的outer边界矩形,并使用这些值进行裁剪以给出最终图像。

更新 - 要获取图像的其余部分,即删除上述区域,可以使用以下内容:

image_src = cv2.imread("input.png")
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY)
ret, gray = cv2.threshold(gray, 10, 255,0)
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
largest_area = sorted(contours, key=cv2.contourArea)[-1]
mask = np.zeros(image_src.shape, np.uint8)
cv2.drawContours(mask, [largest_area], 0, (255,255,255,255), -1)
image_remainder = cv2.bitwise_and(image_src, 255 - mask)

cv2.imwrite("remainder.png", image_remainder)

答案 1 :(得分:0)

这个答案的基本思想是使用文本边框。

1)侵蚀 水平,内核非常大,比如大小为100像素,或者是单个预期字符大小的8倍,就像那样。它应该按行进行。极端纵坐标将给出文本边界的y位置。

2)以相同的方式处理垂直以获取文本边界的x位置。然后使用这些位置裁剪出您想要的图像。

- 这种方法的一个好处是你会得到每个句子/单词分开,我认为这对于OCR是好的。

快乐编码:)

由Mark Setchell编辑

以下是1)

的演示

enter image description here

以下是2)

的演示

enter image description here

答案 2 :(得分:0)

我明白了: Result

源代码:

if __name__ == '__main__':
  SrcImg = cv2.imread('./Yahi9.png', cv2.CV_LOAD_IMAGE_GRAYSCALE)
  _, BinImg = cv2.threshold(SrcImg, 80, 255, cv2.THRESH_OTSU)

  Contours, Hierarchy = cv2.findContours(image=copy.deepcopy(SrcImg),
                                         mode=cv2.cv.CV_RETR_EXTERNAL,
                                         method=cv2.cv.CV_CHAIN_APPROX_NONE)
  MaxContour, _ = getMaxContour(Contours)
  Canvas = np.ones(SrcImg.shape, np.uint8)
  cv2.drawContours(image=Canvas, contours=[MaxContour], contourIdx=0, color=(255), thickness=-1)
  mask = (Canvas != 255)
  RoiImg = copy.deepcopy(BinImg)
  RoiImg[mask] = 255
  RoiImg = cv2.morphologyEx(src=RoiImg, op=cv2.MORPH_CLOSE, kernel=np.ones((3,3)), iterations=4)
  cv2.imshow('RoiImg', RoiImg)
  cv2.waitKey(0)

功能:

def getMaxContour(contours):
  MaxArea = 0
  Location = 0
  for idx in range(0, len(contours)):
      Area = cv2.contourArea(contours[idx])
      if Area > MaxArea:
          MaxArea = Area
          Location = idx
  MaxContour = np.array(contours[Location])
  return MaxContour, MaxArea

呃,这是它的python代码。 它仅在白色区域为最大轮廓时有效。