Jump to content
Compvision.ru
DennerV

Получить общие точки SURF

Recommended Posts

Добрый день!
Стоит задача в сравнении изображения с камеры с эталонным изображением. На данный момент реализован поиск объекта и поворот изображения.

Сравнение пытался сделать через AbsDiff, проблема в том, что из-за качества картинки изображения получаются не пиксель в пиксель, а с небольшим смещением и/или поворотом в 1-2 градуса.

Придумал что можно использовать SURF. Найти общие ключевые точки и при из помощи более точно позиционировать (если нудно масштабировать) изображения. Нашел пример использования SURF. Подскажите как получить отдельно общие точки?

Может есть более лучший способ сравнения 2 изображений, чтоб получить их отличия?

 

Пример изобрадения

 

25.04.2017 11-53-09-1.jpg

25.04.2017 12-44-50-1.jpg

Share this post


Link to post
Share on other sites

Спасибо, буду разбирать пример

10 минут назад, Nuzhny сказал:

Можно и способ побыстрее, например того же cv::matchTemplate должно хватить.

Не подойдет, я потому-что заранее не известно что искать, Т.е. задача заключается в сравнении 2-х плат в показать расхождения (отсутствующий или лишний элемент), например показать синий кусок пластика на фото

Share this post


Link to post
Share on other sites

Если всё как на картинках выше, то совпадение всё равно найдётся. А так да, с точками надёжней.

Share this post


Link to post
Share on other sites
1 час назад, DennerV сказал:

одойдет, я потому-что заранее не известно что искать, Т.е. задача заключается в сравнении 2-х плат в показать расхождения (отсутствующий или лишний элемент), например показать синий кусок пластика на фото

При обработке приведенных Вами изображений я вижу следующие проблемы:

1. Это освещение. Оно должно быть мягким, равномерным и не давать бликов.

2. Как правило элементы на разных платах установлены по разному, могут быть смещения, резисторы, конденсаторы, транзисторы, диоды могут быть под небольшими углами (что допускается по ГОСТу). Как вы планируете это учитывать?

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

Share this post


Link to post
Share on other sites
39 минут назад, 2expres сказал:

При обработке приведенных Вами изображений я вижу следующие проблемы:

1. Это освещение. Оно должно быть мягким, равномерным и не давать бликов.

2. Как правило элементы на разных платах установлены по разному, могут быть смещения, резисторы, конденсаторы, транзисторы, диоды могут быть под небольшими углами (что допускается по ГОСТу). Как вы планируете это учитывать?

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

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

Насчет смещений я тоже думал об этом, самый простой вариант найти разность изображений (AbsDiff) а после найти контуры. Слишком маленькие контуры отсеивать, мелкие (небольшие смещения) уйдут, крупные (элементы/пустые места), останутся, тут уж придется действовать методом тыка.

На данный момент проблема с точным позиционированием полученного изображения относительно контрольного

Share this post


Link to post
Share on other sites

Подскажите как происходит сопоставление найденных точек? В примере drawMatches и все. Мне же нужно взять несколько общих точек на обоих изображениях, знать их координаты, чтоб можно было оценить положение, разнице в размере. Откуда берется дистанция между точками?

Share this post


Link to post
Share on other sites

У каждой точки есть дескриптор и точки сравниваются по дескрипторам, обычно L2 norm.

Положение точки хранится в KeyPoint, а вот получить 'окрестность' точки, на сколько я понимаю, не тривиально, хотя это наверно зависит от метода подсчёта дескриптора.

Например в FAST окрестность вроде фиксированная, но все равно наверно ищется на нескольких скейлах.

fast1.png?w=640&h=320

Share this post


Link to post
Share on other sites

Как это можно сделать (сопоставление) самому?

Допустим есть modelDescriptors - 50 точек и observedDescriptors 100 - точек, общие - пусть будет 20 точек. Каким образом пробежаться по modelDescriptors  и найти/не найти точкам пару в observedDescriptors .

Например:

modelDescriptors [0] - пара не найдена

modelDescriptors [1], координаты (25, 37) - пара observedDescriptors[8], координаты (183, 347)

modelDescriptors [2], координаты (75, 81) - пара observedDescriptors[14], координаты (7, 34)

modelDescriptors [3] - пара не найдена

что-то в этом духе

Как связаны modelKeyPoints и modelDescriptors? Порядковыми номерами или есть какие-то внутренние идентификаторы?

 

Share this post


Link to post
Share on other sites

А неизвестно, какие точки каким соответствуют - это проблема. Один из способов решения - алгоритм RANSAC. Ещё один - итеративное приближение перспективного преобразования (или гомографии) методом наименьших квадратов.

В примере всем этим занимается функция  findHomography, которая из правильных и неправильных соответствий находи матрицу преобразования. Эти алгоритмы тоже не всесильны и могут ошибиться, но не в твоём случае с платами.

И уже после того, как отработала  findHomography и найдено преобразование ты можешь найти точные соответствия между наборами точек. А именно: умножаешь каждую точку из первого набора на матрицу гомографии, получаешь координаты точки на втором изображении и ищешь точное соответствие из второго набора.

