【Python・OpenCV】画像の拡大・縮小をマスターする(cv2.resize)

※当サイトではアフィリエイト広告を利用しています

Python プログラミング 画像処理

【Python・OpenCV】画像の拡大・縮小をマスターする(cv2.resize)

2023-02-22

はじめに

OpenCVは、画像処理における強力なツールですが、初めて使う人にとっては多くの機能があり、最初は戸惑うことがあります。この記事では、OpenCVの中でも基本的な機能であるcv2.resize関数に焦点を当て、その使い方を解説します。

画像のサイズ変更

画像のサイズ変更はcv2.resize関数を使います。
拡大・縮小のいずれも対応していて、補間方法を選択することも可能です。
変更するサイズの指定方法は縦横のサイズを指定する方法と縦横の倍率を指定する2通りの方法があります。

cv2.resize関数

cv2.resize(入力画像, dsize[, dst[, fx[, fy[, interpolation]]]])

引数

名称説明
入力画像(必須)入力画像
dsize(必須)画像のサイズを(横サイズ, 縦サイズ)の様にタプルで指定。整数のみ。
dst(オプション)結果がこの変数に格納されます。指定しない場合は、入力画像と同じサイズ・型で新しい配列が作成されて結果が格納され、戻り値として取得できます。
fx(オプション)水平方向の倍率係数。0の場合はdsize値から自動計算されます。
fy(オプション)垂直方向の倍率係数。0の場合はdsize値から自動計算されます。
interpolation(オプション)補間方法(InterpolationFlags)の指定(デフォルト:cv2.INTER_LINEAR)

引数のInterpolationは以下の様に定義されています。

補間方法説明
cv2.INTER_NEAREST最近傍法(ニアレストネイバー法)
cv2.INTER_LINEARバイリニア補間法
cv2.INTER_CUBICバイキュービック補間法
cv2.INTER_AREAピクセル領域の関係を使用したリサンプリングを行います。
画像の縮小した場合にモアレのない結果となり、画像を拡大した場合には、cv2.INTER_NEARESTに似た結果となります。
cv2.INTER_LANCZOS48x8近傍に対するのLanczos補間法。
cv2.INTER_LINEAR_EXACTBit exact バイリニア補間法。
cv2.INTER_NEAREST_EXACTBit exact 最近傍法。この方法はPIL, scikit-imageまたはMatlabの最近傍法と同じ結果となります。
InterpolationFlags

戻り値

サイズ変更後の画像データ(numpy.ndarray)

使い方

入力画像として、この画像を使用しました。

入力画像(256x256)

引用元
http://www.ess.ic.kanagawa-it.ac.jp/app_images_j.html

縦横のサイズを指定する方法

以下のコードでは横方向のサイズ取得して2倍にした値を設定し、横方向のサイズを変更します。

# 画像を読み込み
image = cv2.imread("image.jpg")
# 画像のサイズを取得
h, w = image.shape[:2]
# 画像のサイズを指定:幅を2倍にリサイズ
result = cv2.resize(image, (w * 2, h))

縦横の倍率を指定する方法

以下のコードでは縦方向の倍率を2倍に設定し、縦方向のサイズを変更します。

# 画像を読み込み
image = cv2.imread("image.jpg")
# 画像のサイズの倍率を指定:高さを2倍にリサイズ
result = cv2.resize(image, None, fx=1, fy=2)

ポイント

cv2.resize関数の二つ目の引数にNoneを指定するのを忘れないでください!

補間方法について

各種補完方法の差異について確認しました。以下に各補間方法の結果を示します。
縦横サイズを1/2に縮小した後、元のサイズに戻しています。
個人的な感想ですが、cv2.INTER_NEARESTcv2.INTER_NEAREST_EXACTが画像の劣化が少ない様です。

cv2.INTER_NEAREST
cv2.INTER_NEAREST
cv2.INTER_LINEAR
cv2.INTER_LINEAR
cv2.INTER_CUBIC
cv2.INTER_CUBIC
cv2.INTER_AREA
cv2.INTER_AREA
cv2.INTER_LANCZOS4
cv2.INTER_LANCZOS4
cv2.INTER_LINEAR_EXACT
cv2.INTER_LINEAR_EXACT
v2.INTER_NEAREST_EXACT
cv2.INTER_NEAREST_EXACT
   

