如何检测图像中相邻的2个或3个目标并获取其坐标?
多相邻目标检测实现方案
核心思路:先收集所有符合匹配条件的目标点,再通过距离判断筛选出相邻的点组,最后返回指定数量(2或3)的相邻目标坐标。
1. 修改原代码,收集所有匹配点
原代码仅保留相似度最高的单个点,我们需要先把所有符合阈值的目标点都收集起来:
# 替换原函数中找单个点的循环部分 match_threshold = 50 # 可根据匹配效果调整,值越小匹配越严格 target_points = [] for x in range(i_s[0]): for y in range(i_s[1]): i_p_s = c_s_i.getpixel((x, y)) d = diff(i_p_s, p) if d < match_threshold: target_points.append((x, y))
2. 定义相邻判断规则
以目标图像(findMe.png)的宽度为基准,设定相邻距离阈值——比如两个目标中心的距离小于目标宽度的1.5倍时,判定为相邻:
target_width, _ = s_i.size adjacent_threshold = target_width * 1.5 # 可根据实际布局调整倍数 def is_adjacent(p1, p2, threshold): # 计算两点欧氏距离 distance = ((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)**0.5 return distance < threshold
3. 分组相邻点并筛选指定数量的组
通过广度优先搜索把相邻的点归为一组,只保留包含指定数量(2或3)目标的组:
def group_adjacent_points(points, threshold, target_count): groups = [] visited = [False]*len(points) for i in range(len(points)): if not visited[i]: group = [] queue = [i] visited[i] = True while queue: idx = queue.pop(0) group.append(points[idx]) for j in range(len(points)): if not visited[j] and is_adjacent(points[idx], points[j], threshold): visited[j] = True queue.append(j) if len(group) == target_count: groups.append(group) return groups
4. 整合到原函数,添加参数支持指定检测数量
修改原函数g_c_o,新增target_count参数(传入2或3即可检测对应数量的相邻目标),兼容原有单个目标检测逻辑:
import time import base64 import pickle from PIL import Image def diff(a, b): return sum((a - b) ** 2 for a, b in zip(a, b)) def is_adjacent(p1, p2, threshold): distance = ((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)**0.5 return distance < threshold def group_adjacent_points(points, threshold, target_count): groups = [] visited = [False]*len(points) for i in range(len(points)): if not visited[i]: group = [] queue = [i] visited[i] = True while queue: idx = queue.pop(0) group.append(points[idx]) for j in range(len(points)): if not visited[j] and is_adjacent(points[idx], points[j], threshold): visited[j] = True queue.append(j) if len(group) == target_count: groups.append(group) return groups def g_c_o(c, _b, target_count=1): time.sleep(1) s_i_p = '' # 原代码未使用该变量,可考虑清理 c_b_64 = _b.execute_script("return arguments[0].toDataURL('image/png').substring(21);", c) c_i = base64.b64decode(c_b_64) with open(r"canvas.png", 'wb') as f: f.write(c_i) with open("files/important.pickle", "rb") as f: d_r = pickle.load(f) if s_i_p == '' and d_r[10] is not None and d_r[10] != '': s_i_p = d_r[10] c_s_i = Image.open('canvas.png') i_s = c_s_i.size s_i = Image.open("findMe.png") target_width, target_height = s_i.size x0, y0 = target_width//2, target_height//2 p = s_i.getpixel((x0, y0))[:-1] # 收集所有匹配点 match_threshold = 50 target_points = [] for x in range(i_s[0]): for y in range(i_s[1]): i_p_s = c_s_i.getpixel((x, y)) d = diff(i_p_s, p) if d < match_threshold: target_points.append((x, y)) if target_count == 1: # 兼容原有单个目标检测,返回相似度最高的点 if target_points: best_point = min(target_points, key=lambda pt: diff(c_s_i.getpixel(pt), p)) return [best_point] return [] else: # 返回指定数量的相邻目标组 adjacent_threshold = target_width * 1.5 return group_adjacent_points(target_points, adjacent_threshold, target_count)
调整建议
- 若匹配点过多/过少,修改
match_threshold值:值越小,匹配越严格,保留的点越少。 - 若相邻判断不准确,调整
adjacent_threshold的倍数:比如目标间距较小时,可设为1.2倍;间距较大时设为2倍。 - 如果存在多组符合条件的相邻目标,函数会返回所有组的列表,可根据需求取第一个或全部。
内容的提问来源于stack exchange,提问作者Agan
相关产品推荐
相关产品推荐

