如何提取图像中的白色区域 [英] How to extract white region in an image

查看:1423
本文介绍了如何提取图像中的白色区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的示例图像





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



我试过变形

  kernel = np.ones ((4,4),np.uint8)
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
cv2.imshow(opening,opening)

但它似乎不起作用。



我也试图找到轮廓

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

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





在裁剪时会导致此图像:





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



还有什么可以尝试吗?



更新



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



解决方案

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

  import numpy as np 
import cv2

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

图像,等高线,等级= cv2.findContours(灰色,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(grey,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] $ b轮廓为c的
$ b:如果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)

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





并且......





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



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



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

  image_src = cv2.imread(input.png)
gray = cv2.cvtColor(image_src,cv2.COLOR_BGR2GRAY)
ret,grey = cv2.threshold(灰色,10,255,0)
图像,轮廓,层次= cv2.findContours(灰色,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
largest_area =已排序(轮廓,键= 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)


I have a sample image like this

I'm looking for a way to black out the noise from the image such that I end up with an image that just has black text on white background so that I may send it to tesseract.

I've tried morphing with

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

but it doesn't seem to work.

I've also tried to find contours

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)

With the above code, I get the following contours:

which leads to this image when cropped:

which is still not good enough. I want black text on white background, so that I can send it to tesseract OCR and have good success rate.

Is there anything else I can try?

Update

Here is an additional similar image. This one is a bit easier because it has a smooth rectangle in it

解决方案

The following works for your given example, although it might need tweaking for a wider range of images.

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)

Giving you the following type of output images:

And...

The code works by first locating the largest contour area. From this a mask is created which is used to first select only the area inside, i.e. the text. The inverse of the mask is then added to the image to convert the area outside the mask to white.

Lastly contours are found again for this new image. Any contour areas outside a suitable size range are discarded (this is used to ignore any small noise areas), and a bounding rect is found for each. With each of these rectangles, an outer bounding rect is calculated for all of the remaining contours, and a crop is made using these values to give the final image.

Update - To get the remainder of the image, i.e. with the above area removed, the following could be used:

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)

这篇关于如何提取图像中的白色区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