Как выровнять 2 изображения на основе их содержимого с помощью OpenCV

Я совершенно новичок в OpenCV, и я начал в него погружаться. Но мне нужна небольшая помощь.

Итак, я хочу объединить эти 2 изображения:

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

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

Может ли кто-нибудь указать мне правильное направление? Я попытался использовать функцию findTransformECC. Вот моя реализация:

cv::Mat im1 = [imageArray[1] CVMat3];
cv::Mat im2 = [imageArray[0] CVMat3];

// Convert images to gray scale;
cv::Mat im1_gray, im2_gray;
cvtColor(im1, im1_gray, CV_BGR2GRAY);
cvtColor(im2, im2_gray, CV_BGR2GRAY);

// Define the motion model
const int warp_mode = cv::MOTION_AFFINE;

// Set a 2x3 or 3x3 warp matrix depending on the motion model.
cv::Mat warp_matrix;

// Initialize the matrix to identity
if ( warp_mode == cv::MOTION_HOMOGRAPHY )
    warp_matrix = cv::Mat::eye(3, 3, CV_32F);
else
    warp_matrix = cv::Mat::eye(2, 3, CV_32F);

// Specify the number of iterations.
int number_of_iterations = 50;

// Specify the threshold of the increment
// in the correlation coefficient between two iterations
double termination_eps = 1e-10;

// Define termination criteria
cv::TermCriteria criteria (cv::TermCriteria::COUNT+cv::TermCriteria::EPS,   number_of_iterations, termination_eps);

// Run the ECC algorithm. The results are stored in warp_matrix.
findTransformECC(
                 im1_gray,
                 im2_gray,
                 warp_matrix,
                 warp_mode,
                 criteria
                 );

// Storage for warped image.
cv::Mat im2_aligned;

if (warp_mode != cv::MOTION_HOMOGRAPHY)
    // Use warpAffine for Translation, Euclidean and Affine
    warpAffine(im2, im2_aligned, warp_matrix, im1.size(), cv::INTER_LINEAR + cv::WARP_INVERSE_MAP);
else
    // Use warpPerspective for Homography
    warpPerspective (im2, im2_aligned, warp_matrix, im1.size(),cv::INTER_LINEAR + cv::WARP_INVERSE_MAP);


UIImage* result =  [UIImage imageWithCVMat:im2_aligned];
return result;

Я пробовал играть с termination_eps и number_of_iterations и увеличивать/уменьшать эти значения, но на самом деле это не имело большого значения.

Итак, вот результат:

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

Что я могу сделать, чтобы улучшить свой результат?

РЕДАКТИРОВАТЬ: я отметил проблемные края красными кружками. Цель состоит в том, чтобы деформировать нижнее изображение и сделать так, чтобы оно совпадало с линиями на изображении выше:

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

Я провел небольшое исследование и боюсь, что функция findTransformECC не даст мне желаемого результата :-(

Важно добавить: на самом деле у меня есть массив этих «полос» изображения, в данном случае 8, все они похожи на изображения, показанные здесь, и все они должны быть обработаны, чтобы соответствовать линии. Я пробовал экспериментировать с функцией stitch OpenCV, но результаты были ужасны.

РЕДАКТИРОВАТЬ:

Вот 3 исходных изображения:

1< /а>

2< /а>

3< /а>

Результат должен быть примерно таким:

result< /а>

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


person gasparuff    schedule 11.01.2017    source источник
comment
Можете ли вы показать нам пример того, как вы хотите, чтобы ваш результат выглядел?   -  person Abdulrahman Alhadhrami    schedule 12.01.2017
comment
@alhadhrami Конечно. Я добавил некоторые детали к вопросу.   -  person gasparuff    schedule 12.01.2017
comment
ты не понял меня. Я просил показать пример правильного вывода, вывода, который вы хотели бы создать в своем коде. @гаспарафф   -  person Abdulrahman Alhadhrami    schedule 15.01.2017
comment
Кроме того, можете ли вы предоставить два изображения, чтобы я мог проводить собственные тесты?   -  person Abdulrahman Alhadhrami    schedule 15.01.2017
comment
Привет @alhadhrami. Извините за поздний ответ, было много дел. Я обновлю свой вопрос сегодня вечером и добавлю информацию, которую вы просили. Спасибо   -  person gasparuff    schedule 19.01.2017
comment
Вопрос обновлен :-)   -  person gasparuff    schedule 19.01.2017
comment
в желаемом результате вы уверены в разрывах в этих синих пиках в середине изображений и в частях в крайнем правом углу? Похоже, вы хотите, чтобы некоторые части были непрерывными, а другие нет, есть ли за этим какое-то правило?   -  person Micka    schedule 26.01.2017
comment
Вы можете попробовать алгоритм Хафа для выравнивания изображений, чтобы найти раздражения в выровненных изображениях, и повторять этот алгоритм, пока все нужные строки не будут... хорошо выровнены :-)   -  person Flocke    schedule 26.01.2017
comment
@Micka, да, их можно игнорировать. Если они превышают определенное расстояние, они не должны оказывать никакого влияния на матрицу преобразования.   -  person gasparuff    schedule 27.01.2017
comment
@Flocke Да, вчера я наткнулся на алгоритм hough и начал думать о том, как я могу использовать его для решения своей проблемы. К сожалению, я понятия не имею, как это сделать   -  person gasparuff    schedule 27.01.2017


