【备忘】Homographic Adaptation 单应性变换

是将一个平面内的点映射到另一个平面内的二维投影变换。

应用

单应性在计算机视觉领域是一个非常重要的概念,它在图像校正、视角变换、图像拼接、增强现实、相机位姿估计、视觉SLAM等领域有非常重要的作用。

SuperPoint: Self-Supervised Interest Point Detection and Description里也会用到单应性(Homographic Adaptation)。

via.SuperPoint_Self-Supervised_Interest_Point_Detection_and_Description_CVPRW_2018

 

 

 具体变换

如下,有一个变换矩阵H--单应性矩阵。假设两张图像中的对应点对齐次坐标为(x',y',1)和(x,y,1),而中间的映射关系就是H。具体如下。 

  


1、打印一张棋盘格标定图纸,将其贴在平面物体的表面。

2、拍摄一组不同方向棋盘格的图片,可以通过移动相机来实现,也可以移动标定图片来实现。

3、对于每张拍摄的棋盘图片,检测图片中所有棋盘格的特征点(角点,也就是下图中黑白棋盘交叉点,中间品红色的圆圈内就是一个角点)。我们定义打印的棋盘图纸位于世界坐标系Zw=0的平面上,世界坐标系的原点位于棋盘图纸的固定一角(比如下图中黄色点)。像素坐标系原点位于图片左上角。 

4、因为棋盘标定图纸中所有角点的空间坐标是已知的,这些角点对应在拍摄的标定图片中的角点的像素坐标也是已知的,如果我们得到这样的N>=4个匹配点对(越多计算结果越鲁棒),就可以根据LM等优化方法,find其单应矩阵H

当然计算单应矩阵一般不需要自己写函数实现,OpenCV中就有现成的函数Mat findHomography可以调用,对应的c++函数是:

Mat findHomography   //返回类型是MAT

(

InputArray srcPoints,   //二者对应points

InputArray dstPoints,  //二者对应points

int method=0, 

double ransacReprojThreshold=3,

OutputArray mask=noArray()

)

从函数定义来看,只要输入匹配点对,指定具体计算方法即可输出结果。

via.opencv official doc

图片校正案例

 

//---------------------------------------------
//环境:win10、opencv
//---------------------------------------------

#include <opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc_c.h>

using namespace cv;
using namespace std;

//设置差分值
int dx = 5;
int dy = dx;

//定义一个数据结构:图片+点集
struct userdata {
    Mat im;
    vector<Point2f> points;
};


void mouseHandler(int event, int x, int y, int flags, void* data_ptr)
{
    userdata* data = ((userdata*)data_ptr);

    //按下鼠标触发,4个点
    if (event == EVENT_LBUTTONDOWN && data->points.size() <= 4)
    {
		//  circle( src2_copy, tracked_points_1[i], 3, Scalar(0,0,255), -1, 8);
        // 实心红点
        circle(data->im, Point(x, y), 3, Scalar(0, 0, 255), 5, CV_AA);

        CvPoint pt;
        char text[16];
        string msg;
        msg = format("(%d, %d)", x, y);
        //    baseLine = 0;
        //    textSize = getTextSize(msg, 1, 0.5, 1, &baseLine);

        //    Point textOrigin(20, imgRGB2.rows - 20);
        //    putText(src2_copy, msg, textOrigin, 1, 1, Scalar(0,255,0));

        //		sprintf(text, "(%d, %d)", 1);
        pt = cvPoint(x - 3 * dx, y - dy);
        putText(data->im, msg, pt, CV_FONT_HERSHEY_SIMPLEX, 0.45, cvScalar(0, 255, 255, 0));


        imshow("Image", data->im);
        if (data->points.size() < 4)
        {
            data->points.push_back(Point2f(x, y));
        }
    }
}



int main()
{
    // Read source image.   
    Mat im_src = imread("002.JPG");

    //dst,物体的纵横比maybe是2:3 
    Size size(540, 240);
    Mat im_dst = Mat::zeros(size, CV_8UC3);


    // 创建方向点向量,并添加4点坐标
    vector<Point2f> pts_dst;
    pts_dst.push_back(Point2f(0, 0));
    pts_dst.push_back(Point2f(size.width - 1, 0));
    pts_dst.push_back(Point2f(size.width - 1, size.height - 1));
    pts_dst.push_back(Point2f(0, size.height - 1));


    //-------------------------------------------
    // 设置鼠标事件数据,手动添加坐标
    Mat im_temp = im_src.clone();
    userdata data;
    data.im = im_temp;

    cout << "点击书的四个角——首先是左上角,然后" << endl
        << "左下角最后 -- 然后按 ENTER" << endl;

    // 显示图像并等待 4 次点击. 
    imshow("Image", im_temp);

    // 鼠标事件  设置回调函数
    setMouseCallback("Image", mouseHandler, &data);
    waitKey(0);

    // 计算单应性

    Mat h = findHomography(data.points, pts_dst);

    // 将源图像扭曲到目标
    warpPerspective(im_src, im_dst, h, size);

    // 输出
    imshow("Image", im_dst);
    waitKey(0);

    return 0;
}

STEP1、运行

 STEP2、从预计的左上角依次顺时针标定

 

 STEP3、最终生成校正结果

 

### SuperPoint 计算机视觉特征点检测算法实现 #### 算法概述 SuperPoint 是一种自监督学习框架下的兴趣点检测和描述方法[^1]。此方法旨在解决传统手工设计特征点检测器的局限性和深度学习模型对大规模标注数据的需求。 #### 方法构成 SuperPoint 结合了两个主要组件:MagicPoint 和 Homographic Adaptation。前者是在合成几何形状的数据集上预训练的兴趣点检测器;后者则是一种增强技术,用于提高检测器在真实世界图像上的泛化能力[^2]。 #### 技术细节 - **MagicPoint**: 利用了简单几何图形(如线段、三角形等)作为基础构建块创建虚拟数据集,在这些无歧义的真实标签下训练全卷积网络(FCNN),从而获得初步的兴趣点预测模型。 - **Homographic Adaptation**: 对输入图片应用随机仿射变换,使得同一物理位置可以在多种视角和尺度下被观察到,进而增强了模型的学习能力和鲁棒性。 #### 实现流程 以下是简化版的 Python 代码片段展示如何利用 PyTorch 来搭建 SuperPoint 模型: ```python import torch.nn as nn from torchvision import models class SuperPointNet(nn.Module): """定义SuperPoint网络架构""" def __init__(self, pretrained=True): super(SuperPointNet, self).__init__() # 使用VGG16去掉最后三层池化层后的部分作为骨干网 vgg = models.vgg16(pretrained=pretrained).features[:30] self.backbone = nn.Sequential(*vgg) # 定义额外的卷积层处理特征图 self.detector_head = nn.Conv2d(in_channels=512, out_channels=65, kernel_size=(3, 3), padding=1) self.descriptor_head = nn.Conv2d(in_channels=512, out_channels=256, kernel_size=(1, 1)) def forward(self, x): features = self.backbone(x) semilogits = self.detector_head(features) descriptors = self.descriptor_head(features) return semilogits, descriptors ``` 上述代码展示了 SuperPoint 的核心组成部分之一 —— VGG16 改造版本用作特征提取模块,并分别设置了负责关键点定位(`detector_head`)以及描述符生成(`descriptor_head`)的任务头[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值