Инвариант шаблона соответствия масштаба и поворота

12

Я ищу метод для масштабирования и вращения Инвариант соответствия шаблона. Я уже попробовал некоторые, но они не работали так хорошо для моих примеров или потребовались навсегда, чтобы выполнить. Обнаружение SIFT и SURF полностью не удалось. Я также пытался реализовать функцию согласования логарифмических шаблонов, но я так и не закончил (точно не знал, как это сделать).

В этих статьях (первая на немецком языке)

http://cvpr.uni-muenster.de/teaching/ss08/seminarSS08/downloads/Wentker-Vortrag.pdf

http://www.jprr.org/index.php/jprr/article/viewFile/355/148

Я читал об этом методе. Отображение полярных координат сработало, но я не знаю, правильно ли это. Изображения выглядят так.

source_log_polar.png http://www.shareimages.com/images/pics/0/0/3/62394-pZSfl5WenZysnpyVnKg-source_log_polar.png

template_log_polar.png

И после сопоставления этих двух изображений с функцией сопоставления шаблонов OpenCV я получил этот результат

match_log_polar.png

Теперь я не знаю, как идти дальше.

Мои шаблоны всегда являются простыми символами в построении чертежей и самих чертежей. Символы могут отличаться по размеру и ориентации.

Например, мой простой план:

введите описание изображения здесь

И мой шаблон

введите описание изображения здесь

В этом примере есть только один шаблон, но в чертежах он должен найти все вхождения, даже те, которые имеют размеры и / или ориентации.

У кого-нибудь есть подход, как я мог это решить?

Редактировать:

Дополнение к подходу Андрея. Алгоритм захвата расстояния для радиального профиля. (Используя EmguCV)

private float[] getRadialProfile( Image<Gray, byte> image, Point center, int resolution )
 {

 var roi = image.ROI;

 if ( !roi.Contains( center ) )
  {
   return null;
  }

 var steps = resolution;
 var degreeSteps = 360 / (double)resolution;
 var data = image.Data;
 var peak = 0.0f;
 var bottom = double.MaxValue;
 var bottomIndex = 0;
 var width = roi.Width;
 var height = roi.Height;
 var minX = roi.X;
 var minY = roi.Y;

 float[] distances = new float[resolution];
 for ( var i = 0; i < steps; i++ )
  {
   var degree = i * degreeSteps;
   var radial = degree * Math.PI / 180.0;
   var dy = Math.Sin( radial );
   var dx = Math.Cos( radial );

   var x = (double)center.X;
   var y = (double)center.Y;

   while ( true )
    {
    x += dx;
    y += dy;
    if ( x >= minX + width || y >= minY + height || x <= minX || y <= minY )
     {
      x = -1;
      y = -1;
      break;
     }
    var pixel = data[(int)y, (int)x, 0];
    if ( pixel == 0 )
     {
      break;
     }
    }

    float distance = 0.0f;
    if ( x != -1 && y != -1 )
    {
      distance = (float)Math.Sqrt( Math.Pow( (center.X - x), 2 ) + Math.Pow( (center.Y - y), 2 ) );
    }

    distances[i] = distance;
    if ( distance > peak )
    {
      peak = distance;
    }
    if ( distance < bottom )
    {
      bottom = distance;
      bottomIndex = i;
    }
   }

    // Scale invariance. Divide by peak
   for ( var i = 0; i < distances.Length; i++ )
   {
     distances[i] /= peak;
   }

    // rotation invariance, shift to lowest value
   for ( var i = 0; i < bottomIndex; i++ )
   {
     distances.ShiftLeft(); // Just rotates the array nothing special
   }

   return distances;
}
Арндт Биберштейн
источник
добро пожаловать на dsp.SE. Мы постараемся вам помочь, но было бы неплохо предоставить более точную информацию. Что вы подразумеваете под SIFT и SURF "полностью провалились"? Что они обнаружили / соответствуют? Кроме того, я лично не знаю насчет Log-Polar Template Matching, но, если вы попробовали, где именно проблема?
Пенелопа
При обнаружении признаков SIFT и SURF не было обнаружено никаких признаков в изображении шаблона. Казалось, в шаблоне слишком мало информации (только этот маленький лук и строчка). Для логарифмического сопоставления я нашел статью, где она описана, но не точную математику за ней. Я буду искать его и добавить.
Арндт Биберштейн
Здесь мы идем: cvpr.uni-muenster.de/teaching/ss08/seminarSS08/downloads/... (немецкий) статьи и этот jprr.org/index.php/jprr/article/viewFile/355/148
Арндта Биберштейн
Эй, не многие здесь понимают немецкий язык, я думаю: D Но для всего остального: вы можете отредактировать свой собственный пост, добавив любую новую информацию в нужное место, а не в комментарии. И, кроме того, вы все еще не сказали, с чем именно у вас были проблемы.
Пенелопа
3
У автора "немецкой статьи" есть статья на английском языке - www-cs.engr.ccny.cuny.edu/~wolberg/pub/icip00.pdf (спасибо Google)
SergV

