Изменение размеров (масштабирование / 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 шаг за шагом. Обработка изображения — изменение размеров