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

圆重叠检测优化:实现红蓝圆一对一匹配,去除重复重叠对

嗨,这个问题我之前也帮别人解决过,本质是要实现红、蓝圆之间的双向一对一最优匹配,避免一个圆被多个配对占用。咱们可以用「贪心匹配+距离优先」或者更严谨的「匈牙利算法」来搞定,下面给你具体的思路和代码修改方案:

核心解决思路

其实就是把这个问题转化为二分图的最优匹配问题:红圆和蓝圆是两个独立的集合,重叠的圆之间有连接边,边的权重是它们的中心距离,我们要找到一组边,让每个红/蓝圆最多出现在一条边里,同时优先选距离最近的配对。

具体分三步:

  • 第一步:先找出所有满足重叠条件的红-蓝圆对,同时记录每一对的中心距离
  • 第二步:对这些候选配对按距离从小到大排序(贪心思路),或者构建距离矩阵用匈牙利算法找全局最优
  • 第三步:遍历配对,给每个圆标记「已匹配」状态,确保每个圆只被配对一次
代码实现方案

方案1:贪心匹配(简单高效,适合中小规模数据)

假设你已经有红圆列表red_circles(每个元素是(x坐标, y坐标, 半径))和蓝圆列表blue_circles,直接套下面的代码逻辑:

import matplotlib.pyplot as plt

# 替换成你实际的红圆、蓝圆数据
red_circles = [(1, 1, 0.8), (1.2, 1.1, 0.7), (3, 3, 0.6)]
blue_circles = [(1.1, 1.05, 0.75), (3.1, 3.2, 0.5)]

# 1. 生成所有重叠候选对,带距离信息
candidate_pairs = []
for red_idx, (rx, ry, rr) in enumerate(red_circles):
    for blue_idx, (bx, by, br) in enumerate(blue_circles):
        # 计算两圆圆心距离
        center_dist = ((rx - bx)**2 + (ry - by)**2)**0.5
        # 判断是否重叠:距离小于两半径之和
        if center_dist < rr + br:
            candidate_pairs.append( (center_dist, red_idx, blue_idx) )

# 2. 按距离从小到大排序,优先保留最近的配对
candidate_pairs.sort(key=lambda item: item[0])

# 3. 一对一匹配,标记已使用的圆
matched_red_ids = set()
matched_blue_ids = set()
final_matched_pairs = []

for dist, red_id, blue_id in candidate_pairs:
    # 如果当前红圆和蓝圆都没被匹配过,就保留这个配对
    if red_id not in matched_red_ids and blue_id not in matched_blue_ids:
        final_matched_pairs.append( (red_id, blue_id) )
        matched_red_ids.add(red_id)
        matched_blue_ids.add(blue_id)

# 4. 绘制结果:所有圆 + 匹配成功的重叠对(用黑框标记)
plt.figure(figsize=(8, 8))
ax = plt.gca()

# 绘制所有红圆、蓝圆
for rx, ry, rr in red_circles:
    ax.add_patch(plt.Circle((rx, ry), rr, color='red', alpha=0.5))
for bx, by, br in blue_circles:
    ax.add_patch(plt.Circle((bx, by), br, color='blue', alpha=0.5))

# 给匹配成功的圆加黑色边框,突出显示
for red_id, blue_id in final_matched_pairs:
    rx, ry, rr = red_circles[red_id]
    bx, by, br = blue_circles[blue_id]
    ax.add_patch(plt.Circle((rx, ry), rr, color='black', fill=False, linewidth=2))
    ax.add_patch(plt.Circle((bx, by), br, color='black', fill=False, linewidth=2))

plt.axis('equal')
plt.title("Red-Blue Circle One-to-One Overlap Matching")
plt.show()

方案2:匈牙利算法(全局最优,适合大规模数据)

如果你的圆数量很多(比如几百上千个),贪心算法可能会出现局部最优的情况,这时候可以用scipy库的linear_sum_assignment实现匈牙利算法,保证全局最优匹配:

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import linear_sum_assignment

# 替换成你实际的数据
red_circles = [(1, 1, 0.8), (1.2, 1.1, 0.7), (3, 3, 0.6)]
blue_circles = [(1.1, 1.05, 0.75), (3.1, 3.2, 0.5)]

# 1. 构建距离矩阵:行=红圆,列=蓝圆,不重叠的对设为无穷大
num_red = len(red_circles)
num_blue = len(blue_circles)
dist_matrix = np.full( (num_red, num_blue), np.inf )

for i, (rx, ry, rr) in enumerate(red_circles):
    for j, (bx, by, br) in enumerate(blue_circles):
        center_dist = ((rx - bx)**2 + (ry - by)**2)**0.5
        if center_dist < rr + br:
            dist_matrix[i][j] = center_dist

# 2. 用匈牙利算法找到全局最优的匹配索引
red_match_indices, blue_match_indices = linear_sum_assignment(dist_matrix)

# 3. 过滤掉无效的配对(距离为无穷大的)
final_matched_pairs = []
for r_idx, b_idx in zip(red_match_indices, blue_match_indices):
    if dist_matrix[r_idx][b_idx] != np.inf:
        final_matched_pairs.append( (r_idx, b_idx) )

# 4. 绘制逻辑和方案1一致,这里省略重复代码
# ...(直接复用方案1的绘制部分即可)
关键说明
  • 两种方案都能解决你遇到的“一个蓝圆被多个红圆匹配”的问题,因为每个圆只能被标记一次「已匹配」
  • 贪心实现简单,计算快;匈牙利算法能保证找到全局最优的配对组合(比如不会出现“近的圆没被匹配,远的反而被匹配”的情况)
  • 你可以根据自己的数据规模选择合适的方案

内容的提问来源于stack exchange,提问作者komodovaran_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:12:31