您可以執行以下操作:在
你認爲你的原始圖像的平面物體上尋求與90度角
你承擔一些相機的固有參數(例如焦點圖像中間和像素尺寸一致),一些相機外部因素(例如,從平面上方以某個位置向下看)以及一些平面座標(xy平面)。這將導致每個像素位於飛機的某些座標上。
您周圍的攝影機中心
旋轉改變攝像機extrinic參數你項目的一些(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<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我不得不擴展翻譯部分,事後可能不需要。可能由於錯誤的翻譯+旋轉組合而出現問題。
比較:tranlation 1.5縮放:
,而不是縮放:
這是你想要達到什麼樣的(如果攝像機的取景中心可被固定在銀行的中間位置)?
書面,這個問題過於廣泛和庫/工具/等。建議不在SO的範圍內。 – excaza