在opencv python中阅读png文件时仅删除棋盘模式

x6h2sr28  于 2022-11-15  发布在  Python
关注(0)|答案(1)|浏览(142)

在移除棋盘格图案时遇到问题。我使用的是cv2.Threshold,但它也选择了意外的像素(红色标记)。

import cv2
import numpy as np

input = cv2.imread('image.png')
ret, logo_mask = cv2.threshold(input[:,:,0], 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
cv2.imshow(logo_mask)

输入图像:

输出图像:

有人能帮忙吗?

trnvg8h3

trnvg8h31#

获得涵盖所有情况的完美结果具有挑战性。
下面的解决方案假定白色棋盘颜色为(255,255,255),灰色为(230,230,230)。
另一个假设是在图像的其他部分中具有该特定颜色的聚类非常小。
我们可以使用以下阶段:

  • 找出颜色为(255,255,255)和(230,230,230)的“白色遮罩”和“灰色遮罩”。
  • 使用按位或创建统一掩码。
  • 查找轮廓,并从遮罩中移除小轮廓(假定为“噪声”)。

代码示例:

import cv2
import numpy as np

input = cv2.imread('image.png')

white_mask = np.all(input == 255, 2).astype(np.uint8)*255  # cv2.inRange(input, (255, 255, 255), (255, 255, 255))
gray_mask = np.all(input == 230, 2).astype(np.uint8)*255  # gray_mask = cv2.inRange(input, (230, 230, 230), (230, 230, 230))

mask = cv2.bitwise_or(white_mask, gray_mask)  # Create unified mask

ctns = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]  # Find contours

# Remove small contours from mask
for c in ctns:
    area = cv2.contourArea(c)  # Find the area of each contours
    if (area < 10):  # Ignore small contours (assume noise).
        cv2.drawContours(mask, [c], 0, 0, -1)

mask = cv2.dilate(mask, np.ones((3, 3), np.uint8))  # Dilate the mask - "cosmetics"

output = cv2.copyTo(input, 255-mask)  # Put black color in the masked part.

# Show images for testing
cv2.imshow('input', input)
cv2.imshow('mask', mask)
cv2.imshow('output', output)
cv2.waitKey()
cv2.destroyAllWindows()

white_mask

gray_mask

mask

output

如果前景部分存在大的白色区域或灰色区域,则上述解决方案可能不起作用。
我想到了一个过程,只寻找白色和灰色矩形之间的边界重叠的区域。
它不起作用,因为树分支之间的小部分被排除在外。
下面的代码可能会给予你一些启发:

import cv2
import numpy as np

input = cv2.imread('image.png')
#ret, logo_mask = cv2.threshold(input[:,:,0], 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)

white_mask = np.all(input == 255, 2).astype(np.uint8)*255  # cv2.inRange(input, (255, 255, 255), (255, 255, 255))
gray_mask = np.all(input == 230, 2).astype(np.uint8)*255  # gray_mask = cv2.inRange(input, (230, 230, 230), (230, 230, 230))

cv2.imwrite('white_mask.png', white_mask)
cv2.imwrite('gray_mask.png', gray_mask)

# Apply opening for removing small clusters
opened_white_mask = cv2.morphologyEx(white_mask, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
opened_gray_mask = cv2.morphologyEx(gray_mask, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))

cv2.imwrite('opened_white_mask.png', opened_white_mask)
cv2.imwrite('opened_gray_mask.png', opened_gray_mask)

white_mask_shell = cv2.dilate(opened_white_mask, np.ones((3, 3), np.uint8)) - opened_white_mask  # Dilate white_mask and keep only the "shell"
gray_mask_shell = cv2.dilate(opened_gray_mask, np.ones((3, 3), np.uint8)) - opened_gray_mask # Dilate gray_mask and keep only the "shell"
white_mask_shell = cv2.dilate(white_mask_shell, np.ones((3, 3), np.uint8)) # Dilate the "shell"
gray_mask_shell = cv2.dilate(gray_mask_shell, np.ones((3, 3), np.uint8)) # Dilate the "shell"

cv2.imwrite('white_mask_shell.png', white_mask_shell)
cv2.imwrite('gray_mask_shell.png', gray_mask_shell)

overlap_shell = cv2.bitwise_and(white_mask_shell, gray_mask_shell)
cv2.imwrite('overlap_shell.png', overlap_shell)

dilated_overlap_shell = cv2.dilate(overlap_shell, np.ones((17, 17), np.uint8))

mask = cv2.bitwise_or(cv2.bitwise_and(white_mask, dilated_overlap_shell), cv2.bitwise_and(gray_mask, dilated_overlap_shell))

cv2.imshow('input', input)
cv2.imshow('white_mask', white_mask)
cv2.imshow('gray_mask', gray_mask)
cv2.imshow('white_mask', white_mask)
cv2.imshow('gray_mask', gray_mask)
cv2.imshow('opened_white_mask', opened_white_mask)
cv2.imshow('opened_gray_mask', opened_gray_mask)
cv2.imshow('overlap_shell', overlap_shell)
cv2.imshow('dilated_overlap_shell', dilated_overlap_shell)
cv2.imshow('mask', mask)
cv2.waitKey()
cv2.destroyAllWindows()

相关问题