Ответы:

6

Я думаю, что вы можете решить свою проблему гораздо проще. Учитывая, что вы имеете дело с чертежами, вам не нужно беспокоиться о пограничном соединении, шуме и многих других вещах, для которых были созданы SIFT и SURF. Ваш шаблон представляет собой полую форму с определенными краями.

Таким образом, моя рекомендация:

  • Пройдите по периметру и найдите профиль расстояний по краям вокруг центра шаблона. Это радиальный профиль шаблона. Разделите на наибольшее расстояние, чтобы быть масштабным инвариантом. Поверните вектор так, чтобы наименьшее расстояние было первым, чтобы быть инвариантным к вращению. (Если ваш шаблон не имеет доминирующего расстояния, вы можете изменить шаг 2 позже)

введите описание изображения здесь

  • Найдите капли на картинке. Вычислите радиальный профиль, описанный в части (1), и сравните два вектора по нормализованной корреляции. Если ваш шаблон не имеет доминирующего расстояния, корреляция становится нормализованной кросс-корреляцией и выбирается максимальная). Те, кто проходит некоторый порог, считаются совпадениями.

Вот некоторый код Matlab, с которого вы можете начать - я написал часть, которая находит профиль расстояния для определенного большого двоичного объекта и вычисляет его для шаблона:

function Doors
    im = imread('http://i.stack.imgur.com/Tf8EV.png');
    im = im(:,:,1);
    template = imread('http://i.stack.imgur.com/PlP4i.png');
    template = template(:,:,1);

    blobs = regionprops(template>0,'Area','Image');
    largestBlob = GetLargestBlob(blobs);
    [prof,edgeImage] = GetBlobRadialProfile(largestBlob);

    figure;
    subplot(1,2,1);plot(prof); title('Radial profile')
    subplot(1,2,2);imshow(edgeImage); title('Template');

end

function [prof,edgeImage] = GetBlobRadialProfile(blob)
    paddedImage = padarray( blob.Image,[8 8]);
    erodedImage = imerode(paddedImage,strel('disk',1));
    edgeImage = xor(erodedImage,paddedImage);

    c = regionprops(paddedImage,'Centroid');
    cx  = c.Centroid(1);
    cy  = c.Centroid(2);

    [y,x] = find(edgeImage);
    rad = (x(:)-cx).^2 + (y(:)-cy).^2;
    [~,minIndex] = min(rad);
    contour = bwtraceboundary(edgeImage, [y(minIndex), x(minIndex)],'N');
    prof = (contour(:,2)-cx).^2 + (contour(:,1)-cy).^2;
    prof = prof./max(prof);
end

function largestBlob = GetLargestBlob(blobs)    
    area = [blobs.Area];
    [~,index] = max(area);
    largestBlob = blobs(index);
