Рассчитать смещение / наклон / поворот похожих изображений в C ++ - PullRequest
6 голосов
/ 01 июля 2011

У меня есть несколько изображений, снятых одновременно в одном направлении из одного и того же места. Тем не менее, есть небольшое смещение, потому что эти камеры не были в точном том же месте, когда делали снимок. Я ищу способ расчета оптимального перемещения / сдвига / перекоса / поворота, необходимого для применения, чтобы сопоставить одно изображение другому, чтобы они наложились (почти) идеально.

Изображения в формате .raw, который я читаю по 16 бит за раз.

Мне предложили (мой работодатель, который не программист [я стажер между прочим]) взять часть исходного изображения (не по краям) и выполнить поиск методом грубой силы для части того же размера с высокой корреляцией в значениях данных. Я надеюсь, что есть менее расточительный алгоритм.

Ответы [ 3 ]

10 голосов
/ 01 июля 2011

Вот краткий код, который делает то, что вы хотите (я использую openCV 2.2):

  1. Предположим, у вас есть 2 изображения: srcImage, dstImage, и вы хотите выровнять их
  2. Код очень прост. Используйте его как основу для вашего алгоритма.

Код:

// 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);
0 голосов
/ 04 июля 2011

Избегайте ошибок компоновщика, используя следующий код:

#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;
}
0 голосов
/ 01 июля 2011

Изображения, снятые с одной и той же позиции, но вы просто немного повернули, чтобы они не были правильно выровнены?Если это так, то изображения связаны гомографией - т.е. проективным преобразованием.Учитывая набор соответствий между изображениями (вам нужно как минимум 4 пары), стандартный способ найти гомографию - использовать алгоритм DLT .

...