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

Posted

技术标签:

【中文标题】在 C++ 中计算相似图像的偏移/倾斜/旋转【英文标题】:Calculate offset/skew/rotation of similar images in C++ 【发布时间】:2011-06-30 23:59:29 【问题描述】:

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

图像是 .raw 格式,我一次读取 16 位。

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

【问题讨论】:

如果您真的需要自己编写,请查找(例如)SIFT 算法。不过,除非你真的需要,否则最好使用 Hugin 或 CombineZP 之类的东西,它们已经可以完成这项工作。 此操作的正确术语是图像注册。您可能会从a search on SO 找到答案。 【参考方案1】:

这是一个简短的代码,可以满足您的需求(我使用的是 openCV 2.2):

    假设您有 2 个图像:srcImage、dstImage,并且您想要对齐它们 代码很简单。将其用作算法的基础。

代码:

// 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);

【讨论】:

哇,谢谢!我正在对文档进行第二次(更像是第 100 次)查看,它一直盯着我的脸!感谢您强调我需要更仔细查看的地方以及出色的示例代码。 我似乎在我的 OpenCV 安装 (2.1) 中找不到类 FeatureDetector,即使它在文档中......有什么想法吗?第一行:Ptrdetector = new SurfFeatureDetector(2000);给我:1>.\makeTforms.cpp(34):错误 C2065:'FeatureDetector':未声明的标识符(VS 2008) 我已重新安装,但在任何地方都找不到该文件。安装程序是否更改或什么o_O 我使用的是 opnencv 2.2。文件位于:C:\Program Files\OpenCV2.2\modules\features2d\include\opencv2\features2d。同样在 OpenCV2.2\bin 我有 opencv_features2d220.dll,在 lib 库中有 opencv_features2d220.lib。你在用窗户吗?如果是这样,请尝试从此处安装:sourceforge.net/projects/opencvlibrary/files/opencv-win/2.2 您是否尝试通过我发布的链接进行安装?【参考方案2】:

图像是从同一位置拍摄的,但您只是稍微旋转了一下,导致它们没有正确对齐?如果是这样,则图像通过homography 相关 - 即投影变换。给定图像之间的一组对应关系(至少需要 4 对),查找单应性的标准方法是使用 DLT algorithm。

【讨论】:

【参考方案3】:

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

#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;

【讨论】:

以上是关于在 C++ 中计算相似图像的偏移/倾斜/旋转的主要内容,如果未能解决你的问题,请参考以下文章

数字图像处理PDF文字倾斜旋转校正

[Android]android.graphics.Camera实现图像的旋转缩放,配合Matrix实现图像的倾斜

RotateRect(旋转矩形)的倾斜旋转变换矫正

使用opencv在鼻子和眼睛轴上旋转图像

图像处理-图像的旋转及变换

UIView Swift 倾斜动画