Интерполяция изображения с помощью cv2.resize() изменяет целочисленное положение пикселя

#python #image #opencv #image-processing #interpolation

#python #изображение #opencv #обработка изображений #интерполяция

Вопрос:

Я пытаюсь интерполировать изображение cv2.resize() , сохраняя при этом целочисленный пиксель положения в новом изображении таким же, как и в исходном изображении. Итак, я написал этот код для тестирования:

 import cv2, scipy
import scipy.misc
import numpy as np

im = cv2.imread('img')
print(im[:,:,0].shape)
print(im[:,:,0])

im = cv2.resize(im, None, fx=2, fy=2, interpolation=cv2.INTER_LANCZOS4)

print(im[::2,::2,0].shape)
print(im[::2,::2,0])
 

Вывод:

 (128, 128)
[[79 62 64 ... 81 81 79]
 [73 59 57 ... 79 81 79]
 [69 51 51 ... 90 88 87]
 ...
 [40 48 43 ... 79 84 88]
 [45 46 44 ... 84 84 83]
 [48 46 44 ... 80 80 83]]
(128, 128)
[[82 66 63 ... 82 81 80]
 [76 64 57 ... 80 79 79]
 [71 57 50 ... 90 85 85]
 ...
 [38 46 45 ... 77 84 87]
 [43 46 45 ... 83 84 84]
 [48 47 44 ... 81 81 82]]
 

Приведенный выше код интерполировал изображение 2 раза, и в идеале два выходных данных должны быть одинаковыми, поскольку im[::2,::2,0] должен быть пиксель перед интерполяцией.

Что-то не так в коде или в любом случае, чтобы сделать это правильно?

Комментарии:

1. Вы пробовали интерполяцию ближайшего соседа? Это может дать результат, который вы ищете.

2. ДА. Но производительность ланцоша лучше, чем ближайшая интерполяция. Я пытаюсь использовать griddata() в opencv, чтобы решить эту проблему.

Ответ №1:

В какой-то момент я нашел объяснение системы координат OpenCV, но оно не может найти его обратно, поэтому этот ответ взят из памяти.

OpenCV видит пиксель как маленький квадрат, а не точечную выборку в сетке. Интерполяция на целое число разбивает этот квадрат на меньшие квадраты. При интерполяции четного размера ни один из новых квадратных центров не будет соответствовать исходному квадратному центру.

При интерполяции нечетного размера один из новых квадратов будет в центре, но также будут другие новые квадраты вверху и слева от верхнего левого пикселя исходного изображения. Эти пиксели были экстраполированы!

То есть, если вы думаете об изображении как о наборе образцов, как я, то интерполяция в OpenCV никогда не будет соответствовать вашим ожиданиям.

Решение состоит в том, чтобы сдвинуть изображение на половину исходного пикселя влево и вверх во время интерполяции. Не уверен, как реализовать это в OpenCV.

Или вы можете попробовать skimage.transform.rescale в skimage или diplib.Resampling в DIPlib (я автор). Что касается последнего, я знаю, что он делает правильные вещи из коробки.