2013-04-24 82 views
1

我使用OpenCV的嘗試獲得此圖像的鳥瞰投影:this image
我先找到了棋盤的所有內角和吸引他們,如下所示image
我然後使用warpPerspective(),但它會產生一個非常小的變形圖像,如here所示。任何人都可以弄清楚是什麼造成了這個?鳥瞰投影誤差

這裏是我的代碼:

#include <ros/ros.h> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/calib3d/calib3d.hpp> 
#include <vector> 

using namespace cv ; 

int main(int argc, char* argv[]) { 
    ros::init(argc, argv, "bird_view") ; 
    int board_w = atoi(argv[1]); 
    int board_h = atoi(argv[2]); 

    cv::Size board_sz(board_w, board_h); 
    cv::Mat image = cv::imread("image.jpg") ; 
    cv::Mat gray_image, tmp, H , birds_image; 
    cv::Point2f objPts[4], imgPts[4] ; 
    std::vector<cv::Point2f> corners ; 
    float Z = 1 ; //have experimented from values as low as .1 and as high as 100 
    int key = 0 ; 
    int found = cv::findChessboardCorners(image, board_sz, corners) ; 

    if (found) { 
    cv::drawChessboardCorners(image, board_sz, corners, 1) ; 
    cvtColor(image, gray_image, CV_RGB2GRAY) ; 
    cornerSubPix(gray_image, corners, Size(11, 11), Size(-1, -1), 
        TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1)) ; 
    cv::resize(image, tmp, Size(), .5, .5) ; 
    namedWindow("IMAGE") ; 
    cv::imshow("IMAGE" , tmp) ; 
    waitKey(0) ; 
    } 

    objPts[0].x = 0 ; 
    objPts[0].y = 0 ; 
    objPts[1].x = board_w-1 ; 
    objPts[0].y = 0 ; 
    objPts[0].x = 0 ; 
    objPts[0].y = board_h-1 ; 
    objPts[0].x = board_w-1 ; 
    objPts[0].y = board_h-1 ; 

    imgPts[0] = corners.at(0) ; 
    imgPts[1] = corners.at(board_w-1) ; 
    imgPts[2] = corners.at((board_h-1) * board_w) ; 
    imgPts[3] = corners.at((board_h-1) * board_w + board_w-1) ; 

    H = cv::getPerspectiveTransform(objPts, imgPts) ; 

    birds_image = image ; 

    while (key != 27) { 

    H.at<float>(2,2) = Z ; 

    cv::warpPerspective(image, birds_image, H, Size(2 * image.cols, 2 * tmp.rows) , 
         CV_INTER_LINEAR | CV_WARP_INVERSE_MAP | CV_WARP_FILL_OUTLIERS) ; 

    cv::imshow("IMAGE", birds_image) ; 
    cv::waitKey(0) ; 
    } 

    return 0 ; 
} 

所有這些代碼是基於O'Reilly的OpenCV的書的鳥瞰投影例子。我認爲所得到的圖片是正確的,但我肯定不能確定。

回答

2

首先,我看你是覆蓋objPts [0],而不是使用objPts 1 [3]:

objPts[0].x = 0 ; 
objPts[0].y = 0 ; 
objPts[1].x = board_w-1 ; 
objPts[0].y = 0 ; 
objPts[0].x = 0 ; 
objPts[0].y = board_h-1 ; 
objPts[0].x = board_w-1 ; 
objPts[0].y = board_h-1 ; 

現在,getPerspectiveTransform沒有什麼發現,會改變一個轉型假設它們通過homography相關聯,將點p0 ... p3集合成p0'... p3'。如果想要使用warpPerspective進行這樣的轉換,則兩個集合p0 ... p3和p0'... p3'必須以圖像座標(像素)表示,但情況並非如此,因爲objPts是在任意空間中表示的座標。

您是說要getPerspectiveTransform要(像素)圖像座標(像素)的國際象棋圖案的四個角和所產生的圖像座標之間的以下映射

corner0 -> (0,0) 
corner1 -> (board_w-1, 0) 
corner2 -> (0, board_h-1) 
corner3 -> (board_w-1, board_h-1) 

所以,如果board_w例如,10,您將棋盤映射到10像素寬的圖像!這解釋了你獲得的結果。

爲了得到你想要的,你應該在上面的例子的第二列中使用你想要的圖像(像素)座標在鳥的視圖圖像中的國際象棋圖案。例如,如果您希望每個正方形爲10x10像素,請將這些值乘以10.

另外,請記住,您沒有糾正鏡頭失真(反正這看起來不大),並且該模式似乎不適用於是完全平坦的,所以你可能會以稍微彎曲的線條的形式在結果圖像中產生一些「不完美」。

希望這會有所幫助!

+0

謝謝,我添加了一些代碼,現在它工作正常! – joshualan 2013-04-28 21:00:31

2

所以感謝米洛的澄清什麼getPerspectiveTransform呢,我稍微改變我所做的指定點時映射:

std::vector<cv::Point2f> objPts(4) ; 
objPts[0].x = 250 ; 
objPts[0].y = 250 ; 
objPts[1].x = 250 + (board_w-1) * 25 ; 
objPts[1].y = 250 ; 
objPts[2].x = 250 ; 
objPts[2].y = 250 + (board_h-1) * 25 ; 
objPts[3].x = 250 + (board_w-1) * 25 ; 
objPts[3].y = 250 + (board_h-1) * 25 ; 

而且它的偉大工程!它對於每幅圖像都會有所不同,因此請仔細閱讀基本值以及要將圖像轉換爲多大/多小。