OpenCV - cравнение алгоритмов интерполяции при изменении размеров изображения

OpenCV

Изменение размеров (масштабирование / scaling) — это очень часто используемый метод при работе с изображениями.
В OpenCV для выполнения этой задачи используется функция resize().

В C++:
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )

В Python:
dst = cv2.resize( src, dsize[, dst[, fx[, fy[, interpolation]]]] )


Размер изображения можно либо указать вручную (dsize), либо передать коэффициенты масштабирования по соответствующим осям картинки: fx, fy.

height, width = img.shape[:2]
res = cv.resize(img, (2*width, 2*height), interpolation = cv.INTER_CUBIC)
# ИЛИ
res = cv.resize(img, None, fx=2, fy=2, interpolation = cv.INTER_CUBIC)


Параметр interpolation устанавливает один из нескольких возможных методов интерполяции:
cv.INTER_NEAREST — интерполяция методом ближайшего соседа (nearest-neighbor interpolation),
cv.INTER_LINEAR — билинейная интерполяция (bilinear interpolation (используется по умолчанию),
cv.INTER_CUBIC — бикубическая интерполяция (bicubic interpolation) в окрестности 4x4 пикселей,
cv.INTER_AREA — передискретизации с использованием отношения площади пикселя,
cv.INTER_LANCZOS4 — интерполяция Ланцоша (Lanczos interpolation) в окрестности 8x8 пикселей.

Для выбора метода — нужно разобраться — какой из этих методов лучше?
По умолчанию, интерполяция выполняется методом cv.INTER_LINEAR.
В официальном учебном пособии OpenCV (Geometric Transformations of Images) указывается, что:
* для сжатия изображения — наиболее предпочтительным методом интерполяции является cv.INTER_AREA,
* для увеличения изображения — наиболее предпочтительны методы интерполяции: cv.INTER_CUBIC (медленный) и cv.INTER_LINEAR.

Остаётся провести сравнение работы различных методов интерполяции, чтобы на практике проверить — какой их них лучше подходит для уменьшения или увеличения изображений.

Сравнение работы различных методов интерполяции при масштабировании изображений в OpenCV



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

Подключаем нужные библиотеки:

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline 

np.random.seed(42)

import seaborn as sns
plt.style.use('seaborn-white')
sns.set_context('notebook', rc={'figure.figsize': (10, 8)}, font_scale=1.5)

import cv2
print('OpenCV version:', cv2.__version__)


OpenCV version: 3.4.2


Загружаем тестовые картинки:

imgorig = cv2.imread('cat4.jpg')
imgorig2 = cv2.imread('cat2.jpg')
imgorig3 = cv2.imread('cat3.jpg')

img = cv2.cvtColor(imgorig, cv2.COLOR_BGR2RGB)
print(img.shape)

img2 = cv2.cvtColor(imgorig2, cv2.COLOR_BGR2RGB)
print(img2.shape)

img3 = cv2.cvtColor(imgorig3, cv2.COLOR_BGR2RGB)
print(img3.shape)


(224, 224, 3)
(278, 345, 3)
(385, 455, 3)


Задаём типы интерполяции:

interpolation_algorithm = [ 
    ("nearest", cv2.INTER_NEAREST), 
    ("bilinear", cv2.INTER_LINEAR), 
    ("bicubic", cv2.INTER_CUBIC), 
    ("area", cv2.INTER_AREA),
    ("lanczos4", cv2.INTER_LANCZOS4)
]


Тестирование:

def resize_test(img, factor, is_plot=True, file_name=None):
    height, width, channels = img.shape
    height2, width2 = int(height*factor), int(width*factor)
    print('orig size:', height, width)
    print('resize size:', height2, width2)

    imgs = []
    for alg in interpolation_algorithm:
        img_r = cv2.resize(img, (width2, height2), interpolation = alg[1])
        imgs.append(img_r)

    if is_plot:
        plt.figure(figsize=(11, 2))
        plt.subplot(1, len(imgs)+1, 1)
        plt.title('orig')
        plt.imshow(img)
        plt.axis('off')
        for i in range( len(imgs) ):
            plt.subplot(1, len(imgs)+1, i+2)
            plt.title( interpolation_algorithm[i][0] )
            plt.imshow(imgs[i])
            plt.axis('off')
        plt.subplots_adjust(wspace=0)
        if file_name != None:
            plt.savefig(file_name)
        plt.show()
    
    return imgs

print('DOWN')
img_down0 = resize_test(img, 0.25, file_name='opencv_resize_down1.png')
img_down1 = resize_test(img2, 0.125, file_name='opencv_resize_down2.png')
img_down2 = resize_test(img3, 0.125, file_name='opencv_resize_down3.png')
print('UP')
img_up0 = resize_test(img_down0[3], 4, file_name='opencv_resize_up1.png')
img_up1 = resize_test(img_down1[3], 8, file_name='opencv_resize_up2.png')
img_up2 = resize_test(img_down2[3], 8, file_name='opencv_resize_up3.png')


Уменьшение

orig size: 224 224
resize size: 56 56

cравнение алгоритмов интерполяции при изменении размеров изображения

orig size: 278 345
resize size: 34 43

cравнение алгоритмов интерполяции при изменении размеров изображения

orig size: 385 455
resize size: 48 56

cравнение алгоритмов интерполяции при изменении размеров изображения

Увеличение

orig size: 56 56
resize size: 224 224

cравнение алгоритмов интерполяции при изменении размеров изображения

orig size: 34 43
resize size: 272 344

cравнение алгоритмов интерполяции при изменении размеров изображения

orig size: 48 56
resize size: 384 448

cравнение алгоритмов интерполяции при изменении размеров изображения

Сравнение скорости работы различных методов интерполяции при масштабировании изображений в OpenCV



Дополнительно рассмотрим сравнение скорости работы различных алгоритмов интерполяции.

import pandas as pd
import time


Выполним 50 раз процедуру изменения масштаба изображения с разным коэффициентом масштабирования и разными алгоритмами интерполяции:

n = 50
data = []
factors = [0.125, 0.25, 0.5, 0.75, 1.25, 1.5, 2, 3, 4, 6, 8, 10]
for alg in interpolation_algorithm:
    for factor in factors:
        times = []
        for i in range(n):
            t0 = time.time()
            cv2.resize(img, None, fx=factor, fy=factor, interpolation=alg[1])
            tdelta = (time.time()-t0)
            times.append(tdelta)
        mtime = np.mean(times)
        err = 2*np.std(times)
        data.append(dict(time=mtime, algorithm=alg[0], error=err, scale=factor))
df = pd.DataFrame(data)

ax = df.set_index('scale').groupby("algorithm")['time'].plot(legend=True, figsize=(10, 8), grid=True, title='Algorithm time compare')
ax[0].set_xlabel("scale factor")
ax[0].set_ylabel("mean time (sec)")


Полученное графическое представление скорости работы алгоритмов:
cравнение скорости работы алгоритмов интерполяции при изменении размеров изображения

Заключение


Полученные данные говорят сами за себя.
Для уменьшения масштаба изображения, лучше всего подходит метод cv2.INTER_AREA.
Для увеличения масштаба изображения, лучше всего подходят методы (расположены в порядке уменьшения скорости работы): cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_LANCZOS4.

За исключением cv2.INTER_LANCZOS4 — все методы имеют сравнимое время работы.
Однако cv2.INTER_CUBIC и cv2.INTER_LINEAR более медленные, чем cv2.INTER_AREA и cv2.INTER_NEAREST, а cv2.INTER_LANCZOS4 — самый медленный из всех алгоритмов.

Ссылки
Geometric Transformations of Images
resize()
Comparison of OpenCV Interpolation Algorithms

По теме
OpenCV шаг за шагом. Обработка изображения — изменение размеров
  • 0
  • 21 марта 2019, 16:11
  • noonv

Комментарии (0)

RSS свернуть / развернуть

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.