Только так.

Share this post


Link to post
Share on other sites

После findHomography получил Mat 3x3? немного не понятно как координату умножить на матрицу, т.е. М1(1, 2) * М2(3, 3). Размеры же не совпадают, или нужно еще какие-то преобразования произвести?

Я тут подумал, может не обязательно сопоставлять все точки, а можно найти матрицу гомографии и по ней сразу трансформировать все изображение?

Share this post


Link to post
Share on other sites

Надо к координатам добавить 1 и получится вектор 3х1. Это называется однородные координаты.

Share this post


Link to post
Share on other sites
var srcPoints = modelKeyPoints.ToArray().Select(x => x.Point).ToList().GetRange(0, Math.Min(modelKeyPoints.Size, observedKeyPoints.Size)).ToArray();
var destPoints = observedKeyPoints.ToArray().Select(x => x.Point).ToList().GetRange(0, Math.Min(modelKeyPoints.Size, observedKeyPoints.Size)).ToArray();
Mat hom = new Mat();
CvInvoke.FindHomography(srcPoints, destPoints, hom, HomographyMethod.Ransac, 5);

var arr = hom.GetData();
var b = new double[,] {
        {BitConverter.ToDouble(arr, 0), BitConverter.ToDouble(arr, 8), BitConverter.ToDouble(arr, 16)},
        {BitConverter.ToDouble(arr, 24), BitConverter.ToDouble(arr, 32), BitConverter.ToDouble(arr, 40)},
        {BitConverter.ToDouble(arr, 48), BitConverter.ToDouble(arr, 56), BitConverter.ToDouble(arr, 64)}
};
        for (var i = 0; i < matches.Size; i++) {
           var match = matches[i].ToArray();
           if (mask.GetData(i)[0] == 0)
              continue;
           foreach (var e in match) {
               var a = new double[] {modelKeyPoints[e.QueryIdx].Point.X, modelKeyPoints[e.QueryIdx].Point.Y, 1.0};
               var c = multiplication(a, b);
               MessageBox.Show(string.Format("Point: {0}", c));
           }
       }

массив b после перевода из байт в дубл содержит отрицательные числа, что мне кажется неправильным. Или я не так перевел?

Какой порядок координат должен быть? (x, y, z)?

Share this post


Link to post
Share on other sites

1. Отрицательные конечно могут быть: там же смещения и углы поворота есть. Можно же поворачивать в разные стороны и сдвигаться в разные стороны.

2. (x, y, 1). Откуда на плоскости z?

Share this post


Link to post
Share on other sites
3 минуты назад, Nuzhny сказал:

1. Отрицательные конечно могут быть: там же смещения и углы поворота есть. Можно же поворачивать в разные стороны и сдвигаться в разные стороны.

2. (x, y, 1). Откуда на плоскости z?

под z я имел ввиду 1

когда умножаю координаты на матрице то получаю отрицательные координаты, а такого уже быть не может

Может неправильно что-то перевожу или порядок спутал

Умножение:

return new[] {a[0]*b[0, 0] + a[1]*b[1, 0] + a[2]*b[2, 0],
                     a[0]*b[0, 1] + a[1]*b[1, 1] + a[2]*b[2, 1],
                     a[0]*b[0, 2] + a[1]*b[1, 2] + a[2]*b[2, 2]}

Получение b, написал выше, тип должен быть дубл?

Share this post


Link to post
Share on other sites

Код на С# выглядит довольно страшно и громоздко. Умножать как обычно: строка на столбец, всё как в школе учили.

Отрицательные значения координат появиться могут: допустим, плата смещена на втором изображении сильно влево, выходит за границы. Конечно, координаты будут отрицательными.

А нельзя написать пример на С++, убедиться, что он работает, а только потом переписывать? Потому что проблемы с типами (double или float) быть могут, почему нет? В С++ проблем с этим нет, потому что всё решается на этапе компиляции. А твои конверты типа BitConverter.ToDouble(arr, 0) могут привести к чему угодно, если ты с типом не угадал.

P.S. В очередной раз убеждаюсь, что лучше всего писать такого рода приложения на С++ или Питоне, в крайнем случае на Матлабе.

Share this post


Link to post
Share on other sites

В моем случае отрицательных координат быть не должно, во всяком случае больших маленьких чисел, потому-что  картинки почти одинаковые.

findHomography  возвращает Мат типа double, это не я придумал

На выходных подумаю/почитаю, может что в голову да и придет

Спасибо

Share this post


Link to post
Share on other sites

С гомографиейй так до конца и не разобрался

Прочел здесь http://stackoverflow.com/questions/28725273/opencv-drawmatches-error, что matches содержит сопоставление между точками matches[0].TrainIdx и matches[0].QueryIdx, так ли это? Правильно ли я понял?

Посчитал длины отрезков соседних точек - вроде как сходится, по координатам тоже похоже.

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

Share this post


Link to post
Share on other sites

cv::warpPerspective

P.S. Я люблю читать исходники библиотек, которые использую. Можно делать это и в отладчике. После этого большинство вопросов проясняется.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

×