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

二值图像中旋转正方形的质心、边长及旋转角求解咨询

解决方案

1. 质心计算(原代码逻辑正确)

黑色像素的坐标均值就是正方形的质心,注意图像采用y轴优先的行主序,所以black_pixels的第一列是y坐标,第二列是x坐标:

black_pixels = np.argwhere(img == 0)
y_centroid, x_centroid = np.mean(black_pixels, axis=0)

2. 获取正方形顶点

正方形的顶点是到质心距离最远的4个像素点,利用这一特性筛选顶点:

# 计算每个像素到质心的相对坐标
centered = black_pixels - np.array([y_centroid, x_centroid])
# 计算距离平方(避免开方,提升计算效率)
dist_sq = np.sum(centered ** 2, axis=1)
# 获取距离最远的4个点的索引
top4_idx = np.argpartition(dist_sq, -4)[-4:]
vertices = black_pixels[top4_idx]

3. 计算边长l

旋转后的正方形因抗锯齿导致黑色像素数不等于l²,通过顶点间距离计算边长更准确:

# 生成所有顶点两两组合的索引(用numpy实现,无需额外库)
idxs = np.triu_indices(4, k=1)
pairs = vertices[idxs[0]], vertices[idxs[1]]
# 计算每对顶点的距离
distances = np.sqrt(np.sum((pairs[0] - pairs[1]) ** 2, axis=1))
# 筛选出边长(对角线长度约为边长的√2倍,以此区分)
sorted_dist = np.sort(distances)
side_mask = sorted_dist < sorted_dist[-1] * 0.8  # 0.8用于区分边长和对角线
side_length = np.mean(sorted_dist[side_mask])

4. 计算旋转角alpha

正方形顶点位于对角线方向,将对角线角度减去45°即可得到边的旋转角,再处理等价角度:

# 取任意顶点到质心的向量
vec = vertices[0] - np.array([y_centroid, x_centroid])
# 计算向量与x轴的逆时针夹角(适配图像y轴向下的特性)
angle_rad = np.arctan2(vec[0], vec[1])
angle_deg = np.degrees(angle_rad)
# 对角线角度比边的旋转角大45°,因此减去45°
alpha = angle_deg - 45
# 调整角度到0°~90°范围,处理等价角度(如0°与90°等价)
alpha = alpha % 90

完整修正代码

import numpy as np

def find_rect(img):
    # 找到所有黑色像素
    black_pixels = np.argwhere(img == 0)
    if len(black_pixels) == 0:
        return 0, 0, 0, 0
    
    # 计算质心
    y_centroid, x_centroid = np.mean(black_pixels, axis=0)
    
    # 获取正方形顶点
    centered = black_pixels - np.array([y_centroid, x_centroid])
    dist_sq = np.sum(centered ** 2, axis=1)
    top4_idx = np.argpartition(dist_sq, -4)[-4:]
    vertices = black_pixels[top4_idx]
    
    # 计算边长
    idxs = np.triu_indices(4, k=1)
    pairs = vertices[idxs[0]], vertices[idxs[1]]
    distances = np.sqrt(np.sum((pairs[0] - pairs[1]) ** 2, axis=1))
    sorted_dist = np.sort(distances)
    side_mask = sorted_dist < sorted_dist[-1] * 0.8
    side_length = np.mean(sorted_dist[side_mask])
    
    # 计算旋转角
    vec = vertices[0] - np.array([y_centroid, x_centroid])
    angle_rad = np.arctan2(vec[0], vec[1])
    angle_deg = np.degrees(angle_rad)
    alpha = angle_deg - 45
    alpha = alpha % 90
    
    return x_centroid, y_centroid, side_length, alpha

# 保留原生成旋转正方形的代码
from scipy.ndimage import rotate
def generate_rot_square(w, h, x, y, l, alpha):
    rect = np.ones((l, l))
    rect = rotate(rect, alpha)
    r_h, r_w = rect.shape
    r_h_1 = r_h // 2
    r_h_2 = r_h - r_h_1
    r_w_1 = r_w // 2
    r_w_2 = r_w - r_w_1

    result = np.zeros((h, w), dtype=bool)
    result[y - r_h_1:y + r_h_2, x - r_w_1:x + r_w_2] = rect > 0.9
    return 1 - result

关键说明

  • 质心计算:原代码逻辑正确,直接取黑色像素坐标均值即可。
  • 边长计算:旋转后的正方形因抗锯齿导致黑色像素数偏离l²,通过顶点间距离计算更精准。
  • 旋转角计算:利用正方形顶点在对角线上的特性,将对角线角度转换为边的旋转角,再通过取模90°处理等价角度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 09:41:01