2015-12-16 35 views
1

我正在开发一款移动应用程序以进行货币识别。现在我试图为这个应用程序构建数据库。如何更改2D图像的视口?

下一步是在不同视图中从原始图像生成一些图像。这里是例子:

原文:

enter image description here

视图1:

enter image description here

正如你在上图中看到,视图1图像是vi原始的左边缘。我想要做的是从原始生成4个图像,从左,右,下,上四个视图。由于图像数量众多,我无法使用相机拍摄,因此我需要编写一个程序来完成这项工作。但我无法找到关于这个问题的任何事情。

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

感谢您的帮助。

+1

书面,这个问题过于广泛和库/工具/等。建议不在SO的范围内。 – excaza

回答

5

您可以执行以下操作:在

  1. 你认为你的原始图像的平面物体上寻求与90度角

  2. 你承担一些相机的固有参数(例如焦点图像中间和像素尺寸一致),一些相​​机外部因素(例如,从平面上方以某个位置向下看)以及一些平面坐标(xy平面)。这将导致每个像素位于飞机的某些坐标上。

  3. 您周围的摄影机中心

  4. 旋转改变摄像机extrinic参数你项目的一些(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; 
} 

这个结果:

enter image description here

,你可以看到有是一个问题:轮换不在银行中心的中心。如果有人能解决这个问题,结果会更好。 Atm我不得不扩展翻译部分,事后可能不需要。可能由于错误的翻译+旋转组合而出现问题。

比较:tranlation 1.5缩放:

enter image description here

,而不是缩放:

enter image description here

这是你想要达到什么样的(如果摄像机的取景中心可被固定在银行的中间位置)?

+0

我认为单应性不是我所需要的,因为从原始图像生成的图像必须具有正确的比例。 Homography使我们有从左或右看的感觉,但对象被扭曲。 –

+0

由于您从一个虚拟移动/旋转的相机中计算单应性(在计算单应性之前,点1-4是重要的!)如果不知道物体的3D模型,您将无法获得更好的结果。如果我找到时间,我将用一些代码演示它...... – Micka

+0

如果您的意思是说您需要相机的正确内在参数(也可能是外部参数),那么它会更容易(如果您可以提供这些参数参数)。 – Micka

2

使用Matlab的射影变换看here。你只需要找到正确的整形矩阵(所谓的homographies)。您可以使用维基百科上的数学构建它们,给定一个旋转矩阵和一个假定的相机内部函数。

但是,我认为合成创建的培训数据可能会导致一些有关您的任务的问题。钞票的反射部分被设计成从不同的观点看起来不同。你会失去信息。

另外,千万不要小看努力,这将有必要制定这个。这个领域正在进行相当复杂的研究。

在这里看到:

Towards Mobile Recognition and Verification of Holograms using Orthogonal Sampling

Mobile User Interfaces for Efficient Verification of Holograms

+0

我不能使用homopgraphy这张图片,因为里面的物体会被扭曲。请给我另一种方式 –