Соответствие шаблону OpenCV и прозрачность
Каким образом OpenCV обрабатывает прозрачность изображения во время сопоставления с шаблоном?
Проблема в том, что шаблонное изображение должно иметь прозрачные части, потому что в исходном изображении в этих местах может быть что угодно.
Я перепробовал все методы, и ни один из них не дал положительных результатов (например, позиция шаблона на исходном изображении была обнаружена неправильно).
8 ответов
Не похоже, что OpenCV обрабатывает альфа так, как вы этого хотите.
У вас есть два варианта:
- Напишите свой собственный метод взаимной корреляции, который будет использовать альфа-канал
- Преобразуйте свои изображения, чтобы ваш альфа-канал стал неактуальным
Поскольку первый вариант прост, я рассмотрю второй вариант здесь. Я собираюсь повторно использовать пример кода, который я предоставил для аналогичного вопроса ранее. Если вы применяете взаимную корреляцию непосредственно к вашим изображениям, фон мешает сопоставлению с шаблоном (в частности, светлым фоновым частям). Если вы поиграете с цветными каналами, вы обнаружите, что совпадение в синем канале дает правильный результат. Это зависит от содержимого изображения и не является последовательным способом решения проблемы.
Другой вариант - выполнить определение края (например, Sobel) на изображении и шаблоне, а затем выполнить взаимную корреляцию. Вот изображения, обнаруженные по краям (я использовал детектор краев Собеля на канале Luma в GIMP, а затем немного растянул по интенсивности).
Как вы можете видеть, альфа-канал здесь стал неактуальным, так как большая часть местности стала нулевой интенсивностью и не будет вносить вклад в расчет взаимной корреляции. Так что теперь кросс-корреляция может быть применена напрямую, давая желаемый результат:
misha@misha-desktop:~/Desktop/stackru$ python cross-correlation.py map-blue.png building-maskz-blue.png
(163, 244)
Наконец, вот еще один связанный вопрос.
PS. Какая игра это?
OpenCV 3.0 предлагает встроенную поддержку сопоставления шаблонов с замаскированными шаблонами. Обратитесь к новой документации:
Параметры:
изображение...
Templ...
результат...
метод...
маска Маска искомого шаблона. Он должен иметь тот же тип данных и размер, что и шаблон. Это не установлено по умолчанию.
[Небольшое отступление]
Обратите внимание, что сопоставление шаблона с замаскированными эталонными изображениями (увеличенное изображение) невозможно. И это имеет смысл, учитывая, что OpenCV использует сопоставление шаблонов на основе FFT.
Поэтому, если вам нужно выполнить сопоставление с шаблоном только в определенных областях ваших эталонных изображений, вам нужно будет реализовать свой собственный метод для этого или замаскировать вывод cv::matchTemplate.
Внедрение его с нуля должно компенсировать случаи, когда вы хотите искать шаблон только в очень специфических регионах (например, по углам Харриса).
У меня есть немного более умопомрачительное решение этой проблемы, которое на самом деле, кажется, работает достаточно хорошо: замените альфа-канал шаблонного изображения шумом, который более или менее делает прозрачные области статистически незначимыми во время процесса сопоставления.
Например, мой сценарий использования включал поиск символов эмодзи на снимках экрана с iOS. Фон клавиатуры iOS меняет цвет в зависимости от контекста, что затрудняет процесс сопоставления, если вы фиксируете определенный цвет фона в изображении шаблона.
Вот необработанное шаблонное изображение на альфе:
Вот обработанный шаблон с заполнением шума для альфа-канала:
Я отправил обработанное изображение шаблона через образец кода соответствия шаблонов, предоставленный в документации OpenCV. На темном или светлом фоне совпадение найдено с достаточной уверенностью.
Поиск на темном фоне:
Поиск на светлом фоне:
Для сравнения, оставление прозрачного альфа-канала шаблона - или фиксация на темном или светлом фоне - не возвращало приемлемых совпадений.
OpenCV обрабатывает прозрачность как часть изображения, а не игнорирует ее, что может привести к непреднамеренным результатам. Я справляюсь с этим, используя шаблон с прозрачностью в качестве
template
и
mask
параметр в
matchTemplate()
. Я ответил на аналогичный вопрос здесь с более подробной информацией, может быть, это поможет.
SQDIFF/SQDIFF_N
вариант будет решением, если вы попытаетесь заменить альфа-канал на черный цвет RGB. По крайней мере, это было моим решением той же проблемы. Из моего результата очевидно, что этот метод чувствителен к ярким пиксельным значениям, и я воспользовался этой возможностью.
Я думаю, что вы пытаетесь сделать то, что в OpenCV называется сопоставлением шаблона с маской. Я думаю, что вы можете попробовать установить ROI (область интересов) на шаблоне. Этот ТАК вопрос показывает, как это сделать. (обратите внимание, что в этом вопросе ROI устанавливается на целевом изображении, а не на шаблоне, но процедура такая же).
Я не уверен, но канал прозрачности рассматривается как любой другой канал. Если пиксель в шаблоне "прозрачный", он должен быть "прозрачным" и на основном изображении. Я просто догадываюсь здесь.
Я столкнулся с той же проблемой, и я подумал о решении. Предполагая, что referenceImageMask и templateMask имеют 1 в хороших пикселях и 0 в плохих. И эти referenceImage и templateImage уже замаскированы и также имеют 0 в плохих пикселях.
Затем первый результат сопоставления с шаблоном даст ненормализованную взаимную корреляцию между изображениями. Однако куча пикселей были нулевыми.
Второе сопоставление шаблона даст для каждого возможного смещения количество пикселей, которые в то же время отличались от нуля (без маски) на обоих изображениях.
Затем, нормализация корреляции по этому числу должна дать значение, которое вы (и я) хотели. Среднее произведение для пикселей, которые не маскируются на обоих изображениях.
Image<Gray, float> imCorr = referenceImage.MatchTemplate(templateImage, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR);
Image<Gray, float> imCorrMask = referenceImageMask.MatchTemplate(templateMask, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR);
_imCorr = _imCorr.Mul(_imCorrMask.Pow(-1));
ОБНОВЛЕНИЕ: фактически, это решение не работает. Поскольку реализация взаимной корреляции в opencv использует ДПФ, возникнут числовые проблемы, и вы не можете использовать вторую взаимную корреляцию для исправления первой.