サンプルコード

ここまでに紹介したリサイズ処理のすべてのサンプルコードは下になります。

import cv2

# 画像の読み込み
image = cv2.imread("image.jpg")

# 画像のサイズを指定:幅を2倍にリサイズ
h, w = image.shape[:2]
result = cv2.resize(image, (w * 2, h))
cv2.imwrite("画像のサイズを指定:幅を2倍.jpg", result)

# 画像のサイズの倍率を指定:高さを2倍にリサイズ
result = cv2.resize(image, None, fx=1, fy=2)
cv2.imwrite("画像のサイズの倍率を指定:高さを2倍.jpg", result)

# 補間方法の比較:縦横を1/2に縮小後、縦横を2倍に拡大して元のサイズに戻して補間方法の結果を確認
h, w = image.shape[:2]
x_scale1 = 0.5
y_scale1 = 0.5
x_scale2 = 2.0
y_scale2 = 2.0

# INTER_NEAREST
result = cv2.resize(image, None, fx=x_scale1, fy=y_scale1, interpolation=cv2.INTER_NEAREST)
result = cv2.resize(image, None, fx=x_scale2, fy=y_scale2, interpolation=cv2.INTER_NEAREST)
cv2.imwrite("resize_INTER_NEAREST.jpg", result)

# INTER_LINEAR
result = cv2.resize(image, None, fx=x_scale1, fy=y_scale1, interpolation=cv2.INTER_LINEAR)
result = cv2.resize(image, None, fx=x_scale2, fy=y_scale2, interpolation=cv2.INTER_LINEAR)
cv2.imwrite("resize_INTER_LINEAR.jpg", result)

# INTER_CUBIC
result = cv2.resize(image, None, fx=x_scale1, fy=y_scale1, interpolation=cv2.INTER_CUBIC)
result = cv2.resize(image, None, fx=x_scale2, fy=y_scale2, interpolation=cv2.INTER_CUBIC)
cv2.imwrite("resize_INTER_CUBIC.jpg", result)

# INTER_AREA
result = cv2.resize(image, None, fx=x_scale1, fy=y_scale1, interpolation=cv2.INTER_AREA)
result = cv2.resize(image, None, fx=x_scale2, fy=y_scale2, interpolation=cv2.INTER_AREA)
cv2.imwrite("resize_INTER_AREA.jpg", result)

# INTER_LANCZOS4
result = cv2.resize(image, None, fx=x_scale1, fy=y_scale1, interpolation=cv2.INTER_LANCZOS4)
result = cv2.resize(image, None, fx=x_scale2, fy=y_scale2, interpolation=cv2.INTER_LANCZOS4)
cv2.imwrite("resize_INTER_LANCZOS4.jpg", result)

# INTER_LINEAR_EXACT
result = cv2.resize(image, None, fx=x_scale1, fy=y_scale1, interpolation=cv2.INTER_LINEAR_EXACT)
result = cv2.resize(image, None, fx=x_scale2, fy=y_scale2, interpolation=cv2.INTER_LINEAR_EXACT)
cv2.imwrite("resize_INTER_LINEAR_EXACT.jpg", result)

# INTER_NEAREST_EXACT
result = cv2.resize(image, None, fx=x_scale1, fy=y_scale1, interpolation=cv2.INTER_NEAREST_EXACT)
result = cv2.resize(image, None, fx=x_scale2, fy=y_scale2, interpolation=cv2.INTER_NEAREST_EXACT)
cv2.imwrite("resize_INTER_NEAREST_EXACT.jpg", result)

おわりに

画像のサイズ変更は比較的利用頻度が高い機能ではないでしょうか。
本記事では補完方法の違いについて画像を載せていますが、口元の白いヒゲの表現でそれらの違いがわかるのではないでしょうか。
個人的な感想ではcv2.INTER_LINEARcv2.INTER_LINEAR_EXACTはやや劣化しているように思いました。
また、画像の種類によってアルゴリズムの差が出にくいこともあるような気がします。

サンプルコードで使った、画像の書き出し方法についてはこちらの記事を参考にして下さい。

参考記事

最後までご覧頂きありがとうございました。

■(広告)OpenCVの参考書としてどうぞ!■

参考リンク

-Python, プログラミング, 画像処理
-