Freigeben über


Accord.Net упрощает добавление стыкованных изображений и панорам в приложение

Грэг Дункан

Знаю, я слегка зациклился на «изображениях», но когда я увидел сегодняшний проект, хотя он и был опубликован год назад, мне понравилось каким образом он демонстрирует то, что вам может показаться трудным (а это так и есть) и то, что вы могли решить никогда не включать в свои приложения. Тем не менее, этот проект, демонстрирующий потрясающий фреймворк, делает это легко. ( И я обещаю, больше не будет материалов об «изображениях» какое-то время. Я их исключил из свой системы… пока не встречу что-то действительно потрясающее…J).

Автоматическая стыковка изображений с помощью Accord . NET

Введение

Accord.NET Framework – относительно новый фреймворк для AForge.NET, популярного набора компьютерного зрения и искусственного интеллекта. Accord.NET реализует средства и возможности, которых до сих пор не было в AForge.NET, такие как поддержка на уровне ядра векторных машин, дискриминантный и проективный анализ, скрытые марковские модели, новые алгоритмы обучения нейронных сетей, новые фильтры изображений и другие полезные методы и инструменты. Среди прочего Accord.NET позволяет создавать программы автоматической стыковки изображений и, возможно, автоматического создания панорам.

Панорама – это картина, созданная объединением серии фотографий в одно большое изображение. Объединяя серию фотографий можно полное изображение области или местности, которое иначе не поместилось бы на один снимок.

В приведенном ниже примере мы покажем, как используя возможности, доступные в Accord.NET стыковать вместе два изображения и создать простую небольшую панораму. В последнем разделе мы обсудим способы обобщения этого метода для множества пар изображений, создавая мозаику изображений.

clip_image002

Для демонстрации мы используем эти две фотографии озера, взятые с сайта UFSCar. Они были сделаны с поворотом в несколько градусов друг относительно друга. Только на втором снимке можно видеть здание гимназии, в то время как самая левая часть озера присутствует лишь на первом снимке.

Что мне нравится, так это глубина статьи. В ней не просто рассказывается о примере, но и о науке и математическом обосновании, стоящим за магией, приводимой в примере.

Выделение особенностей

Чтобы создать нашу панораму воспользуемся главной идеей, состоящей в том, чтобы определить общие точки в обоих изображениях и затем спроектируем одно из них на другое, чтобы эти точки совместились. Чтобы идентифицировать эти точки, отныне будем называть их интересными точками. Мы используем простой детектор интересных точек, известный под названием «Детектор углов Харриса».

Хотя полное описание детектора Харриса находится за рамками этой статьи (но доступно здесь), мне кажется, будет интересно включить небольшой рассказ о детекторе углов и об операторе Харриса.

...

Соответствие элементов

После нахождения интересных точек нам необходимо их как-то сопоставить. Для этого мы используем правило максимальной корреляции, чтобы определить соответствие между двумя изображениями. Кросс-корреляция работает, анализируя окно пикселей вокруг каждой точки первого изображения и коррелируя его с окном пикселей вокруг каждой точки второго изображения. Точки с максимальным значением двусторонней корреляции рассматриваются как соответствующие друг другу.

...

Оценка гомографии

Теперь у нас есть два набора соответствующих точек и нам нужно построить модель преобразования, переводящего точки одного набора в другой. То, что мы ищем, является некоторым видом преобразования изображения, которое используется для проектирования одного из них на другой при условии совпадения большинства коррелированных особых точек – нам требуется найти матрицу гомографии, соответствующую этим двум изображениям.

Гомография – проективное преобразование, вид преобразования, используемого в проективной геометрии. Она описывает, что случиться с воспринимаемыми положениями наблюдаемых объектов, когда изменяется точка зрения наблюдателя. В более формальных терминах: гомография – это обратимое преобразование реальной проективной плоскости на проективную плоскость, переводящее прямые линии в прямые линии.

Используя гомогеничные координаты, можно представить гомографию в виде матрицы 3x3 с восемью степенями свободы.

...

clip_image004

clip_image006

После основательной подготовки в статье рассматривается код:

Исходный код

При использовании Accord.NET код для стыковки изображений становится крайне простым. Помните, что нужно выполнить четыре шага: определение интересных точек, корреляционное соответствие, оценка надежной гомографии и градиентное сопряжение. Поэтому, прежде чем переходить к этим шагам, давайте определим некоторые переменные классов (этот код взят из примера прикладного кода):

