🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Anaconda

Anacondaは、Python本体とPythonで利用されるライブラリを一括でインストールできるパッケージです。環境構築が容易になるため、Python開発者間ではよく利用されており、商用目的としても利用できます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3928閲覧

Pythonで写真の縦横を判別して画像処理したい

TakayukiMoriya

総合スコア26

Anaconda

Anacondaは、Python本体とPythonで利用されるライブラリを一括でインストールできるパッケージです。環境構築が容易になるため、Python開発者間ではよく利用されており、商用目的としても利用できます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/09/10 03:06

何をやっているか

Pythonの画像処理モジュールPillowを使って指定したフォルダ内の写真のをリサイズして、右下にロゴマークを合成して保存する、というプログラムを作っています。

ここまでの進捗

以下コードで横向きの写真にロゴの挿入ができました。ここからさらに進化させたいと考えております。

Python

1import os 2import sys 3import shutil 4from datetime import datetime 5from enum import Enum, auto 6 7import tkinter, tkinter.filedialog 8from PIL import Image 9 10WM_FILE = 'logo.png' #横写真の場合のウォーターマーク画像 11 12class Mode(Enum): 13 BLG = auto() #ブログ用 14 15def mkdir_dto(img, output_dir_path): 16 """画像の撮影日のフォルダを作成する 17 :param img: 画像(PIL) 18 :param output_dir_path: 出力先のフォルダーのパス 19 :return: 作成したフォルダーのパス 20 """ 21 EXIF_DTO = 36867 #Exifの撮影日のタグ番号 22 23 # 移動先フォルダー作成。フォルダー名はExifの撮影日からyyyymmdd形式で生成 24 exif = img._getexif() 25 dt = datetime.strptime(exif[EXIF_DTO], '%Y:%m:%d %H:%M:%S') 26 output_sub_dir = dt.strftime('%Y%m%d') 27 output_path = os.path.join(output_dir_path, output_sub_dir) 28 os.makedirs(output_path, exist_ok=True) 29 30 return output_path 31 32def make_img(img, img_name, mode, watermark, output_path): 33 """画像をリサイズし、ウォーターマークを貼り付け、別名で保存する 34 :param img: 画像(PIL) 35 :param img_name: 画像(PIL)ファイル名 36 :param mode: Mode.BLGならブログ用、Mode.TMBならサムネイル用 37 :param watermark: ウォーターマーク画像(PIL) 38 :param output_path: 出力先フォルダーのパス 39 """ 40 BLG_CHAR = '_s' #ブログ画像のファイル名に付加する文字列 41 MAX_W_BLG = 4000 #ブログ画像の幅の上限 42 MAX_H_BLG = 2400 #ブログ画像の高さの上限 ※こちらはあまり意味のない数値です 43 44 # サイズ、ファイル名の末尾に付加する文字列を設定 45 if (mode == Mode.BLG): #ブログ用 46 w, h = MAX_W_BLG, MAX_H_BLG 47 add_chr = BLG_CHAR 48 49 else: 50 return None 51 52 #リサイズ 53 img.thumbnail((w, h)) 54 55 #ウォーターマークを付加 56 w_img, h_img = img.size 57 w_wm, h_wm = watermark.size 58 img.paste(watermark, (3000, 300), watermark)#ロゴの位置 59 60 #ファイル名に文字列を付加して保存 61 fname, ext = os.path.splitext(img_name) 62 img.save(os.path.join(output_path, fname + add_chr + ext), quality=95, exif=img.info['exif'])#追記 63 64 65# ウォーターマーク画像読み込み 66watermark = Image.open(WM_FILE) 67 68#元画像フォルダー選択 69root = tkinter.Tk() 70root.withdraw() 71msg = '画像フォルダーを選択してください。' 72img_dir_path = tkinter.filedialog.askdirectory(title=msg) 73if (not img_dir_path): #[キャンセル]クリック時の処理 74 print('フォルダーを選んでください。') 75 sys.exit() 76 77#出力先フォルダー選択 78msg = '出力先フォルダーを選択してください。' 79output_dir_path = tkinter.filedialog.askdirectory(title=msg) 80if (not output_dir_path):#[キャンセル]クリック時の処理 81 print('フォルダーを選んでください。') 82 sys.exit() 83 84# 元画像フォルダー内のファイル1つずつ処理 85for img_file in os.listdir(img_dir_path): 86 #元画像読み込み (PIL) 87 img_path = os.path.join(img_dir_path, img_file) 88 img_pil = Image.open(img_path) 89 90 #ファイルの移動先フォルダー作成 91 output_path = mkdir_dto(img_pil, output_dir_path) 92 93 #ブログ用画像とサムネイル用画像を作成 94 make_img(img_pil.copy(), img_file, Mode.BLG, watermark, output_path) 95# make_img(img_pil, img_file, Mode.TMB, watermark, output_path) 96 97 #元画像(PIL)を閉じる 98 img_pil.close()

どう進化させたいか&発生しているエラー

こちらのプログラムに、写真のEixf情報を元に縦写真か横写真かの判別をして横写真ならロゴを右下に、縦写真なら270°回転させたロゴを右上に合成する、という機能を追加したいです。

自分なりに考えて、画像処理の部分にExifの回転に関する情報を取得して条件分岐させるというプログラムを書きましたが、
'Image' object has no attribute '_getexif'
というエラーになってしまいます。

Python

1def make_img(img, img_name, mode, watermark, output_path): 2 """画像をリサイズし、ウォーターマークを貼り付け、別名で保存する 3 :param img: 画像(PIL) 4 :param img_name: 画像(PIL)ファイル名 5 :param mode: Mode.BLGならブログ用、Mode.TMBならサムネイル用 6 :param watermark: ウォーターマーク画像(PIL) 7 :param output_path: 出力先フォルダーのパス 8 """ 9 EXIF_ROT = 274#Exifの回転のタグ番号 10 exif = img._getexif() 11 BLG_CHAR = '_s' #ブログ画像のファイル名に付加する文字列 12 MAX_W_BLG = 4000 #幅の上限 13 MAX_H_BLG = 2400 #高さの上限  14 15 # サイズ、ファイル名の末尾に付加する文字列を設定 16 if (mode == Mode.BLG): #ブログ用 17 w, h = MAX_W_BLG, MAX_H_BLG 18 add_chr = BLG_CHAR 19 20 else: 21 return None 22 23 #リサイズ 24 img.thumbnail((w, h)) 25 26 #ウォーターマークを付加 27 _orientation = exif[EXIF_ROT] 28 w_img, h_img = img.size 29 w_wm, h_wm = watermark.size 30 31 if _orientation == 1: 32 img.paste(watermark, (3000, 300), watermark)#ロゴ位置は仮です 33 34 elif _orientation == 6: 35 img.paste(watermark, (2800, 2000), watermark, ROTATE_270)#ロゴ位置は仮です 36 37 elif _orientation == 8: 38 img.paste(watermark, (400, 2000), watermark, ROTATE_90)# ロゴ位置は仮です 39 40 41 #ファイル名に文字列を付加して保存 42 fname, ext = os.path.splitext(img_name) 43 img.save(os.path.join(output_path, fname + add_chr + ext), quality=95, exif=img.info['exif'])# 44

条件分岐の手前のExif情報を取得するやり方が間違っているのでしょうか?
小生の力不足で恐縮ですが、解決方法があればご教授いただければ幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2019/09/10 10:07

画像の形式(拡張子)は何ですか?
TakayukiMoriya

2019/09/10 10:21

JPEGです。そこにPNGのロゴを合成します。
guest

回答1

0

ベストアンサー

貼り付けるロゴを回転させるのではなく、貼り付ける画像の方を回転させて本来の向きにするほうがロゴの貼り付け位置は同じになるので、いいのではないでしょうか。

以下の記事で Pillow で EXIF タグから回転方向を判定して、画像を本来の向きにする方法が紹介されています。

PILでEXIF Orientationタグを考慮して処理 - Qiita

投稿2019/09/10 03:43

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakayukiMoriya

2019/09/10 06:15

ご回答ありがとうございます。できればEXIFデータを変えることなく処理を行いたいんですよね。何万枚という写真を扱うため、回転させる分処理に時間が掛かりそうな点も心配で… ニッチな悩みですみません
tiitoi

2019/09/10 06:22

今回のエラーの直接の原因は img.copy() した PIL.Image オブジェクトでは EXIF 情報はコピーされないため、そのコピーした画像に対して、_getexif() は呼び出せません。 コピーする前に exif 情報を別の変数に保存しておくなどの修正が必要と思われます。
TakayukiMoriya

2019/09/10 07:07

ありがとうございます。もう少し頑張ってみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問