end
Андрей Рубштейн
источник
Я думаю, это не работает с незамкнутыми формами? Или я просто пропущу эти "дыры" в форме.
Арндт Биберштейн
@ArndtBieberstein, да, это работает только для закрытых форм. Я предполагаю, что должен быть какой-то метод для его расширения.
Андрей Рубштейн 12.12.12
Так как OpenCV не содержит функцию bwtraceboundary, я написал свою собственную и просто «пропустил» дыры и заполнил нулями. Вот небольшой пример того, как теперь выглядят результаты. 5 участков для каждого шаблона. Красная точка - это отправная точка. Образец сюжета
Арндт Биберштейн
@ArndtBieberstein, очень мило! Может быть, вы могли бы поделиться результатами с нами, когда вы закончите.
Андрей Рубштейн 12.12.12
Конечно, Кодекс не так хорош или эффективен, но он работает. Я приложу это ниже моего Вопроса. Это написано на C # (я использую EmguCV)
Арндт Биберштейн
3

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

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

  1. Вычислить края с помощью детектора края Беркли.
  2. Соединить края получается. «Обнаружение границ глобального объекта».
  3. Соответствие формы с использованием расстояния Chamfer или Houstoff Distance.

Его статья об этом доступна по адресу: Многоэтапное обнаружение деформируемых объектов на основе контура.

С другой стороны, я думаю, что SIFT должен работать, так как алгоритмы обнаружения углов будут работать на основе имеющейся у вас функции шаблона.

Примечание: SIFT не является полностью инвариантным к вращению. Это не в состоянии справиться с вращениями> 60 градусов или около того. Поэтому формирование нескольких шаблонов - хорошая идея.

Как на лог-полярных преобразованиях Фурье-Меллина: они вызывают потерю информации из-за того, как осуществляется выборка для преобразований.

Naresh
источник
Этот метод звучит действительно многообещающе! Я не могу открыть вашу ссылку, но я погуглил ваш подход. Я не знал, что SIFT, что SIFT - это не полностью вариант вращения! Очень хороший ответ! +1
Арндт Биберштейн
1
Я почти ничего не нашел о Chamfer Distance и о том, как он работает, для тех, кто тоже ищет это, воспользуйтесь этой ссылкой.
Арндт Биберштейн
@Naresh SIFT не является инвариантным к вращению для больших поворотов вне плоскости. Не в одной плоскости.
а-Джейс
1

Я не задумывался об этом, но я уверен, что можно найти надежное решение без особых проблем, используя классические дескрипторы Фурье (FD). Я думаю, что ваша проблема может быть очень хорошим кандидатом для этого. Не думайте, что вам нужно определять края, потому что у вас есть черные линии. Просто начните растровое сканирование, пока не дойдете до пикселей, а затем выполните следующее:

Просто обработайте периметры вашей комнаты так, как если бы они были одномерным сигналом, где амплитуда сигнала - это нормальное расстояние от центра тяжести объекта, отобранного с некоторой постоянной частотой. Итак, сделайте простую модель FD для двери. Затем отсканируйте параметр каждой комнаты с помощью своего рода выпуклого фильтра в поисках нарастающего фронта, пика и спада, который устанавливает окно запуска / остановки «сигнала» для захвата. Сделайте FFT или аналогичный алгоритм FD для этого захваченного «сигнала» и сравните с шаблоном FD. Может быть, шаг сравнения шаблонов может быть простой корреляцией с пороговым значением для запуска совпадения. Так как только у ваших дверей есть закругленные края, это должно быть довольно легкой проблемой соответствия FD.

Думайте об этом как об использовании FD для поиска изображений или музыки из базы данных. Много белой книги по этому вопросу.

Это хороший учебник по использованию FD для аппроксимации форм: я сомневаюсь, что он вам понадобится, но вы также можете сначала преобразовать ваши изображения в полярную систему координат, чтобы справиться с поворотами, как предложено в этой статье: поиск изображений на основе формы с использованием универсальный дескриптор Фурье

Посмотрите, как они FD параметризуют обнаружение периметра яблока? Та же идея, что и твоя дверь.

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

дайте мне знать, как это происходит, если вы попробуете этот подход.

Ариэль Бентолила
источник
0

Возможно, вы найдете этот код Matlab, который я написал, полезным: Fractal Mosaics

В ней реализована статья «Надежная регистрация изображений с использованием логополярного преобразования» ( pdf ) в художественном приложении, которое требовало большей надежности, чем традиционные методы, которые я обнаружил.

user2348114
источник