如题,我想把图中断掉的线条去掉,其它部分保持不变。

去除的效果如下图所示:使用到的方法是调用skimage库中的 morphology.remove_small_objects,过滤的阈值可以自己设置,我设置的为100.

python
import numpy as np
import cv2
from skimage import morphology
import matplotlib.pyplot as plt
from pathlib import Path
def process_image(input_path, output_path_prefix='processed', min_size=200):
"""
处理彩色PNG图片:
1. 将非黑色像素转为白色线条(二值化)
2. 去除小物体
3. 恢复原始彩色
4. 保存结果
参数:
- input_path: 输入图片路径
- output_path_prefix: 输出文件前缀
- min_size: 去除小物体的最小尺寸(像素数)
"""
# 1. 读取彩色图片
print(f"读取图片: {input_path}")
original_image = cv2.imread(input_path, cv2.IMREAD_UNCHANGED)
if original_image is None:
raise FileNotFoundError(f"无法读取图片: {input_path}")
# 如果图片有透明通道,移除它(只处理RGB)
if original_image.shape[2] == 4:
original_image_rgb = cv2.cvtColor(original_image, cv2.COLOR_BGRA2BGR)
print("检测到透明通道,已移除")
else:
original_image_rgb = original_image
# 转换为RGB格式用于显示
original_image_rgb_display = cv2.cvtColor(original_image_rgb, cv2.COLOR_BGR2RGB)
# 2. 创建二值图像(将所有非黑色像素转为白色)
# 将BGR转为灰度图
gray = cv2.cvtColor(original_image_rgb, cv2.COLOR_BGR2GRAY)
# 方法1:使用阈值处理(适用于纯黑色背景)
# 阈值设为1(因为纯黑色是0),大于1的都转为白色
_, binary_mask = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)
# 方法2:或者使用颜色范围检测(更鲁棒,检测所有非黑色像素)
# 将图片转为HSV颜色空间,更好地检测颜色
hsv = cv2.cvtColor(original_image_rgb, cv2.COLOR_BGR2HSV)
# 创建掩码:非黑色的所有像素
# 黑色通常对应低亮度值
lower_bound = np.array([0, 0, 1]) # 最小亮度为1(避免纯黑色)
upper_bound = np.array([180, 255, 255]) # HSV的最大值
color_mask = cv2.inRange(hsv, lower_bound, upper_bound)
# 使用颜色掩码作为二值图像
binary_image = color_mask.copy()
print(f"二值图像创建完成,白色像素数: {np.sum(binary_image > 0)}")
# 3. 使用skimage去除小物体
print(f"去除小物体 (min_size={min_size})...")
# 将0-255的二值图像转为True/False(True表示前景)
binary_bool = binary_image > 0
cleaned_binary_bool = morphology.remove_small_objects(binary_bool, min_size=min_size)
# 转换回0-255图像
cleaned_binary = (cleaned_binary_bool * 255).astype(np.uint8)
print(f"去除小物体后,白色像素数: {np.sum(cleaned_binary > 0)}")
# 4. 从过滤后的二值图像中恢复彩色
print("恢复彩色...")
# 创建彩色结果图像(黑色背景)
color_result = np.zeros_like(original_image_rgb)
# 将二值掩码应用到原始彩色图像
# 方法1:直接使用掩码
for c in range(3): # 对每个颜色通道
color_result[:, :, c] = original_image_rgb[:, :, c] * (cleaned_binary > 0)
# 方法2:使用cv2.bitwise_and(更高效)
# color_result = cv2.bitwise_and(original_image_rgb, original_image_rgb, mask=cleaned_binary)
# 转换为RGB格式用于显示
color_result_rgb = cv2.cvtColor(color_result, cv2.COLOR_BGR2RGB)
# 5. 保存处理后的图片
input_path_obj = Path(input_path)
stem = input_path_obj.stem
# 保存二值图像(处理后)
binary_output_path = f"{output_path_prefix}_{stem}_binary.png"
cv2.imwrite(binary_output_path, cleaned_binary)
print(f"二值图像已保存: {binary_output_path}")
# 保存彩色结果图像
color_output_path = f"{output_path_prefix}_{stem}_color.png"
# 需要将RGB转回BGR保存
cv2.imwrite(color_output_path, color_result)
print(f"彩色结果图像已保存: {color_output_path}")
# 6. 显示结果
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
# 原始彩色图像
axes[0, 0].imshow(original_image_rgb_display)
axes[0, 0].set_title('原始彩色图像')
axes[0, 0].axis('off')
# 原始灰度图
axes[0, 1].imshow(gray, cmap='gray')
axes[0, 1].set_title('原始灰度图')
axes[0, 1].axis('off')
# 二值图像(处理前)
axes[0, 2].imshow(binary_image, cmap='gray')
axes[0, 2].set_title('二值图像(处理前)')
axes[0, 2].axis('off')
# 二值图像(处理后)
axes[1, 0].imshow(cleaned_binary, cmap='gray')
axes[1, 0].set_title(f'二值图像(处理后,min_size={min_size})')
axes[1, 0].axis('off')
# 彩色结果
axes[1, 1].imshow(color_result_rgb)
axes[1, 1].set_title('恢复的彩色图像')
axes[1, 1].axis('off')
# 显示处理的像素变化
axes[1, 2].bar(['before process', 'after process'],
[np.sum(binary_image > 0), np.sum(cleaned_binary > 0)])
axes[1, 2].set_title('白色像素数量变化')
axes[1, 2].set_ylabel('pixels')
plt.tight_layout()
plt.show()
return {
'original': original_image_rgb,
'binary': binary_image,
'cleaned_binary': cleaned_binary,
'color_result': color_result,
'binary_path': binary_output_path,
'color_path': color_output_path
}
# 使用示例
if __name__ == "__main__":
# 替换为您的图片路径
input_image_path = "bear_23_colored_greendelete_headmask.png" # 请将这里替换为您的图片路径
try:
# 处理图片
results = process_image(
input_path=input_image_path,
output_path_prefix='processed', # 输出文件前缀
min_size=100 # 调整这个值来控制去除小物体的大小阈值
)
print("\n处理完成!")
print(f"二值图像保存为: {results['binary_path']}")
print(f"彩色结果保存为: {results['color_path']}")
except FileNotFoundError as e:
print(f"错误: {e}")
print("请确保图片路径正确,并且图片存在。")
except Exception as e:
print(f"处理过程中出现错误: {e}")
print("请确保已安装必要的库: pip install opencv-python scikit-image matplotlib numpy")
提示词:帮我写一个可以直接运行的代码,读取一个彩色的png图片,我的图片是纯黑色背景的,我需要你先将图片中所有内容变成白色的线条,黑色的背景,也就是二值图像。注意不要将蓝色、紫色那种颜色漏掉,是图片内的所有有颜色的像素都变成白色的,然后使用这张二值图,调用skimage库中的 morphology.remove_small_objects,处理后,一些杂碎的线条将会被过滤掉。我需要你返回的是我原来彩色的图片,也就是说,要从过滤后的二值图像中恢复原来彩色图片对应的颜色。并同时保存处理后的图片。