如何为指定像素所属同色连续像素块的边界着色?
为指定像素所属同颜色连续块的边界着色
原图像生成代码
我使用以下代码生成了一张包含5种随机颜色的像素图:
from PIL import Image import random w, h = 40, 27 img = Image.new("RGB", (w,h)) pixels = img.load() available_colors = { 'r': (255, 13, 18), 'b': (72, 64, 255), 'y': (236, 236, 1), 'p': (208, 1, 239), 'g': (37, 252, 32), } for i in range(w): for j in range(h): pixels[i,j] = random.choice(list(available_colors.values())) # 放大便于观察 img = img.resize((15*w,15*h), Image.NEAREST)
原图像

需求说明
给定图像中任意像素坐标(如(0,0)),为该像素所属的同颜色连续像素块的最外层两个像素涂黑,预期效果如下:
实现方案(基于OpenCV)
工具选择
OpenCV是处理这类区域分割与边界提取任务的首选工具,内置连通域分析、轮廓检测、形态学操作等功能,无需手动实现复杂算法。
核心步骤
- 定位目标连通块:获取指定像素的颜色,筛选图像中同颜色像素,通过连通域分析锁定目标像素所属的连续块(排除其他同颜色但不相连的区域)。
- 生成双层边界:提取目标块的轮廓,通过膨胀操作将轮廓向外扩展1像素,得到两层边界区域。
- 边界着色:在原图像上将双层边界区域涂黑。
完整代码
import cv2 import numpy as np from PIL import Image import random # 生成原图像(复用原有代码) w, h = 40, 27 img = Image.new("RGB", (w,h)) pixels = img.load() available_colors = { 'r': (255, 13, 18), 'b': (72, 64, 255), 'y': (236, 236, 1), 'p': (208, 1, 239), 'g': (37, 252, 32), } for i in range(w): for j in range(h): pixels[i,j] = random.choice(list(available_colors.values())) img = img.resize((15*w,15*h), Image.NEAREST) cv_img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) # 处理边界着色 target_x, target_y = 0, 0 # 指定目标像素坐标 target_color = cv_img[target_y, target_x].tolist() # 1. 创建同颜色掩码 mask = cv2.inRange(cv_img, np.array(target_color), np.array(target_color)) # 2. 连通域分析,定位目标块 num_labels, labels, _, _ = cv2.connectedComponentsWithStats(mask, connectivity=8) target_label = labels[target_y, target_x] target_mask = np.where(labels == target_label, 255, 0).astype(np.uint8) # 3. 提取轮廓并生成双层边界 contours, _ = cv2.findContours(target_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) border_mask = np.zeros_like(target_mask) cv2.drawContours(border_mask, contours, -1, 255, thickness=1) # 第一层边界 # 膨胀得到第二层边界 kernel = np.ones((3,3), np.uint8) dilated_border = cv2.dilate(border_mask, kernel, iterations=1) final_border = cv2.bitwise_or(border_mask, dilated_border) # 4. 涂黑边界 result = cv_img.copy() result[final_border == 255] = (0, 0, 0) # 转换回PIL格式查看 result_pil = Image.fromarray(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)) result_pil.show()
关键操作解释
- 连通域分析:
cv2.connectedComponentsWithStats将图像中相连的同色区域标记为不同块,确保只处理目标像素所在的连续区域,避免误操作其他同色块。 - 轮廓提取:
cv2.findContours获取块的最外层边缘,thickness=1绘制1像素宽的边界。 - 膨胀操作:
cv2.dilate将原始边界向外扩展1像素,合并后得到两层边界,满足“最外层两个像素涂黑”的需求。
内容的提问来源于stack exchange,提问作者ScientiaEtVeritas
相关产品推荐
相关产品推荐

