OpenCV——svd速度优化

在发现opencv运行SVD::compute()过程太慢,一张299*299的图片Debug要几s,release也要0.5s。

第一次尝试:

将299*299图像分成13份23*299的图像运行svd。release模式下能达到0.25s,将近快一倍。

第二次:

加上UMat,成绩感人。release模式下速度0.02s,又快了10倍。

void main()
{
    Mat img = Mat(height, width, CV_8UC1, image);
    Mat src_ = img.clone();
    Mat dst_show = Mat(img.size(), CV_8UC1, Scalar(0));
    int set_height = 23;
    double t1 = getTickCount();
    for (int i = 0; i < 13; i++)
    {
	Mat src;
	src = Mat(img, Rect(0, 0 + i * set_height, img.cols, set_height));

	src.convertTo(src, CV_64FC1);
	UMat U, W, V;

	SVD::compute(src, W, U, V);

	int set_dim = min(src.rows, src.cols);
	
	UMat W_;
	Mat(set_dim, set_dim, CV_64FC1, Scalar(0)).copyTo(W_);
		
	for (int i = 0; i < kvalue; i++)
	{
		W_.getMat(ACCESS_READ).at<double>(i, i) = W.getMat(ACCESS_READ).at<double>(i, 0);
	}
	
	Mat dst = U.getMat(ACCESS_READ) * W_.getMat(ACCESS_READ) * V.getMat(ACCESS_READ);
	dst.c
<think>嗯,用户想计算单应性矩阵,用于图像点和地理坐标之间的透视变换。首先,我得回忆一下单应性矩阵是什么。单应性矩阵是一个3x3的矩阵,用于描述两个平面之间的投影变换,比如从图像平面到地理坐标平面的映射。对吧? 那计算单应性矩阵通常需要至少四个对应点对,因为每个点对提供两个方程,而矩阵有8个自由度(因为比例因子无关),所以四个点对刚好足够这个线性方程组。不过,如果使用更多点对,可以用最小二乘法来优化结果,减少误差。这个方法应该没错。 接下来,用户可能想知道具体的计算步骤。首先,需要将地理坐标和图像坐标对应起来,建立方程组。比如,每个点对的坐标是$(x_i, y_i)$对应到$(u_i, v_i)$,然后构建一个矩阵A,每个点对生成两行,最终Ah=0的问题。这里可能需要用奇异值分SVD)来求,或者使用直接线性变换(DLT)算法。 不过,用户提到的是地理坐标,可能需要考虑坐标系的转换,比如地理坐标通常是经纬度,可能需要先投影到平面坐标系统,比如UTM,这样才能进行平面变换。这一步是不是必须的?如果用户的地理坐标已经是平面投影后的坐标,那可以直接用;否则需要先转换,否则单应性矩阵可能无法正确映射,因为经纬度是球面坐标,而单应性适用于平面。 然后,关于归一化的问题。在计算单应性矩阵之前,通常要对坐标进行归一化处理,比如平移和缩放,使得坐标的均值为0,标准差为√2,这样可以提高数值稳定性。这一步可能用户没有考虑到,但实际应用中很重要,避免因为坐标数量级差异大导致矩阵条件数过高,不稳定。 还有,出单应性矩阵后,需要验证其正确性,比如用已知点对测试重投影误差,或者使用RANSAC算法去除异常点的影响,尤其是在有噪声或错误对应点的情况下。用户可能没有提到异常点的问题,但实际应用中这一步很关键。 代码实现方面,可能需要用到numpy进行矩阵运算,或者使用OpenCV中的findHomography函数,它内部已经处理了归一化和SVD,还能选择不同的方法,比如RANSAC。但用户可能想自己实现,所以需要详细步骤。 另外,用户的应用场景是地理坐标映射到图像点,比如可能是无人机图像的地理配准,或者地图投影的应用。这时候可能需要考虑地理坐标的精度,以及是否需要考虑高程的影响,如果地形有起伏,单纯的单应性矩阵可能不够,需要使用更复杂的模型,比如三维投影。但用户的问题限定在二维平面,所以假设地面是平坦的。 最后,生成的相关问题应该覆盖单应性矩阵的基本原理、优化方法、应用场景以及可能的替代方案,帮助用户进一步了。</think>### 单应性矩阵计算步骤 单应性矩阵(Homography Matrix)用于描述两个平面之间的透视变换关系。若需通过图像点与地理坐标的对应关系计算单应性矩阵,步骤如下: --- #### **1. 数据准备** - **输入要求**:至少需要 **4组对应点对**(推荐更多点以提高鲁棒性)。每组包含: - 图像坐标系中的点坐标 $(u_i, v_i)$ - 地理坐标系中的点坐标 $(x_i, y_i)$(需确保为平面投影坐标,如UTM坐标系[^1]) --- #### **2. 构建线性方程组** 单应性矩阵 $H$ 是3×3矩阵,满足: $$ \begin{bmatrix} x' \\ y' \\ w' \end{bmatrix} = H \cdot \begin{bmatrix} u \\ v \\ 1 \end{bmatrix}, \quad \text{其中归一化后} \quad x = \frac{x'}{w'}, \quad y = \frac{y'}{w'} $$ 展开后得到约束方程: $$ x_i (h_{31}u_i + h_{32}v_i + h_{33}) = h_{11}u_i + h_{12}v_i + h_{13} \\ y_i (h_{31}u_i + h_{32}v_i + h_{33}) = h_{21}u_i + h_{22}v_i + h_{23} $$ 每对点生成两个方程,整理为矩阵形式 $A \cdot h = 0$,其中: $$ A = \begin{bmatrix} -u_1 & -v_1 & -1 & 0 & 0 & 0 & u_1x_1 & v_1x_1 & x_1 \\ 0 & 0 & 0 & -u_1 & -v_1 & -1 & u_1y_1 & v_1y_1 & y_1 \\ \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots \end{bmatrix}, \quad h = \begin{bmatrix} h_{11} & h_{12} & h_{13} & h_{21} & h_{22} & h_{23} & h_{31} & h_{32} & h_{33} \end{bmatrix}^T $$ --- #### **3. 求矩阵** - **奇异值分SVD)**:对矩阵 $A$ 进行SVD,最小奇异值对应的右奇异向量即为 $h$ 的[^2]。 - **归一化处理**:为提升数值稳定性,需对坐标进行平移和缩放,使均值为0,标准差为 $\sqrt{2}$。 --- #### **4. 验证与优化** - **重投影误差**:计算 $\sum \| (x_i, y_i) - H \cdot (u_i, v_i, 1)^T \|^2$,误差越小精度越高。 - **RANSAC**:若存在异常点,使用RANSAC算法剔除离群点后重新计算。 --- #### **代码示例(Python)** ```python import numpy as np def compute_homography(src_points, dst_points): # src_points: 图像坐标 [[u1, v1], [u2, v2], ...] # dst_points: 地理坐标 [[x1, y1], [x2, y2], ...] A = [] for (u, v), (x, y) in zip(src_points, dst_points): A.append([-u, -v, -1, 0, 0, 0, u*x, v*x, x]) A.append([0, 0, 0, -u, -v, -1, u*y, v*y, y]) A = np.array(A) # SVD最小特征值对应向量 _, _, V = np.linalg.svd(A) H = V[-1].reshape(3, 3) H /= H[2, 2] # 归一化 return H # 示例:4组对应点 src = np.array([[0, 0], [100, 0], [100, 100], [0, 100]]) dst = np.array([[10, 20], [110, 25], [105, 125], [15, 120]]) H = compute_homography(src, dst) print("单应性矩阵:\n", H) ``` --- #### **应用场景** - 卫星影像与地图的配准 - 增强现实中的虚实场景对齐 - 无人机航拍图像的地理定位 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值