如何使用 OpenCV Python 在图像中仅保留黑色文本?

Vir*_*ngg 1 python opencv colors

我有以下图像:

这个图片

我想只保留黑色文本 0790 并从图片中删除所有文本。这个 stackoverflow 问题教我们如何去除颜色。但是,我需要保留颜色,而不是删除它。

sta*_*ine 13

一种可能的解决方案包括将图像转换为CMYK颜色空间并提取K(基色 - 黑色)通道、对其进行阈值处理并应用一些形态学来清理二值图像。

OpenCV 没有实现从BGR到 的转换CMYK,因此我们必须K手动计算通道。代码如下所示:

# Imports
import cv2
import numpy as np

# Read image
imagePath = "D://opencvImages//"
inputImage = cv2.imread(imagePath + "A6RXi.png")

# Conversion to CMYK (just the K channel):

# Convert to float and divide by 255:
imgFloat = inputImage.astype(np.float) / 255.

# Calculate channel K:
kChannel = 1 - np.max(imgFloat, axis=2)

# Convert back to uint 8:
kChannel = (255 * kChannel).astype(np.uint8)
Run Code Online (Sandbox Code Playgroud)

这是 K(黑色)通道:

现在,使用固定值对图像进行阈值处理。在这种情况下,我将阈值设置为190

# Threshold image:
binaryThresh = 190
_, binaryImage = cv2.threshold(kChannel, binaryThresh, 255, cv2.THRESH_BINARY)
Run Code Online (Sandbox Code Playgroud)

这是二值图像:

这是一点噪音,但如果我们实现区域过滤器,我们可以去除较小的斑点。该函数在本文末尾定义。让我们应用最小值为的过滤器100。所有小于此值的斑点都将被删除:

# Filter small blobs:
minArea = 100
binaryImage = areaFilter(minArea, binaryImage)
Run Code Online (Sandbox Code Playgroud)

这是过滤后的图像:

凉爽的。让我们用封闭过滤器改善斑点的形态:

# Use a little bit of morphology to clean the mask:
# Set kernel (structuring element) size:
kernelSize = 3
# Set morph operation iterations:
opIterations = 2
# Get the structuring element:
morphKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))
# Perform closing:
binaryImage = cv2.morphologyEx(binaryImage, cv2.MORPH_CLOSE, morphKernel, None, None, opIterations, cv2.BORDER_REFLECT101)

cv2.imshow("binaryImage [closed]", binaryImage)
cv2.waitKey(0)
Run Code Online (Sandbox Code Playgroud)

这是最终结果:

这就是areaFilter函数。它接收一个最小区域和一个二值图像,它返回没有小斑点的图像:

def areaFilter(minArea, inputImage):
    # Perform an area filter on the binary blobs:
    componentsNumber, labeledImage, componentStats, componentCentroids = \
        cv2.connectedComponentsWithStats(inputImage, connectivity=4)

    # Get the indices/labels of the remaining components based on the area stat
    # (skip the background component at index 0)
    remainingComponentLabels = [i for i in range(1, componentsNumber) if componentStats[i][4] >= minArea]

    # Filter the labeled pixels based on the remaining labels,
    # assign pixel intensity to 255 (uint8) for the remaining pixels
    filteredImage = np.where(np.isin(labeledImage, remainingComponentLabels) == True, 255, 0).astype('uint8')

    return filteredImage
Run Code Online (Sandbox Code Playgroud)