2015-12-16 62 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這張圖片,因爲裏面的物體會被扭曲。請給我另一種方式 –