使用 Python 从图像中屏蔽掉较大的不规则形状

Masked out large irregular shape from image with Python

objective是去除大的不规则区域,只保留图像中的字符。

例如,给定以下内容

和预期的 masked output

我的印象是这可以实现如下

import cv2
import numpy as np
from matplotlib import pyplot as plt

dpath='remove_bg1.jpg'

img = cv2.imread(dpath)

img_fh=img.copy()
cv2.bitwise_not(img_fh,img_fh)
ksize=10
kernel = np.ones((ksize,ksize),np.uint8)
erosion = cv2.erode(img_fh,kernel,iterations = 3)
invertx = cv2.bitwise_not(erosion)
masked = cv2.bitwise_not(cv2.bitwise_and(img_fh,invertx))

all_image=[img,invertx,masked]
ncol=len(all_image)
for idx, i in enumerate(all_image):
    plt.subplot(int(f'1{ncol}{idx+1}')),plt.imshow(i)

plt.show()

产生

显然,上面的代码没有产生预期的结果。

我可以知道如何正确解决这个问题吗?

要删除不需要的斑点,我们必须创建一个遮罩,使其完全封闭。

流量:

  1. 反向二值化图像(这样你就有一个白色的前景与黑暗的背景)
  2. Dilate 图像(因为 blob 与字母 'A' 接触,它必须被隔离)
  3. 求面积最大的轮廓
  4. 在另一张单通道图像上绘制轮廓加厚(膨胀)
  5. 像素分配:包含膨胀斑点的像素在原始图像上变为白色

代码:

im = cv2.imread('stained_text.jpg')
im2 = im.copy()
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

# inverse binaraization
th = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

注意接触字母 'A' 的斑点区域。因此,为了隔离它,我们使用椭圆核

执行侵蚀
# erosion
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
erode = cv2.erode(th, kernel, iterations=2)

# find contours
contours, hierarchy = cv2.findContours(erode, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Contour of maximum area
c = max(contours, key = cv2.contourArea)

# create 1-channel image in black 
black = np.zeros((im.shape[0], im.shape[1]), np.uint8)
# draw the contour on it
black = cv2.drawContours(black, [c], 0, 255, -1)
# perform dilation to have clean border
# we are using the same kernel
dilate = cv2.dilate(black, kernel, iterations = 3)

# assign the dilated area in white over the original image
im2[dilate == 255] = (255,255,255)

This was just one of the many possible ways on how to proceed. The key thing to note is how to isolate the blob.