
Изменение размеров (масштабирование / 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) в окрестности 4×4 пикселей,
cv.INTER_AREA — передискретизации с использованием отношения площади пикселя,
cv.INTER_LANCZOS4 — интерполяция Ланцоша (Lanczos interpolation) в окрестности 8×8 пикселей.
Для выбора метода — нужно разобраться — какой из этих методов лучше?
По умолчанию, интерполяция выполняется методом 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

orig size: 278 345 resize size: 34 43

orig size: 385 455 resize size: 48 56

Увеличение
orig size: 56 56 resize size: 224 224

orig size: 34 43 resize size: 272 344

orig size: 48 56 resize size: 384 448

Сравнение скорости работы различных методов интерполяции при масштабировании изображений в 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)")
Полученное графическое представление скорости работы алгоритмов:
Заключение
Полученные данные говорят сами за себя.
Для уменьшения масштаба изображения, лучше всего подходит метод 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 шаг за шагом. Обработка изображения — изменение размеров