Исходный код для этой статьи содержит демонстрационное приложение и небольшое подмножество Accord.NET Framework, чтобы избежать путаницы с пространствами имен. Если вы хотите применять Accord.NET, пожалуйста, убедитесь что скачали самую последнюю версию со станицы проекта Origo. Кстати, в приложении-примере предполагается, что вы будете нажимать кнопки в правильном порядке. Если вы вызовете очередной шаг до того, как предыдущий будет обсчитан, скорее всего, вы получите исключение. Это просто свойство кода, необходимого для стыковки. Также это относится и к коду в следующих разделах.

...

Вот снимок решения (которое у меня скомпилировалось и запустилось с первого раза, и которое породило ряд проектов для рассмотрения, за что я благодарен!):

clip_image008

Вот работающее приложение:

clip_image010

Помните я говорил, что смешение/слияние/стыковка выглядят легко? Вот весь код…

 private void btnHarris_Click(object sender, EventArgs e)
  {
      // Step 1: Detect feature points using Harris Corners Detector
      HarrisCornersDetector harris = new HarrisCornersDetector(0.04f, 1000f);
      harrisPoints1 = harris.ProcessImage(img1).ToArray();
      harrisPoints2 = harris.ProcessImage(img2).ToArray();

      // Show the marked points in the original images
      Bitmap img1mark = new PointsMarker(harrisPoints1).Apply(img1);
      Bitmap img2mark = new PointsMarker(harrisPoints2).Apply(img2);

      // Concatenate the two images together in a single image (just to show on screen)
      Concatenate concatenate = new Concatenate(img1mark);
      pictureBox.Image = concatenate.Apply(img2mark);
  }

  private void btnCorrelation_Click(object sender, EventArgs e)
  {
      // Step 2: Match feature points using a correlation measure
      CorrelationMatching matcher = new CorrelationMatching(9);
      IntPoint[][] matches = matcher.Match(img1, img2, harrisPoints1, harrisPoints2);

      // Get the two sets of points
      correlationPoints1 = matches[0];
      correlationPoints2 = matches[1];

      // Concatenate the two images in a single image (just to show on screen)
      Concatenate concat = new Concatenate(img1);
      Bitmap img3 = concat.Apply(img2);

      // Show the marked correlations in the concatenated image
      PairsMarker pairs = new PairsMarker(
          correlationPoints1, // Add image1's width to the X points to show the markings correctly
          correlationPoints2.Apply(p => new IntPoint(p.X + img1.Width, p.Y)));

      pictureBox.Image = pairs.Apply(img3);
  }

  private void btnRansac_Click(object sender, EventArgs e)
  {
      // Step 3: Create the homography matrix using a robust estimator
      RansacHomographyEstimator ransac = new RansacHomographyEstimator(0.001, 0.99);
      homography = ransac.Estimate(correlationPoints1, correlationPoints2);

      // Plot RANSAC results against correlation results
      IntPoint[] inliers1 = correlationPoints1.Submatrix(ransac.Inliers);
      IntPoint[] inliers2 = correlationPoints2.Submatrix(ransac.Inliers);

      // Concatenate the two images in a single image (just to show on screen)
      Concatenate concat = new Concatenate(img1);
      Bitmap img3 = concat.Apply(img2);

      // Show the marked correlations in the concatenated image
      PairsMarker pairs = new PairsMarker(
          inliers1, // Add image1's width to the X points to show the markings correctly
          inliers2.Apply(p => new IntPoint(p.X + img1.Width, p.Y)));

      pictureBox.Image = pairs.Apply(img3);
  }

  private void btnBlend_Click(object sender, EventArgs e)
  {
      // Step 4: Project and blend the second image using the homography
      Blend blend = new Blend(homography, img1);
      pictureBox.Image = blend.Apply(img2);
  }

  private void btnDoItAll_Click(object sender, EventArgs e)
  {
      // Do it all
      btnHarris_Click(sender, e);
      btnCorrelation_Click(sender, e);
      btnRansac_Click(sender, e);
      btnBlend_Click(sender, e);
  }

 

clip_image012

Если вы собираетесь добавить в приложение обработку изображений, то этот пример может стать первым шагом по дороге Accord.Net/AForge.Net, которая вам нужна…

Вот несколько ссылок, которые могут оказаться интересными: