画像を一気にリサイズさせたいなーと思うことがあったので備忘録。
リサイズと言っても、縦横ピクセル指定や倍率していなどいろいろありますね。
リサイズの方法は別途記事にするとして、今回は「フォルダ内の画像を倍率指定でリサイズ保存」を目標とします。
非エンジニアでもコードをなんとなーく理解しながらカスタマイズできる..はず!
目標
- フォルダ内の画像(jpgとpng)を一気にリサイズさせたい!
- リサイズ後は名前を変えて全部jpgで保存したい!いやいや、名前も拡張子もそのまま保存したい!
こんなことをやりたい人の参考になるはずです。
解説はいいからコードだけほしい~という人はまとめに飛んでください。
フォルダ構成
初心者がコピペするときの難関!フォルダ構成。
ちゃんと理解しないとパスが通らないエラーになる嫌な奴。。。
今回のフォルダ構成はこんな感じです。
「input」フォルダにある果物の画像をリサイズしていきます。
コード解説
globを使ってフォルダ内の画像ファイルを一覧取得
まずはどのファイルを変換するのかをパソコンに教える必要があります。
globというライブラリを使うと「指定したフォルダ内のファイルをリストとして取得」してくれます。
import glob
# glob.glob(パス)で取得して、img_listというリストに格納する。
# *は正規表現と呼ばれるもので、特に指定せず「inputフォルダの中全部!」という意味。
img_list = glob.glob("./input/*")
# 確認してみよう!
print(img_list)
これだと.txtが入ってしまう><ということで、正規表現を少し工夫してみます。
import glob
# glob.glob(パス)で取得して、img_listというリストに格納する。
# 「*.png」で「.pngの前は何でもいいよ!」という意味。つまり拡張子が.pngのものだけ取ってこれる。
img_list = glob.glob("./input/*.png")
# 確認してみよう!
print(img_list)
これだと「.jpg」が取ってこれなくて困ってしまいます。
glob.globには複数の拡張子を取ってくることができません。
そこでlist.extend()を使ってpngのリストとjpgのリストを合体させます。
import glob
# glob.glob(パス)で取得して、img_listというリストに格納する。
img_list = glob.glob("./input/*.png")
img_list.extend(glob.glob("./input/*.jpg"))
# 確認してみよう!
print(img_list)
この方法の便利な点は、他の拡張子も欲しい!となった際に同じ要領で足していける点です。
画像を読み込んでリサイズ
作成したリストを元に画像を読み込んでリサイズします。
ここではOpenCVという画像の取り扱いが得意なライブラリを使用します。
import glob
import cv2
# glob.glob(パス)で取得して、img_listというリストに格納する。
img_list = glob.glob("./input/*.png")
img_list.extend(glob.glob("./input/*.jpg"))
#img_listの先頭を読み込んでみる。※[0]で1番目、[1]で2番目の値を取得できる。
original_img = cv2.imread(img_list[0])
#リサイズする。
resized_img = cv2.resize(original_img, dsize=None, fx=0.5, fy=0.5)
「cv2.imread(ファイル名。正確にはパス)」で画像ファイルを読み込みます。
※読み込んだ画像はnumpy配列という数値の羅列で管理されるのでヒトが見てもさっぱりです。
次に「cv2.resize(画像, dsize, fx,fy)」でリサイズします。
画像は先ほどimreadで読み込んだものです。今回はorifinal_imgとして読み込んでいます。
dsizeは縦横のピクセル値などを指定する際に使用しますが、今回は「倍率を変える」なのでNoneとします。
fxとfyは縦横のリサイズ倍率です。今回は50%に縮小するのでどちらも0.5とします。
リサイズした画像を保存
まず1枚だけ「sample.png」という名前で保存してみましょう。
import glob
import cv2
# glob.glob(パス)で取得して、img_listというリストに格納する。
img_list = glob.glob("./input/*.png")
img_list.extend(glob.glob("./input/*.jpg"))
#img_listの先頭を読み込んでみる。※[0]で1番目、[1]で2番目の値を取得できる。
original_img = cv2.imread(img_list[0])
#リサイズする。
resized_img = cv2.resize(original_img, dsize=None, fx=0.5, fy=0.5)
#保存する
cv2.imwrite("./output/sample.png", resized_img)
第一引数に保存先のパス、第二引数にリサイズ後の画像をいれてあげればOKです。
画像を全部リサイズする!
クライマックスです。「順番に」画像をfor文で処理してみましょう。
読み込みと保存にちょっと工夫が必要なので注目してみてください。
import glob
import cv2
# glob.glob(パス)で取得して、img_listというリストに格納する。
img_list = glob.glob("./input/*.png")
img_list.extend(glob.glob("./input/*.jpg"))
for i,img in enumerate(img_list):
#img_listの中身を一つずつimgに格納する。
#imgを読み込む。
original_img = cv2.imread(img)
#リサイズする
resized_img = cv2.resize(original_img, dsize=None, fx=0.5, fy=0.5)
#保存する
cv2.imwrite("./output/sample_" + str(i) + ".png", resized_img)
「sample_0.png」~「sample_4.png」まで5枚の画像が確認できましたか?
上書き保存したいor元の名前のまま別のフォルダに保存したい。
ここまできたらちょっと自分好みに調整したいな~と思ったりしませんか。
というわけで挑戦してみましょう。
上書き保存
読み込んだファイル名(パス)と同じところに保存すればOKです。
import glob
import cv2
# glob.glob(パス)で取得して、img_listというリストに格納する。
img_list = glob.glob("./input/*.png")
img_list.extend(glob.glob("./input/*.jpg"))
for i,img in enumerate(img_list):
#img_listの中身を一つずつimgに格納する。
#imgを読み込む。
original_img = cv2.imread(img)
#リサイズする
resized_img = cv2.resize(original_img, dsize=None, fx=0.5, fy=0.5)
#保存する
cv2.imwrite(img, resized_img)
別のフォルダに元の名前のまま保存
これちょっと面倒です。しかし、元データを取っておきたい勢(私)には刺さります。
面倒といいつつpythonは便利なものでファイル名だけを取得する方法があります。「os.path.basename」です。
import glob
import cv2
import os ★osのimportをわすれずに★
# glob.glob(パス)で取得して、img_listというリストに格納する。
img_list = glob.glob("./input/*.png")
img_list.extend(glob.glob("./input/*.jpg"))
for i,img in enumerate(img_list):
#img_listの中身を一つずつimgに格納する。
#imgを読み込む。
original_img = cv2.imread(img)
#リサイズする
resized_img = cv2.resize(original_img, dsize=None, fx=0.5, fy=0.5)
#保存ファイル名を作成
img_name = os.path.basename(img)
#保存する
cv2.imwrite("./output/"+ img_name, resized_img)
こんな感じです!お疲れさまでした。
発展コード解説
余裕がある人は、もーーーーっと便利にカスタマイズしてみましょう!
汎用性を持たせよう!
そのときによってフォルダ違うんだけど..とか、リサイズの設定その都度変えたい..とか思いませんか?
というわけで汎用性の高いコードに変身させてあげましょう!変数を駆使すれば簡単!すぐ!できます。
import glob,cv2,os
# 都度変える変数コーナー
# オリジナル画像のフォルダパス
input_path = "./input/"
# 保存先フォルダパス
output_path = "./output/"
# リサイズ倍率
x = 0.5
y = 0.5
img_list = glob.glob(input_path + "*.png")
img_list.extend(glob.glob(input_path +"*.jpg"))
for i,img in enumerate(img_list):
original_img = cv2.imread(img)
resized_img = cv2.resize(original_img, dsize=None, fx=x, fy=y)
img_name = os.path.basename(img)
cv2.imwrite(output_path + img_name, resized_img)
進捗を確認できるようにしよう!
今回のサンプルではリサイズが5枚なのであっという間ですが、これが1000枚とかになったら時間かかりそうですよね。
そんなときどこまで終わったかな~っていうのを確認する仕組みを組み入れてみます。
「プログレスバー」と呼ばれるものでtqdmというライブラリを使います。
import glob
import cv2
import os
from tqdm import tqdm
★import time
input_path = "./input/"
output_path = "./output/"
x = 0.5
y = 0.5
img_list = glob.glob(input_path + "*.png")
img_list.extend(glob.glob(input_path +"*.jpg"))
with tqdm(total=len(img_list)) as bar:
for i,img in enumerate(img_list):
original_img = cv2.imread(img)
resized_img = cv2.resize(original_img, dsize=None, fx=x, fy=y)
img_name = os.path.basename(img)
cv2.imwrite(output_path + img_name, resized_img)
bar.update(1)
★time.sleep(1)
バーが進むのが早すぎて動作確認できない!という人は★の2か所を追記して見てください。Time.speepで「一時停止」の役割です。
まとめ
今回は「フォルダ内の画像を一気にリサイズする!」というテーマでコードを作成してみました。
出来上がったコードはこちら!
import glob
import cv2
import os
from tqdm import tqdm
# 都度変える変数コーナー
# オリジナル画像のフォルダパス
input_path = "./input/"
# 保存先フォルダパス
output_path = "./output/"
# リサイズ倍率
x = 0.5
y = 0.5
# glob.glob(パス)で取得して、img_listというリストに格納する。
img_list = glob.glob(input_path + "*.png")
img_list.extend(glob.glob(input_path +"*.jpg"))
with tqdm(total=len(img_list)) as bar:
for i,img in enumerate(img_list):
#img_listの中身を一つずつimgに格納する。
#imgを読み込む。
original_img = cv2.imread(img)
#リサイズする
resized_img = cv2.resize(original_img, dsize=None, fx=x, fy=y)
#保存ファイル名を作成
img_name = os.path.basename(img)
#保存する
cv2.imwrite(output_path + img_name, resized_img)
bar.update(1)
以上、業務効率化させたい人に届けば嬉しいです。
コメント