opencv 单应矩阵 应用

视觉惯性SLAM 14天挑战 大作业

任务:利用单应矩阵将广告牌的内容替换成自己的图片。

opencv 单应矩阵 应用_第1张图片

代码框架如下:

#include 

using namespace cv;
using namespace std;

struct userdata
{
    Mat im;
    vector<Point2f> points;
};

void mouseHandler(int event, int x, int y, int flags, void *data_ptr)
{
    if (event == EVENT_LBUTTONDOWN)
    {
        userdata *data = ((userdata *)data_ptr);
        circle(data->im, Point(x, y), 3, Scalar(0, 255, 255), 5, CV_AA);
        imshow("Image", data->im);
        if (data->points.size() < 4)
        {
            data->points.push_back(Point2f(x, y));
        }
    }
}

int main(int argc, char **argv)
{
    // Read in the image.
    // input your image
    Mat im_src = imread("new.jpg");
    // imshow("src img", im_src);
    Size size = im_src.size();

    // Create a vector of points.
    vector<Point2f> pts_src;
    pts_src.push_back(Point2f(0, 0));                           
    pts_src.push_back(Point2f(size.width - 1, 0));               
    pts_src.push_back(Point2f(size.width - 1, size.height - 1)); 
    pts_src.push_back(Point2f(0, size.height - 1));             

    // Destination image
    // Mat im_dst = imread("times-square.jpg");
    Mat im_dst = imread("ad.jpg");

    // Set data for mouse handler
    Mat im_temp = im_dst.clone();
    userdata data;
    data.im = im_temp;

    // show the image
    imshow("Image", im_temp);

    cout << "Click on four corners of a billboard and then press ENTER" << endl;
    // 注意鼠标旋转顺序和原图定义角点顺序要一致
    setMouseCallback("Image", mouseHandler, &data);
    waitKey(0);

    // ----------  开始你的代码  --------------

    // 计算原图四个角点和目标图区域对应角点的 Homography
    // 用H对原图做变换

    // 提取鼠标点击的四个角点

    // 把目标图中对应区域像素值设置为0dst << "\ttemp size: " << size_temp << std::endl;

    // 把原图叠加到目标图上
    // ----------  结束你的代码  --------------
    // Display image.
    imshow("Image", im_dst);
    waitKey(0);

    return 0;
}

答案

#include 

using namespace cv;
using namespace std;

struct userdata
{
    Mat im;
    vector<Point2f> points;
};

void mouseHandler(int event, int x, int y, int flags, void *data_ptr)
{
    if (event == EVENT_LBUTTONDOWN)
    {
        userdata *data = ((userdata *)data_ptr);
        circle(data->im, Point(x, y), 3, Scalar(0, 255, 255), 5, CV_AA);
        imshow("Image", data->im);
        if (data->points.size() < 4)
        {
            data->points.push_back(Point2f(x, y));
        }
    }
}

int main(int argc, char **argv)
{
    // Read in the image.
    // input your image
    // 新的广告图片
    Mat im_src = imread("new.jpg");
    Size size = im_src.size();

    // Create a vector of points.
    // 广告图片的四个角
    vector<Point2f> pts_src;
    pts_src.push_back(Point2f(0, 0));                            // 左上角
    pts_src.push_back(Point2f(size.width - 1, 0));               // 左下角
    pts_src.push_back(Point2f(size.width - 1, size.height - 1)); // 右下角
    pts_src.push_back(Point2f(0, size.height - 1));              // 右上角

    // Destination image
    // 广告框图片
    Mat im_dst = imread("ad.jpg");

    // Set data for mouse handler
    Mat im_temp = im_dst.clone();
    userdata data;
    data.im = im_temp;

    // show the image
    imshow("Image", im_temp);

    cout << "Click on four corners of a billboard and then press ENTER" << endl;
    // 注意鼠标旋转顺序和原图定义角点顺序要一致
    // 在广告框上选取广告的的四个点
    setMouseCallback("Image", mouseHandler, &data);
    waitKey(0);
    // 我想输出看一下坐标点是咋样的
    // 这里就是想投影成什么形状的四边形的四个点坐标
    for (auto i : data.points)
    {
        std::cout << i << std::endl;
    }

    // ----------  开始你的代码  --------------

    // 计算原图四个角点和目标图区域对应角点的 Homography
    Mat h_matrix = findHomography(pts_src/*广告图片的四个顶点*/, data.points/*原广告的四个顶点*/);
    std::cout << h_matrix << std::endl; // 单应矩阵

    // 用H对原图做变换
    warpPerspective(im_src/*新的广告图片*/, im_temp/*广告框图片*/, h_matrix/*单应矩阵*/, im_temp.size());

    // 提取鼠标点击的四个角点
    // 将data.points 从 vector 类型转换为 Point 类型
    Point pts_dst[4];
    for (int i = 0; i < 4; i++)
    {
        pts_dst[i] = data.points[i];
    }

    // 把目标图中对应区域像素值设置为0
    fillConvexPoly(im_dst/*广告框图片*/, pts_dst/*旧广告的四个顶点*/, 4, Scalar(0));
    Size size_dst = im_dst.size();
    Size size_temp = im_temp.size();
    std::cout << "dst size: " << size_dst << "\ttemp size: " << size_temp << std::endl;

    // 把原图叠加到目标图上
    im_dst = im_dst + im_temp;
    // ----------  结束你的代码  --------------
    // Display image.
    imshow("Image", im_dst);
    waitKey(0);

    return 0;
}

你可能感兴趣的:(SLAM,课程设计,矩阵,c++)