Перейти к содержимому
Compvision.ru

Recommended Posts

DennerV    0

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

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

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

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

 

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

 

25.04.2017 11-53-09-1.jpg

25.04.2017 12-44-50-1.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    207

SURF - да, подойдёт. См. пример из OpenCV.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    207

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2expres    3
1 час назад, DennerV сказал:

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0
39 минут назад, 2expres сказал:

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

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mrgloom    236

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

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

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

fast1.png?w=640&h=320

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0

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

Допустим есть 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? Порядковыми номерами или есть какие-то внутренние идентификаторы?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    207

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

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

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

Только так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    207

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0
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)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    207

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0
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, написал выше, тип должен быть дубл?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    207

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0

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

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

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

Спасибо

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
DennerV    0

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Nuzhny    207

cv::warpPerspective

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×