当前位置:  开发笔记 > 编程语言 > 正文

如何更改2D图像的视口?

如何解决《如何更改2D图像的视口?》经验,为你挑选了1个好方法。

我正在开发一款用于识别金钱的移动应用程序.现在我正在尝试为这个应用程序构建数据库.

下一步是从不同视图中的原始图像生成一些图像.这是一个例子:

原版的:

在此输入图像描述

查看1:

在此输入图像描述

如上图所示,视图1图像是从左边缘查看原始图像.我想要做的是从原始生成4个图像,从左,右,下,上4视图.由于图像数量非常大,我无法使用相机捕捉,因此我需要编写一个程序来完成这项工作.但是我找不到关于这个问题的任何事情.

请告诉我有什么工具可以做我需要的吗?或任何图书馆,框架支持这个?我可以在MATLAB和openCV上编码.

谢谢你的帮助.



1> Micka..:

您可以执行以下操作:

    您假设原始图像在平面物体上以90度角看

    你假设一些相机内在参数(例如图像中间的焦点和均匀像素大小),一些相​​机外部(例如,从平面上方看某个位置"向下")和一些平面坐标(xy平面).这将导致每个像素位于平面的某些坐标上.

    您可以通过围绕相机中心旋转来更改相机的外部参数

    您将一些(4个或更多)平面位置投影到相机图像(例如使用cv::projectPoints()).

    你计算描述两个摄像机视图之间像素"运动"的透视单应性(输入像素位置是那些投影平面位置和原始图像中相同的平面位置)

    记住每个选定视图的单应性.

    对于每个图像,只需使用这些单应性,您不必重新计算它们,因为它们对于每个图像是相同的.

编辑:这是它在行动中的样子(对于丑陋的代码抱歉):

cv::Mat getRotationMatrixAroundY(double angle)
{
    cv::Mat rVec;

    cv::Mat deg45 = cv::Mat::zeros(3,3,CV_64FC1);
    double cos45 = cos(CV_PI*angle/180.0);
    double sin45 = sin(CV_PI*angle/180.0);

    // different axis:
    /*      deg45.at(1,1) = cos45;      deg45.at(1,2) = sin45;      deg45.at(0,0) = 1;      deg45.at(2,1) = -sin45;     deg45.at(2,2) = cos45;      */

    /*      deg45.at(0,0) = cos45;      deg45.at(0,1) = in45;       deg45.at(2,2) = 1;      deg45.at(1,0) = -sin45;     deg45.at(1,1) = cos45;      */


    deg45.at(0,0) = cos45;
    deg45.at(0,2) = sin45;
    deg45.at(1,1) = 1;
    deg45.at(2,0) = -sin45;
    deg45.at(2,2) = cos45;

    cv::Rodrigues(deg45, rVec);

    return rVec;
}

// banknode training sample generator
int main()
{
    cv::Mat input = cv::imread("../inputData/bankNode.jpg");

    std::vector pointsOnPlane;

    pointsOnPlane.push_back(cv::Point3f(0-input.cols/2,0-input.rows/2,0));
    pointsOnPlane.push_back(cv::Point3f(input.cols-input.cols/2,0-input.rows/2,0));
    pointsOnPlane.push_back(cv::Point3f(input.cols-input.cols/2,input.rows-input.rows/2,0));
    pointsOnPlane.push_back(cv::Point3f(0-input.cols/2,input.rows-input.rows/2,0));





    std::vector originalPointsInImage;
    originalPointsInImage.push_back(cv::Point2f(0,0));
    originalPointsInImage.push_back(cv::Point2f(input.cols,0));
    originalPointsInImage.push_back(cv::Point2f(input.cols,input.rows));
    originalPointsInImage.push_back(cv::Point2f(0,input.rows));

    std::cout << "original pixel positions:" << std::endl;
    for(unsigned int i=0; i(0,0) = 500.0;
    cameraIntrinsics.at(1,1) = 500.0;
    cameraIntrinsics.at(0,2) = input.cols/2.0;
    cameraIntrinsics.at(1,2) = input.rows/2.0;

    std::vector distCoefficients;

    cv::Mat rVec;
    cv::Mat tVec;
    cv::solvePnP(pointsOnPlane, originalPointsInImage, cameraIntrinsics, distCoefficients, rVec, tVec);


    // let's increase the distance a bit
    tVec = tVec*2;
    double angle = -45; // degrees


    cv::Mat rVec2 = getRotationMatrixAroundY(angle);

    // TODO: how to "add" some rotation to a previous rotation in Rodrigues?!?
    // atm just overwrite:


    std::vector projectedPointsOnImage;
    cv::projectPoints(pointsOnPlane, rVec2, tVec, cameraIntrinsics, distCoefficients, projectedPointsOnImage);


    cv::Mat H = cv::findHomography(originalPointsInImage, projectedPointsOnImage);

    cv::Mat warped;
    cv::warpPerspective(input, warped, H, input.size());




    cv::imshow("input", input);
    cv::imshow("warped", warped);
    cv::waitKey(0);
    return 0;
}

结果如下:

在此输入图像描述

正如您所看到的,存在一个问题:旋转不在banknode的中心附近.如果有人能解决这个问题,结果会更好.Atm我不得不缩放翻译部分,之后可能没有必要.可能是由于错误的翻译+旋转组合而出现问题.

比较:翻译缩放1.5:

在此输入图像描述

而不是缩放:

在此输入图像描述

这是你想要实现的(如果摄像机的观察中心可以固定在banknode的中间)?

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有