我正在尝试编写一些代码来检测我的 png 文件是否只是一个部分或包含多个部分(各部分之间是透明的)。
我在网上找到了一些代码,但它总是告诉我我的png有多个部分。
import numpy as np
from PIL import Image
from scipy import ndimage
def has_multiple_parts(image_path, threshold=10):
try:
# Open the image using Pillow
img = Image.open(image_path)
# Convert the image to a NumPy array
img_array = np.array(img)
# Convert the image to grayscale (if it's not already)
if len(img_array.shape) == 3:
img_gray = img.convert('L')
img_array = np.array(img_gray)
# Apply binary thresholding to create a mask
mask = img_array < threshold
# Label connected components in the mask
labeled_regions, num_regions = ndimage.label(mask)
# If there is only one labeled region, it's considered as one part
return num_regions == 1
except Exception as e:
print(f"Error: {e}")
return False
image_path = "c:\\Documents\\Genshin-1-part-png.png"
if has_multiple_parts(image_path):
print(f"{image_path} has only one part.")
else:
print(f"{image_path} has more than one part.")
我想出的最佳解决方案是使用 alpha 通道(透明通道)来计算区域。当图像透明时,该通道的值为 0;当图像不透明时,该通道的值为 255。要以 RGBA 模式打开图像,我使用 OpenCV 库,我不知道是否还有其他选项。
打开图像后,您可以将阈值应用于第四个通道(alpha)以创建蒙版,并使用 scipy 对其进行标记。
最后,使用条件
num_regions <= 2
很重要,因为 if:
这里有完整的代码:
from scipy import ndimage
import cv2
def has_multiple_parts(image_path, threshold=1):
try:
# Open the image using OpenCV in RGBA mode
img_rgba = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
# Take the alpha channel (transparency)
alpha_channel = img_rgba[:,:,3]
# Apply binary thresholding to create a mask
mask = alpha_channel < threshold
# Label connected components in the mask
labeled_regions, num_regions = ndimage.label(mask)
# If there are one or two labeled region, it means there is just one part
return num_regions <= 2
except Exception as e:
print(f"Error: {e}")
return False
image_path = "Genshin-1-part-png.png"
if has_multiple_parts(image_path):
print(f"{image_path} has only one part.")
else:
print(f"{image_path} has more than one part.")