Как зарегистрировать изображение вручную (регистрация изображения) - PullRequest
1 голос
/ 21 июня 2011

Я конвертирую код из Matlab в C ++, и одна из функций, которые я не понимаю, это imtransform.Мне нужно «зарегистрировать» изображение, что в основном означает растяжение, наклон и поворот моего изображения, чтобы оно правильно перекрывалось с другим изображением.

Imtransform от Matlab выполняет регистрацию за вас, но, поскольку я программирую это на C ++, мне нужно знать, что было абстрагировано.Какая нормальная математика используется при регистрации изображений?Как я могу перейти от 2 массивов данных (которые составляют изображения) к 1 массиву, который является совмещенным изображением с перекрытием?

Ответы [ 2 ]

2 голосов
/ 26 октября 2018

Я рекомендую вам использовать OpenCV в c ++, и есть много инструментов и функций для обработки изображений, которые вы можете вызывать и использовать.

Модуль регистрации осуществляет параметрическую регистрацию изображений.Реализованный метод - прямое выравнивание, то есть он использует непосредственно значения пикселей для вычисления регистрации между парой изображений, в отличие от регистрации на основе признаков.

Константы OpenCV, которые представляют эти модели, имеют префиксMOTION_ и отображаются в скобках.

  • Перевод (MOTION_TRANSLATION): первое изображение можно сдвинуть (перевести) на (x, y), чтобы получить второе изображение.Нам нужно оценить только два параметра x и y.

  • Евклидов (MOTION_EUCLIDEAN): первое изображение является повернутой и сдвинутой версией второго изображения.Таким образом, есть три параметра - х, у и угол.Вы заметите на рисунке 4, когда квадрат претерпевает евклидово преобразование, размер не изменяется, параллельные линии остаются параллельными, а прямые углы остаются неизменными после преобразования.

  • Affine (MOTION_AFFINE): Аффинное преобразование представляет собой комбинацию вращения, сдвига (сдвига), масштаба и сдвига.Это преобразование имеет шесть параметров.Когда квадрат претерпевает аффинное преобразование, параллельные линии остаются параллельными, но линии, встречающиеся под прямым углом, больше не остаются ортогональными.

  • Гомография (MOTION_HOMOGRAPHY): все описанные выше преобразования являются 2Dтрансформирует.Они не учитывают 3D-эффекты.Гомографическое преобразование, с другой стороны, может учитывать некоторые 3D-эффекты (но не все).Это преобразование имеет 8 параметров.Квадрат при преобразовании с использованием гомографии может измениться на любой четырехугольник.

Ссылка: https://docs.opencv.org/3.4.2/db/d61/group__reg.html

Это пример, который я нашел очень полезным для регистрации изображений:

#include <opencv2/opencv.hpp>
#include "opencv2/xfeatures2d.hpp"
#include "opencv2/features2d.hpp"

using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;

const int MAX_FEATURES = 500;
const float GOOD_MATCH_PERCENT = 0.15f;


void alignImages(Mat &im1, Mat &im2, Mat &im1Reg, Mat &h)

{


  Mat im1Gray, im2Gray;
  cvtColor(im1, im1Gray, CV_BGR2GRAY);
  cvtColor(im2, im2Gray, CV_BGR2GRAY);

  // Variables to store keypoints and descriptors
  std::vector<KeyPoint> keypoints1, keypoints2;
  Mat descriptors1, descriptors2;

  // Detect ORB features and compute descriptors.
  Ptr<Feature2D> orb = ORB::create(MAX_FEATURES);
  orb->detectAndCompute(im1Gray, Mat(), keypoints1, descriptors1);
  orb->detectAndCompute(im2Gray, Mat(), keypoints2, descriptors2);

  // Match features.
  std::vector<DMatch> matches;
  Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
  matcher->match(descriptors1, descriptors2, matches, Mat());

  // Sort matches by score
  std::sort(matches.begin(), matches.end());

  // Remove not so good matches
  const int numGoodMatches = matches.size() * GOOD_MATCH_PERCENT;
  matches.erase(matches.begin()+numGoodMatches, matches.end());


  // Draw top matches
  Mat imMatches;
  drawMatches(im1, keypoints1, im2, keypoints2, matches, imMatches);
  imwrite("matches.jpg", imMatches);


  // Extract location of good matches
  std::vector<Point2f> points1, points2;

  for( size_t i = 0; i < matches.size(); i++ )
  {
    points1.push_back( keypoints1[ matches[i].queryIdx ].pt );
    points2.push_back( keypoints2[ matches[i].trainIdx ].pt );
  }

  // Find homography
  h = findHomography( points1, points2, RANSAC );

  // Use homography to warp image
  warpPerspective(im1, im1Reg, h, im2.size());

}


int main(int argc, char **argv)
{
  // Read reference image
  string refFilename("form.jpg"); 
  cout << "Reading reference image : " << refFilename << endl; 
  Mat imReference = imread(refFilename);


  // Read image to be aligned
  string imFilename("scanned-form.jpg");
  cout << "Reading image to align : " << imFilename << endl; 
  Mat im = imread(imFilename);


  // Registered image will be resotred in imReg. 
  // The estimated homography will be stored in h. 
  Mat imReg, h;

  // Align images
  cout << "Aligning images ..." << endl; 
  alignImages(im, imReference, imReg, h);

  // Write aligned image to disk. 
  string outFilename("aligned.jpg");
  cout << "Saving aligned image : " << outFilename << endl; 
  imwrite(outFilename, imReg);

  // Print estimated homography
  cout << "Estimated homography : \n" << h << endl; 

}
1 голос
/ 21 июня 2011

Raw C ++ не имеет встроенных в него концепций, на которые вы ссылаетесь.Однако есть много библиотек обработки изображений для C ++, которые вы можете использовать для различных преобразований. DevIL и FreeImage должны иметь возможность выполнять наложение, а также некоторые преобразования.

...