You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为指定像素所属同色连续像素块的边界着色?

为指定像素所属同颜色连续块的边界着色

原图像生成代码

我使用以下代码生成了一张包含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)),为该像素所属的同颜色连续像素块的最外层两个像素涂黑,预期效果如下:
指定(0,0)后的边界着色效果


实现方案(基于OpenCV)

工具选择

OpenCV是处理这类区域分割与边界提取任务的首选工具,内置连通域分析、轮廓检测、形态学操作等功能,无需手动实现复杂算法。

核心步骤

  1. 定位目标连通块:获取指定像素的颜色,筛选图像中同颜色像素,通过连通域分析锁定目标像素所属的连续块(排除其他同颜色但不相连的区域)。
  2. 生成双层边界:提取目标块的轮廓,通过膨胀操作将轮廓向外扩展1像素,得到两层边界区域。
  3. 边界着色:在原图像上将双层边界区域涂黑。

完整代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:50:27