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

通过OpenCV对齐矩阵投影视图中的水平线

问题描述

我拥有两个不同的矩阵A(形状为5×11)和B(形状为5×2),希望为它们生成投影视图。但分隔不同数值的水平线最终处于不同高度(约80px与150px),使用numpy、matplotlib和OpenCV实现,相关代码如下:

矩阵A投影生成代码

import numpy as np
import cv2
import matplotlib.pyplot as plt
output_width, output_height = 1000, 600

values = 1 + np.random.rand(5, 11).astype("float32")

source_points = np.array(
    [
        [-0.5, -0.5], [10.5, -0.5], [-0.5, 4.5], [10.5, 4.5],
    ], dtype="float32"
)
target_points = np.array(
    [
        [1, 0], [1000, 0], [250, 250], [750, 250],
    ], dtype="float32"
)

transformation = cv2.getPerspectiveTransform(source_points, target_points)
warped_values = cv2.warpPerspective(
    values, 
    transformation, 
    (output_width, output_height), 
    borderMode=cv2.BORDER_TRANSPARENT, 
    flags=cv2.INTER_NEAREST
)
plt.imshow(warped_values)

矩阵B投影生成代码

values = 1 + np.random.rand(5, 2).astype("float32")

source_points = np.array(
    [
        [-0.5, -0.5], [1.5, -0.5], [-0.5, 4.5], [1.5, 4.5],
    ], dtype="float32"
)

target_points = np.array(
    [
        [201, 0],  [800, 0], [450, 250], [550, 250],
    ], dtype="float32"
)

transformation = cv2.getPerspectiveTransform(source_points, target_points)
warped_values = cv2.warpPerspective(
    values, 
    transformation, 
    (output_width, output_height), 
    flags=cv2.INTER_NEAREST, 
    borderMode=cv2.BORDER_TRANSPARENT
)
plt.imshow(warped_values)
原因分析
  1. 透视变换的行缩放比例不一致:
    两个矩阵的源点行范围都是-0.5到4.5(对应5行数据,每行高度1单位),但列范围差异极大:矩阵A列范围是-0.5到10.5(11列),矩阵B是-0.5到1.5(2列)。透视变换时,行方向的单位长度会随列跨度的不同被拉伸不同幅度——矩阵A列跨度大,行方向拉伸幅度小;矩阵B列跨度小,行方向拉伸幅度大,最终导致行分隔线的视觉高度差异。
  2. Matplotlib自动缩放放大差异:
    plt.imshow默认会根据输入数组的形状自动调整显示纵横比,加上透视变换后存在的透明区域,进一步放大了行分隔线的高度差异。
解决办法

方法1:统一透视变换的行缩放比例

调整矩阵B的目标点,让行方向的变换幅度与矩阵A一致,确保每行间隔投影后的像素高度相同。计算逻辑是让矩阵B下边缘的x跨度与源列跨度的比例和矩阵A一致:

# 修改矩阵B的target_points
target_points = np.array(
    [
        [201, 0],  [800, 0], [325, 250], [675, 250],
    ], dtype="float32"
)

方法2:固定Matplotlib显示参数

在plt.imshow后添加固定纵横比的设置,避免自动缩放带来的视觉偏差,同时统一颜色映射范围:

# 替换原plt.imshow行,添加以下代码
plt.imshow(warped_values, vmin=1, vmax=2)
plt.gca().set_aspect('equal', adjustable='box')
plt.show()

方法3:手动校准行间隔映射

先计算矩阵A中每行间隔投影后的实际像素高度,再以此为基准调整矩阵B的目标点y坐标,直接保证行分隔线的高度一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 15:43:10