如何检测非规则形状轮廓,基于中心黑点锚点从图像中裁剪目标区域
解决方案
你这个场景非常适合用漫水填充(洪水填充) 算法实现,核心逻辑是从中心锚点出发,遍历所有连通的内部区域,碰到预设的边界色就停止,完全不受形状规则度限制,对小边界孔洞也有不错的容错性,实现步骤如下:
前置优化
先把你预存的边界RGB值转成Python集合,查找效率比循环遍历Excel行高两个数量级:
import numpy as np from PIL import Image import pandas as pd # 读取图像,加alpha通道方便后续输出透明背景 image = Image.open("你的图像路径").convert("RGBA") rgb_arr = np.array(image.convert("RGB")) # 转numpy数组加速像素操作 # 读取预存边界色,转成集合格式 line_df = pd.read_excel("C:/Users/lines RGb.xlsx") boundary_colors = set( (r,g,b) for r,g,b in zip(line_df.iloc[:,0], line_df.iloc[:,1], line_df.iloc[:,2]) )
步骤1:定位中心锚点
# 查找所有RGB值为(77,77,77)的锚点像素 target_anchor = (77,77,77) anchor_pixels = np.argwhere(np.all(rgb_arr == target_anchor, axis=-1)) # 取众数作为中心坐标,注意numpy数组坐标为(y,x),需要适配PIL的(x,y)格式 center_y = int(np.bincount(anchor_pixels[:,0]).argmax()) center_x = int(np.bincount(anchor_pixels[:,1]).argmax())
步骤2:漫水填充获取内部区域掩码
h, w = rgb_arr.shape[:2] mask = np.zeros((h, w), dtype=bool) # 掩码规则:True表示属于地块内部 queue = [(center_x, center_y)] mask[center_y, center_x] = True # 8方向遍历,比4方向容错性更高,适配有小缺口的边界 directions = [(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)] while queue: x, y = queue.pop(0) for dx, dy in directions: nx = x + dx ny = y + dy # 跳过超出图像范围的坐标 if 0 <= nx < w and 0 <= ny < h: # 跳过已标记、以及属于边界色的像素 if not mask[ny, nx] and tuple(rgb_arr[ny, nx]) not in boundary_colors: mask[ny, nx] = True queue.append((nx, ny)) # 可选:处理边界小孔洞,做一次形态学闭运算补洞 from scipy.ndimage import binary_closing mask = binary_closing(mask, structure=np.ones((3,3))).astype(bool)
步骤3:提取目标区域
两种输出方式按需选择:
方式1:保留不规则形状,背景透明
# 把掩码外的区域alpha通道设为0(透明) alpha_arr = np.array(image.getchannel("A")) alpha_arr[~mask] = 0 image.putalpha(Image.fromarray(alpha_arr)) # 可选:裁掉周围全透明的多余边距 bbox = image.getbbox() cropped_img = image.crop(bbox) cropped_img.save("输出路径.png")
方式2:仅裁出包含目标区域的最小外接矩形
# 找掩码的上下左右边界 ys, xs = np.where(mask) min_x, max_x = xs.min(), xs.max() min_y, max_y = ys.min(), ys.max() cropped_img = image.crop((min_x, min_y, max_x, max_y)) cropped_img.save("输出路径.jpg")
适配特殊场景的优化方案
- 如果存在图像压缩导致的边界色偏,可以把精确颜色匹配改成颜色距离判断:计算当前像素和边界色的欧式距离,小于阈值就算是边界
- 如果边界孔洞较大,可以先提取所有边界色像素生成边界掩码,做闭运算补洞后再执行漫水填充
内容的提问来源于stack exchange,提问作者Benzo
相关产品推荐
相关产品推荐

