Files
jigsaw/extract_mask.py
2024-12-03 11:34:51 +13:00

93 lines
2.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import cv2
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
# 读取图像
image_path = 'jigsaw_mask.png' # 替换为您的图像路径
image = cv2.imread(image_path)
if image is None:
raise ValueError("无法读取图像,请检查路径是否正确。")
# 转换为RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 应用固定阈值进行二值化
_, mask = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
# 进行形态学操作以连接断裂的线条
# 定义较大的核
kernel = np.ones((1,1), np.uint8)
# 增加膨胀次数以连接断裂
mask = cv2.dilate(mask, kernel, iterations=1)
# 闭运算进一步连接
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=5)
# 再次确保掩膜是二值的
_, mask = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)
# 创建 Alpha 通道
alpha = cv2.bitwise_not(mask)
# 确保 Alpha 通道只有0和255
alpha = cv2.threshold(alpha, 127, 255, cv2.THRESH_BINARY)[1]
# 创建纯白色背景
white_bg = 255 * np.ones_like(image_rgb, dtype=np.uint8)
# 合并 RGB 图像和 Alpha 通道
final_rgb = cv2.bitwise_and(white_bg, white_bg, mask=cv2.bitwise_not(mask))
image_rgba = cv2.cvtColor(final_rgb, cv2.COLOR_RGB2RGBA)
image_rgba[:, :, 3] = alpha
# 将 OpenCV 的 RGBA 图像转换为 Pillow Image 对象
image_pil = Image.fromarray(image_rgba)
# 转换为 NumPy 数组以进一步处理
data = np.array(image_pil)
# 分离颜色通道
red, green, blue, alpha = data.T
# 定义黑色的阈值范围
black_threshold = 50 # 根据需要调整
# 创建掩膜黑色区域为True其余为False
black_areas = (red < black_threshold) & (green < black_threshold) & (blue < black_threshold)
# 设置黑色区域的 Alpha 为0非黑色区域的 Alpha 为255
data[..., 3][black_areas.T] = 0
data[..., 3][~black_areas.T] = 255
# 将非黑色区域设置为纯白色
data[..., 0:3][~black_areas.T] = [255, 255, 255]
# 创建新的 Image 对象
final_image = Image.fromarray(data)
# 保存结果为 PNG支持透明度
output_path = 'mask.png'
final_image.save(output_path)
print(f"已保存带纯白背景和透明部分的图像到 {output_path}")
# 可选:显示图像
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
plt.title('原图')
plt.imshow(image_rgb)
plt.axis('off')
plt.subplot(1,2,2)
plt.title('带纯白背景和透明部分的图像')
plt.imshow(final_image)
plt.axis('off')
plt.show()