Ответы (2)


По вашим изображениям кажется, что они пересекаются. Поскольку вы сказали, что функция stitch не дала желаемых результатов, реализуйте собственное сшивание. Я тоже пытаюсь сделать что-то близкое к этому. Вот учебник о том, как реализовать это на С++: https://ramsrigoutham.com/2012/11/22/panorama-image-stitching-in-opencv/

person Rodrigo Maller Martins    schedule 24.01.2017
comment
Спасибо за этот вклад. Действительно, я проверил это, но результаты пока не очень полезны. Я все еще выясняю. - person gasparuff; 25.01.2017

Вы можете использовать алгоритм Хафа с высоким порогом на двух изображениях, а затем сравнить вертикальные линии на обоих из них - большинство из них должны быть немного сдвинуты, но сохраняйте угол.

Вот что я получил, запустив этот алгоритм на одном из изображений:

Алгоритм Houghlines на первом примере

Отфильтровать горизонтальные линии должно быть легко (поскольку они представлены как Vec4i), а затем вы можете выровнять оставшиеся линии вместе.

Вот пример его использования в документации OpenCV .

ОБНОВЛЕНИЕ: еще одна мысль. Выравнивание линий вместе можно выполнить с помощью концепции, аналогичной тому, как работает функция взаимной корреляции. Не имеет значения, если на картинке 1 10 строк, а на картинке 2 100 строк, позиция сдвига с выровненными большинством строк (что, в основном, максимум для CCF) должна быть довольно близкой к ответу. , хотя для этого может потребоваться некоторая настройка - например, придание веса каждой линии в зависимости от ее длины, угла и т. д. Компьютерное зрение никогда не имеет прямого пути, а :)

ОБНОВЛЕНИЕ 2. Мне действительно интересно, если взять строку нижних пикселей верхнего изображения в качестве массива 1 и строку верхних пикселей нижнего изображения в качестве массива 2 и запустить над ними общий CCF, то использование его максимума в качестве сдвига тоже может работать... Но я думаю это был бы известный метод, если бы он работал хорошо.

person Leontyev Georgiy    schedule 27.01.2017
comment
Спасибо за ваш ценный вклад. Хотя я действительно не знаю, как поместить эту теорию в код. Ваше ОБНОВЛЕНИЕ 2 - это то, о чем я тоже думал. Но мне нужно выяснить, как работает CCF. - person gasparuff; 28.01.2017
comment
@gasparuff CCF(A, B) == REV_FFT(FFT(A)*CONJ(FFT(B))), где A, B - входные векторы степени 2 длины, остатки заполнить нулями, БПФ - быстрое преобразование Фурье, а REV_FFT — обратное, CONJ — комплексно-сопряженное. Мнимые части A и B изначально равны нулю, действительные части представляют собой значения оттенков серого соответствующих линий пикселей. Результат CCF тоже сложен, его нужно преобразовать в (re^2)+(im^2) для каждого элемента. - person Leontyev Georgiy; 28.01.2017
comment
Максимальный элемент результата обеспечит нужный вам сдвиг. - person Leontyev Georgiy; 28.01.2017
comment
Можете ли вы показать мне пример того, как это реализовать? Я все еще ищу ответ :-( - person gasparuff; 01.02.2017