ディレクトリ内にある画像をリサイズしたいとき、いつも同じようなコードを作り直している気がするので、メモがてらQiitaに投稿しようと思う。
必要なもの
- Python 3.10
- OpenCV for python (opencv-pythonでインストールすると楽)
使い方
下記のどちらかのコマンドを実行するだけ!
srcdirにある画像をリサイズしてdstdirに出力します。
# サイズを指定してリサイズ (サイズは`{width}x{height}`で指定する)
$ python3 image_resizer.py /path/to/srcdir /path/to/dstdir -s 320x240
# 割合でリサイズ
$ python3 image_resizer.py /path/to/srcdir /path/to/dstdir -r 0.5
ソースコード
import cv2
import argparse
import os
import sys
import numpy as np
from typing import Generator, Tuple
def valid_size(arg_str: str) -> (int, int):
try:
(width, height) = arg_str.split('x', 2)
if width.isdecimal() and height.isdecimal():
return (int(width), int(height))
else:
raise ValueError()
except:
raise argparse.ArgumentTypeError('size argument is invalid. please input value "{width}x{height}" like this: 800x600')
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument('srcdir', type=str, help='Please enter your images directory')
parser.add_argument('dstdir', type=str, help='Please enter your output directory')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-s', '--size', type=valid_size, help='resize parameter (you can specify resize size directly)')
group.add_argument('-r', '--ratio', type=float, help='resize ratio parameter (you can specify resize ratio)')
return parser.parse_args()
def image_loader(dirname: str) -> Generator[Tuple[str, np.ndarray], None, None]:
for filename in os.listdir(dirname):
filepath = os.path.join(dirname, filename)
image: np.ndarray = cv2.imread(filepath, -1)
if image is None:
continue
yield filepath, image
def image_resize(image: np.ndarray, size: (int, int) = None, ratio: float=None):
if (size is not None):
return cv2.resize(image, size, interpolation=cv2.INTER_CUBIC)
else:
return cv2.resize(image, None, fx=ratio, fy=ratio, interpolation=cv2.INTER_CUBIC)
def main():
args = get_args()
print(args.srcdir)
if not os.path.isdir(args.srcdir):
print(f'{args.srcdir} is not directory.')
return 1
print(args.size, args.ratio)
os.makedirs(args.dstdir, exist_ok=True)
for (filepath, image) in image_loader(args.srcdir):
filename = os.path.basename(filepath)
dstfilepath = args.dstdir
dstfilepath = os.path.join(args.dstdir, filename)
dst_image = image_resize(image, size=args.size, ratio=args.ratio)
cv2.imwrite(dstfilepath, dst_image)
if __name__ == '__main__':
sys.exit(main())