#python #numpy #opencv #image-processing
#python #тупой #opencv #обработка изображений
Вопрос:
Я работаю над проектом по обнаружению склеенных (отфотошопленных) изображений и хочу 128×128 патчей на границах подделанных областей. У меня есть подлинное фоновое изображение и поддельное.
Если я просто нахожу разницу в значениях пикселей и применяю пороговое значение для получения двоичного изображения, я получаю много шума (маленькие черные пятна в белой части и наоборот), который не удаляется эффективно cv2.medianBlur()
. Я предполагаю, что это связано с разными коэффициентами сжатия изображений до и после сращивания. Кроме того, некоторые пиксели в склеенной части похожи на соответствующие пиксели в auth. изображение.
Поэтому я заменяю обычную cv2.threshold()
функцию, которая добавляет значения 4-связанных соседей пикселя и сравнивает их с пороговым значением.
Это моя пороговая функция :
def threshold(image,thresh):
b,g,r= cv2.split(image)
res=np.zeros(b.shape,dtype=np.uint8)
#Not considering boundary pixels for the binary image
for i in range(1,b.shape[0]-1):
for j in range(1,b.shape[1]-1):
sumb = b[i][j] b[i 1][j] b[i-1][j] b[i][j 1] b[i][j-1]
sumg = g[i][j] g[i 1][j] g[i-1][j] g[i][j 1] g[i][j-1]
sumr = r[i][j] r[i 1][j] r[i-1][j] r[i][j 1] r[i][j-1]
res[i][j]=255 if sumb<=5*thresh or sumg<=5*thresh or sumr<=5*thresh else 0
res=res[1:-1,1:-1]
res=cv2.copyMakeBorder(res,1,1,1,1,cv2.BORDER_REFLECT_101)
return res
Это дает лучшие результаты, но не такие хорошие, как ожидалось.
Например, это подлинное изображение:
Это склеенное изображение:
Это пороговое изображение (я обнаружил, что thresh=2
это оптимальное значение):
Я попытался удалить небольшие компоненты, удалив компоненты с использованием нескольких белых пикселей connectedComponentsWithStats()
.
Это границы после удаления небольших связанных компонентов:
в то время как ожидаемое изображение:
Я мог бы увеличить минимальное количество пикселей, требуемое для каждого компонента, но в моем наборе данных есть изображения, где подделанная часть небольшая.
Как я могу получить лучшие результаты, чем эти?
Кроме того, можно ли оптимизировать мою threshold
функцию? Прямо сейчас на обработку одного изображения уходит не менее 2 секунд!
Комментарии:
1. Интересная статья доктора Нила Краветца о подделке фотографий здесь … hackerfactor.com/papers/bh-usa-07-krawetz-wp.pdf
2. JPEG (т. Е. сжатие изображения с потерями / шумом, вероятно, усложняет задачу.
Ответ №1:
[У меня сейчас не установлен OpenCV на моем компьютере, поэтому вместо этого я просмотрел ваши изображения в MATLAB. Приведенный ниже код Python не тестировался.]
Поскольку ваши изображения идентичны, за исключением тех случаев, когда были внесены целенаправленные изменения (масштабирование или переводы не учитываются), можно просто вычесть два изображения и посмотреть на разницу:
res = cv2.absdiff(image,thresh)
Если вы отобразите это (с некоторой контрастностью), вы увидите:
Как вы можете видеть, по крайней мере, один из каналов имеет сильную разницу в «склеенной» области, за ее пределами здесь есть несколько очень светлых точек, вызванных сжатием с потерями.
Давайте возьмем максимум по R, G, B для каждого пикселя:
res = np.amax(res, axis=2) # (I think OpenCV stores the channels in the 3rd dimension?)
Я обнаружил, что большинство артефактов сжатия ниже 15, поэтому давайте установим пороговое значение:
res = res > 15
Наконец, примените свой cv2.medianBlur()
, чтобы удалить последние биты шума. Вы также можете попробовать применить GaussianBlur()
до порога.
Комментарии:
1. Ваши 3 строки кода сработали как по волшебству! Я пробовал то же самое очень непитоновским способом — проверял, было ли значение каждого канала для каждого пикселя больше 15 (используя вложенные циклы for ). Я не думаю, что получил тот же результат. Вероятно, какая-то ошибка в моей логике. Большое спасибо!
2. Все еще существует проблема с несколькими изображениями, на которых изменен только фон неба. Абсолютная разница в этих случаях невелика. Как я могу рассмотреть соседние пиксели, чтобы улучшить его, не проходя через циклы снова?
3. @AbdulMuizz: Вы рассматриваете соседние пиксели с помощью фильтра. Я бы предположил
GaussianBlur
, что тогда вы, вероятно, можете снизить порог.