Pynote

Python、機械学習、画像処理について

OpenCV - 画像をリサイズする方法

resize()

resize() で画像のりサイズが行える。

dst = cv.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
  • 引数
    • src: 入力画像
    • dsize: 出力サイズ
    • dst: 出力画像
    • fx: x 方向のスケール
    • fy: y 方向のスケール
    • interpolation: 補完方法
  • 返り値
    • dst: 出力画像

dsize で出力の大きさを指定するか、fx, fy で幅及び高さ方向の倍率を指定する。
dsize を指定した場合、fx=0, fy=0 とし、fx, fy を指定した場合、dsize=None としなければならない。

補完方法には次から選べる。デフォルトはバイリニア補間である。

基本的な使い方

今回使用する画像

画像を読み込む。

import cv2
import matplotlib.pyplot as plt
import numpy as np

# 画像を読み込む。
img = cv2.imread('harinezumi.jpg')
print('original size:', img.shape)  # original size: (400, 400, 3)

plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()

指定した大きさにリサイズする。

# (100, 300) にリサイズする。
scaled = cv2.resize(img, dsize=(100, 300))
print('{} -> {}'.format(img.shape, scaled.shape))

指定した倍率でリサイズする。

# (round(400 * 0.702), round(400 * 0.702) にリサイズする。
scaled = cv2.resize(img, dsize=None, fx=0.702, fy=0.702)
print('{} -> {}'.format(img.shape, scaled.shape))  # (400, 400, 3) -> (281, 281, 3)

アスペクト比を固定して、幅が指定した値になるようリサイズする。

def scale_to_width(img, width):
    scale = width / img.shape[1]
    return cv2.resize(img, dsize=None, fx=scale, fy=scale)

scaled = scale_to_width(img, 250)
print('{} -> {}'.format(img.shape, scaled.shape))  # (400, 400, 3) -> (250, 250, 3)

アスペクト比を固定して、高さが指定した値になるようリサイズする。

def scale_to_height(img, width):
    scale = width / img.shape[1]
    return cv2.resize(img, dsize=None, fx=scale, fy=scale)

scaled = scale_to_height(img, 300)
print('{} -> {}'.format(img.shape, scaled.shape))  # (400, 400, 3) -> (300, 300, 3)

指定した大きさまたは倍率でスケールする。

def scale(img, width, height, keep_aspect=True):
    if keep_aspect:
        scale = max(width / img.shape[1], height / img.shape[0])
        return cv2.resize(img, dsize=None, fx=scale, fy=scale)
    else:
        return cv2.resize(img, (width, height))

scaled = scale(img, 200, 100, keep_aspect=False)
print('{} -> {}'.format(img.shape, scaled.shape))  # (400, 400, 3) -> (100, 200, 3)

scaled = scale(img, 200, 100, keep_aspect=True)
print('{} -> {}'.format(img.shape, scaled.shape))  # (400, 400, 3) -> (200, 200, 3)

アスペクト比を固定して、指定した解像度にリサイズする。

リサイズ前の大きさを (w, h), リサイズ後の大きさを (W, H)、リサイズの倍率を s とする。
このとき、リサイズ後の解像度を resolation とするには、

 \displaystyle
\begin{align}
W &= w * s \\
H &= h * s \\
W * H &= resolation
\end{align}

を解いて、倍率を s = \sqrt{\frac{resolation}{w * h}} と決めればよい。

def scale_to_resolation(img, resolation):
    h, w, c = img.shape
    scale = np.sqrt(resolation / (h * w))
    return cv2.resize(img, dsize=None, fx=scale, fy=scale)

scaled = scale_to_resolation(img, 640 * 480)
print('{} -> {}'.format(img.shape, scaled.shape))  # (400, 400, 3) -> (554, 554, 3)