1

現在、Visual Studio 2010 で OpenCV 2.3.1 を使用して画像のスティッチングに取り組んでいますが、問題が発生しています。

問題の説明 数台のカメラ (約 3 ~ 4 台) から取得した複数の画像をスティッチングするためのコードを作成しようとしています。

これまでに行ったことは次のとおりです: (簡単にするために、コードの一部をいくつかの単語に置き換えます)

     1.Reading frames(images) from 2 cameras (Currently I'm just working on 2 cameras.)
     2.Feature detection, descriptor calculation (SURF)
     3.Feature matching using FlannBasedMatcher
     4.Removing outliers and calculate the Homography with inliers using RANSAC.
     5.Warp one of both images.

ステップ 5. では、次のスレッドの回答に従い、いくつかのパラメーターを変更しました: Opencv で 2 つの画像をステッチする

しかし、結果はひどいものです。結果を youtube にアップロードしました。もちろん、リンクを知っている人だけが見ることができます。

http://youtu.be/Oy5z_7LeaMk

私のコードを以下に示します:(重要な部分のみが表示されます)

VideoCapture cam1, cam2;
cam1.open(0);
cam2.open(1);

while(1)
{
    Mat frm1, frm2;

    cam1 >> frm1;
    cam2 >> frm2;

   //(SURF detection, descriptor calculation 
   //and matching using FlannBasedMatcher)


    double max_dist = 0; double min_dist = 100;

    //-- Quick calculation of max and min distances between keypoints
    for( int i = 0; i < descriptors_1.rows; i++ )
    { 
        double dist = matches[i].distance;
        if( dist < min_dist ) min_dist = dist;
        if( dist > max_dist ) max_dist = dist;
    }


    (Draw only "good" matches 
    (i.e. whose distance is less than 3*min_dist ))            

    vector<Point2f> frame1;
    vector<Point2f> frame2;

    for( int i = 0; i < good_matches.size(); i++ )
    {
      //-- Get the keypoints from the good matches
      frame1.push_back( keypoints_1[ good_matches[i].queryIdx ].pt );
      frame2.push_back( keypoints_2[ good_matches[i].trainIdx ].pt ); 
    }
    Mat H = findHomography( Mat(frame1), Mat(frame2), CV_RANSAC );
    cout << "Homography: " << H << endl;


    /* warp the image */
    Mat warpImage2;
    warpPerspective(frm2, warpImage2, 
    H, Size(frm2.cols, frm2.rows), INTER_CUBIC); 

    Mat final(Size(frm2.cols*3 + frm1.cols, frm2.rows),CV_8UC3); 

    Mat roi1(final, Rect(frm1.cols, 0, frm1.cols, frm1.rows)); 
    Mat roi2(final, Rect(2*frm1.cols, 0, frm2.cols, frm2.rows)); 

    warpImage2.copyTo(roi2); 
    frm1.copyTo(roi1); 
    imshow("final", final); 

縫製を良くするために他に何をすればよいですか?

また、ホモグラフィ行列を計算し続けるのではなく固定することは合理的ですか? つまり、2 台のカメラ間の角度と変位を自分で指定して、希望を満たすホモグラフィ行列を導き出すということです。

ありがとう。:)

4

2 に答える 2

1

賢明にこれを行っているように聞こえますが、両方のカメラにアクセスでき、それらが互いに静止したままである場合は、オフラインで調整し、オンラインで変換を適用するだけで、アプリケーションがより効率的になります.

注意すべき点の 1 つは、OpenCV のfindHomography関数を使用していると言うことです。ドキュメントから、この関数:

Finds a perspective transformation between two planes.

ただし、ポイントは 3D シーンをイメージングしているため、特定の平面に限定されません。オフラインでキャリブレーションする場合は、両方のカメラでチェス盤を撮影し、検出されたコーナーをこの機能で使用できます。

または、同様の関数で計算できる基本行列を調べることもできます。この行列はカメラの相対的な位置を表していますが、それらを抽出するにはいくつかの作業 (および優れた教科書) が必要です。

見つけることができれば、Richard Hartley と Andrew Zisserman による書籍「Multiple View Geometry in computer vision」のパート II: 「Two-View Geometry」を参照することを強くお勧めします。

于 2012-05-24T07:36:03.730 に答える
0

私は最近、画像登録に取り組んでいます。私のアルゴリズムは 2 つの画像を取り、SURF 特徴を計算し、対応を見つけ、ホモグラフィ行列を見つけて、両方の画像をつなぎ合わせます。次のコードでそれを行いました。

void stich(Mat base, Mat target,Mat homography, Mat& panorama){


Mat corners1(1, 4,CV_32F);
Mat corners2(1,4,CV_32F);
Mat corners(1,4,CV_32F);
vector<Mat> planes;
/* compute corners 
of warped image
*/
corners1.at<float>(0,0)=0;
corners2.at<float>(0,0)=0;
corners1.at<float>(0,1)=0;
corners2.at<float>(0,1)=target.rows;
corners1.at<float>(0,2)=target.cols;
corners2.at<float>(0,2)=0;
corners1.at<float>(0,3)=target.cols;
corners2.at<float>(0,3)=target.rows;

planes.push_back(corners1);
planes.push_back(corners2);

merge(planes,corners);

perspectiveTransform(corners, corners, homography);

/* compute size of resulting 
image and allocate memory
*/
double x_start = min( min( (double)corners.at<Vec2f>(0,0)[0], (double)corners.at<Vec2f> (0,1)[0]),0.0);
double x_end   = max( max( (double)corners.at<Vec2f>(0,2)[0], (double)corners.at<Vec2f>(0,3)[0]), (double)base.cols);
double y_start = min( min( (double)corners.at<Vec2f>(0,0)[1], (double)corners.at<Vec2f>(0,2)[1]), 0.0);
double y_end   = max( max( (double)corners.at<Vec2f>(0,1)[1], (double)corners.at<Vec2f>(0,3)[1]), (double)base.rows);

/*Creating image
with same channels, depth
as target
and proper size
*/
panorama.create(Size(x_end - x_start + 1, y_end - y_start + 1), target.depth());

planes.clear();

/*Planes should
have same n.channels
as target
*/
for (int i=0;i<target.channels();i++){
planes.push_back(panorama);
}

merge(planes,panorama);
    // create translation matrix in order to copy both images to correct places
Mat T;
T=Mat::zeros(3,3,CV_64F);
T.at<double>(0,0)=1;
T.at<double>(1,1)=1;
T.at<double>(2,2)=1;
T.at<double>(0,2)=-x_start;
T.at<double>(1,2)=-y_start;

// copy base image to correct position within output image

 warpPerspective(base, panorama, T,panorama.size(),INTER_LINEAR| CV_WARP_FILL_OUTLIERS);
 // change homography to take necessary translation into account
gemm(T, homography,1,T,0,T);
    // warp second image and copy it to output image
warpPerspective(target,panorama, T, panorama.size(),INTER_LINEAR);
 //tidy
corners.release();
T.release();

}

どんな質問でも試します

于 2012-05-24T09:06:12.063 に答える