【问题标题】:How to change viewport of 2D image? [closed]如何更改二维图像的视口? [关闭]
【发布时间】:2015-12-16 14:54:20
【问题描述】:

我正在开发一个用于货币识别的移动应用。现在我正在尝试为这个应用程序构建数据库。

下一步是从不同视图中的原始图像生成一些图像。示例如下:

原文:

查看 1:

如您在上图中所见,视图 1 图像是从左边缘的原始视图。我想要做的是从原始图像生成 4 个图像,从左、右、下、上 4 个视图。由于图像数量非常多,我无法使用相机来捕捉,所以我需要编写一个程序来完成这项工作。但是我找不到关于这个问题的任何信息。

请告诉我有什么工具可以满足我的需要吗?或任何库,框架支持这个?我可以在 MATLAB 和 openCV 上编写代码。

感谢您的帮助。

【问题讨论】:

  • 正如所写,这个问题太宽泛了,图书馆/工具/等。建议超出了 SO 的范围。

标签: matlab opencv image-processing graphics computer-vision


【解决方案1】:

您可以执行以下操作:

  1. 您假设原始图像在平面对象上以 90 度角观看

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

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

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

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

  6. 记住每个所选视图的单应性。

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

编辑: 这就是它在运行中的样子(对不起,丑陋的代码):

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<double>(1,1) = cos45;      deg45.at<double>(1,2) = sin45;      deg45.at<double>(0,0) = 1;      deg45.at<double>(2,1) = -sin45;     deg45.at<double>(2,2) = cos45;      */

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


    deg45.at<double>(0,0) = cos45;
    deg45.at<double>(0,2) = sin45;
    deg45.at<double>(1,1) = 1;
    deg45.at<double>(2,0) = -sin45;
    deg45.at<double>(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<cv::Point3f> 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<cv::Point2f> 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<originalPointsInImage.size(); ++i)
        std::cout << originalPointsInImage[i] << std::endl;

    cv::Mat cameraIntrinsics = cv::Mat::eye(3,3,CV_64FC1);

    cameraIntrinsics.at<double>(0,0) = 500.0;
    cameraIntrinsics.at<double>(1,1) = 500.0;
    cameraIntrinsics.at<double>(0,2) = input.cols/2.0;
    cameraIntrinsics.at<double>(1,2) = input.rows/2.0;

    std::vector<double> 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<cv::Point2f> 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;
}

结果如下:

如您所见,存在一个问题:旋转不是围绕银行节点的中心。如果有人能解决这个问题,结果会更好。 Atm 我必须缩放翻译部分,之后可能不需要。可能是平移+旋转组合错误造成的问题。

为了比较:翻译比例为 1.5:

且未缩放:

这是你想要实现的(如果相机的观察中心可以固定在银行节点的中间)?

【讨论】:

  • 我认为单应性不是我需要的,因为从原始生成的图像必须具有正确的比例。单应性让我们有从左或右看但物体扭曲的感觉。
  • 因为您从虚拟移动/旋转的相机计算单应性(在计算单应性之前第 1-4 点很重要!)如果不知道对象的 3D 模型,您将不会获得任何更好的结果。如果我有时间我会用一些代码来演示它......
  • 如果您的意思是您需要相机的正确内部(可能还有外部)参数,那么它会更容易(如果您可以提供这些参数)。
  • 请告诉我您需要哪些参数?
  • 用于捕获输入图像的相机的相机内在函数
【解决方案2】:

查看here 使用 Matlab 进行投影变换。你只需要找到正确的扭曲矩阵(所谓的homographies)。给定旋转矩阵和假定的相机内在函数,您可以使用维基百科上的数学来构建它们。

但是,我认为综合创建的训练数据可能会导致您的任务出现一些问题。钞票的反射部分被设计成从不同的角度看起来不同。你会丢失信息。

此外,不要低估开发它所必需的努力。在这个领域正在进行相当复杂的研究。

看这里:

Towards Mobile Recognition and Verification of Holograms using Orthogonal Sampling

Mobile User Interfaces for Efficient Verification of Holograms

【讨论】:

  • 我不能对这个图像使用单应性,因为里面的对象会被扭曲。请给我另一种方式
猜你喜欢
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 2015-05-24
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多