在 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,即使它在文档中......有什么想法吗?第一行:Ptr图像是从同一位置拍摄的,但您只是稍微旋转了一下,导致它们没有正确对齐?如果是这样,则图像通过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++ 中计算相似图像的偏移/倾斜/旋转的主要内容,如果未能解决你的问题,请参考以下文章