在C ++中计算类似图像的偏移/倾斜/旋转

时间:2011-06-30 23:59:29

标签: c++ image-processing opencv image-manipulation

我同时从同一起始位置指向同一方向拍摄了多张图像。然而,由于这些相机在拍照时不在精确相同位置,因此仍有轻微偏移。我正在寻找一种方法来计算应用于将一个图像与另一个图像匹配所需的最佳平移/剪切/倾斜/旋转,以便它们(几乎)完美地叠加。

图像采用.raw格式,我一次只能读取16位。

我被建议(由我的雇主不是程序员[我是实习生])来拍摄源图像的一部分(不是边缘)和强力搜索相同大小的部分与数据值高度相关。我希望有一个不那么浪费的算法。

3 个答案:

答案 0 :(得分:10)

这是一个做你想要的短代码(我使用openCV 2.2):

  1. 假设你有两张图片:srcImage,dstImage,你想对齐它们
  2. 代码非常简单。使用它作为算法的基础。
  3. 代码:

    // Detect special points on each image that can be corresponded    
    Ptr<FeatureDetector>  detector = new SurfFeatureDetector(2000);  // Detector for features
    
    vector<KeyPoint> srcFeatures;   // Detected key points on first image
    vector<KeyPoint> dstFeatures;
    detector->detect(srcImage,srcFeatures);
    detector->detect(dstImage,dstFeatures); 
    
    // Extract descriptors of the features
    SurfDescriptorExtractor extractor;  
    Mat projDescriptors, camDescriptors;
    extractor.compute(srcImage,  srcFeatures, srcDescriptors);
    extractor.compute(dstImage , dstFeatures, dstDescriptors );
    
    // Match descriptors of 2 images (find pairs of corresponding points)
    BruteForceMatcher<L2<float>> matcher;       // Use FlannBasedMatcher matcher. It is better
    vector<DMatch> matches;
    matcher.match(srcDescriptors, dstDescriptors, matches);     
    
    // Extract pairs of points
    vector<int> pairOfsrcKP(matches.size()), pairOfdstKP(matches.size());
    for( size_t i = 0; i < matches.size(); i++ ){
        pairOfsrcKP[i] = matches[i].queryIdx;
        pairOfdstKP[i] = matches[i].trainIdx;
    }
    
    vector<Point2f> sPoints; KeyPoint::convert(srcFeatures, sPoints,pairOfsrcKP);
    vector<Point2f> dPoints; KeyPoint::convert(dstFeatures, dPoints,pairOfdstKP);
    
    // Matched pairs of 2D points. Those pairs will be used to calculate homography
    Mat src2Dfeatures;
    Mat dst2Dfeatures;
    Mat(sPoints).copyTo(src2Dfeatures);
    Mat(dPoints).copyTo(dst2Dfeatures);
    
    // Calculate homography
    vector<uchar> outlierMask;
    Mat H;
    H = findHomography( src2Dfeatures, dst2Dfeatures, outlierMask, RANSAC, 3);
    
    // Show the result (only for debug)
    if (debug){
       Mat outimg;
       drawMatches(srcImage, srcFeatures,dstImage, dstFeatures, matches, outimg, Scalar::all(-1), Scalar::all(-1),
                   reinterpret_cast<const vector<char>&> (outlierMask));
       imshow("Matches: Src image (left) to dst (right)", outimg);
       cvWaitKey(0);
    }
    
    // Now you have the resulting homography. I mean that:  H(srcImage) is alligned to dstImage. Apply H using the below code
    Mat AlignedSrcImage;
    warpPerspective(srcImage,AlignedSrcImage,H,dstImage.Size(),INTER_LINEAR,BORDER_CONSTANT);
    Mat AlignedDstImageToSrc;
    warpPerspective(dstImage,AlignedDstImageToSrc,H.inv(),srcImage.Size(),INTER_LINEAR,BORDER_CONSTANT);
    

答案 1 :(得分:0)

拍摄的图像是否位于相同的位置,但是您只是旋转了一点,以至于它们没有正确对齐?如果是,那么图像通过homography相关 - 即投影变换。给定图像之间的一组对应关系(您需要至少4对),找到单应性的标准方法是使用DLT algorithm

答案 2 :(得分:0)

使用以下代码避免链接器错误:

#include "cv.h"
#include "highgui.h"
using namespace cv;

// Directives to linker to include openCV lib files.
#pragma comment(lib, "opencv_core220.lib") 
#pragma comment(lib, "opencv_highgui220.lib") 
#pragma comment(lib, "opencv_contrib220.lib") 
#pragma comment(lib, "opencv_imgproc220.lib") 
#pragma comment(lib, "opencv_gpu220.lib") 
#pragma comment(lib, "opencv_video220.lib") 
#pragma comment(lib, "opencv_legacy220.lib") 

#pragma comment(lib, "opencv_ml220.lib") 
#pragma comment(lib, "opencv_objdetect220.lib") 
#pragma comment(lib, "opencv_ffmpeg220.lib") 

#pragma comment(lib, "opencv_flann220.lib") 
#pragma comment(lib, "opencv_features2d220.lib") 
#pragma comment(lib, "opencv_calib3d220.lib") 

// Your code here...
int main(void){
    Mat B = Mat:eye(3,3,CV_8U);
    return -1;
}