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

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

詳細はこちら
Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python

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

Q&A

解決済

2回答

4613閲覧

pillowで画像編集した写真からExifを消したくない、保持したままにしたい

TakayukiMoriya

総合スコア26

Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python

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

0グッド

0クリップ

投稿2019/09/06 06:47

画像処理プログラムを作成しております

以下コードをjupiter notebookで実行し、画像処理を行うプログラムを作成中です。

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 10#FACE_ICON_FILE = 'smile.png' #アイコン画像 11WM_FILE = 'logo.png' #ウォーターマーク画像 12 13class Mode(Enum): 14 BLG = auto() #ブログ用 15 16def mkdir_dto(img, output_dir_path): 17 """画像の撮影日のフォルダを作成する 18 :param img: 画像(PIL) 19 :param output_dir_path: 出力先のフォルダーのパス 20 :return: 作成したフォルダーのパス 21 """ 22 EXIF_DTO = 36867 #Exifの撮影日のタグ番号 23 24 # 移動先フォルダー作成。フォルダー名はExifの撮影日からyyyymmdd形式で生成 25 exif = img._getexif() 26 dt = datetime.strptime(exif[EXIF_DTO], '%Y:%m:%d %H:%M:%S') 27 output_sub_dir = dt.strftime('%Y%m%d') 28 output_path = os.path.join(output_dir_path, output_sub_dir) 29 os.makedirs(output_path, exist_ok=True) 30 31 return output_path 32 33def make_img(img, img_name, mode, watermark, output_path): 34 """画像をリサイズし、ウォーターマークを貼り付け、別名で保存する 35 :param img: 画像(PIL) 36 :param img_name: 画像(PIL)ファイル名 37 :param mode: Mode.BLGならブログ用、Mode.TMBならサムネイル用 38 :param watermark: ウォーターマーク画像(PIL) 39 :param output_path: 出力先フォルダーのパス 40 """ 41 BLG_CHAR = '_s' #ブログ画像のファイル名に付加する文字列 42 MAX_W_BLG = 3600 #ブログ画像の幅の上限 43 MAX_H_BLG = 3600 #ブログ画像の高さの上限  44 45 # サイズ、ファイル名の末尾に付加する文字列を設定 46 if (mode == Mode.BLG): #ブログ用 47 w, h = MAX_W_BLG, MAX_H_BLG 48 add_chr = BLG_CHAR 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, (w_img - w_wm-180, h_img- h_wm-110), watermark)#ロゴの程良い位置を右下から(x,y)=(-180,-120)として座標を決定してます 59 60 #ファイル名に文字列を付加して保存 61 fname, ext = os.path.splitext(img_name) 62 img.save(os.path.join(output_path, fname + add_chr + ext), quality=95,) 63 64 65# 顔アイコン画像とウォーターマーク画像読み込み 66 67watermark = Image.open(WM_FILE) 68 69#元画像フォルダー選択 70root = tkinter.Tk() 71root.withdraw() 72msg = '画像フォルダーを選択してください。' 73img_dir_path = tkinter.filedialog.askdirectory(title=msg) 74if (not img_dir_path): #[キャンセル]クリック時の処理 75 print('フォルダーを選んでください。') 76 sys.exit() 77 78#出力先フォルダー選択 79msg = '出力先フォルダーを選択してください。' 80output_dir_path = tkinter.filedialog.askdirectory(title=msg) 81if (not output_dir_path):#[キャンセル]クリック時の処理 82 print('フォルダーを選んでください。') 83 sys.exit() 84 85# 元画像フォルダー内のファイル1つずつ処理 86for img_file in os.listdir(img_dir_path): 87 #元画像読み込み (PIL) 88 img_path = os.path.join(img_dir_path, img_file) 89 img_pil = Image.open(img_path) 90 91 92 #ファイルの移動先フォルダー作成 93 output_path = mkdir_dto(img_pil, output_dir_path) 94 95 #ブログ用画像とサムネイル用画像を作成 96 make_img(img_pil.copy(), img_file, Mode.BLG, watermark, output_path) 97 98 #元画像(PIL)を閉じる 99 img_pil.close()

直面している問題

上記コードは問題なく動作するのですが、pillowの仕様なのか書き出された画像から一切のExifデータが削除されてしまいます。複数のカメラマンに撮ってもらった大量の写真データを時系列に並べて管理するということを実現したいため、Exifデータを消したくありません。

python

1 img.save(os.path.join(output_path, fname + add_chr + ext), quality=95,)

この行になにか付け加えればExifデータを保持したまま画像を作ることができるのでしょうか?それとも何か他の方法があるのでしょうか?

お手数おかけしますが、ご教授いただければ幸いです。

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

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

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

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

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

meg_

2019/09/06 09:32

画像の形式は何でしょうか?
guest

回答2

0

ベストアンサー

save() で保存する際に exif 引数で画像の EXIF データを指定することで、EXIF データ付きで保存できます。画像のEXIF データは img.info['exif'] で取得できます。

python

1from PIL import Image 2 3img = Image.open("sample.jpg") 4 5img.save('output.jpg', exif=img.info['exif'])

投稿2019/09/06 07:04

tiitoi

総合スコア21956

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

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

TakayukiMoriya

2019/09/06 12:48

ありがとうございます。 img.save(os.path.join(output_path, fname + add_chr + ext), quality=95, exif=img.info['exif']) としたところExif情報が継承されました。
guest

0

最終的にこちらで落ち着きました。PhotoShopのバッジ処理より高速で使いやすそうです。

python

1#0906 2import os 3import sys 4import shutil 5from datetime import datetime 6from enum import Enum, auto 7 8import tkinter, tkinter.filedialog 9from PIL import Image 10#import cv2 11 12#FACE_ICON_FILE = 'smile.png' #アイコン画像 13#WM_FILE = 'logo.png' #横写真の場合のウォーターマーク画像 14WM_FILE = 'logorotated.png' #縦写真の場合のウォーターマーク画像 15#CASCADE_FILE = 'haarcascade_frontalface_default.xml' #カスケードファイル 16 17class Mode(Enum): 18 BLG = auto() #ブログ用 19# TMB = auto()#サムネイル用 20 21#def mask_face(img_cv, cascade, img_pil, mask): 22 """顔をアイコン画像で隠す 23 :param img_cv: 元画像(OpenCV) 24 :param cascade: カスケードファイル 25 :param img_pil: 元画像(PIL) 26 :param mask: 顔を隠す用の画像(PIL) 27 """ 28 #顔認識を実行 29 # faces = cascade.detectMultiScale(img_cv, scaleFactor=1.5) 30 31 #認識された顔にアイコンを貼り付け 32# for (x, y, w, h) in faces: 33# mask = mask.resize((w, h)) 34# img_pil.paste(mask, (x, y), mask) 35 36def mkdir_dto(img, output_dir_path): 37 """画像の撮影日のフォルダを作成する 38 :param img: 画像(PIL) 39 :param output_dir_path: 出力先のフォルダーのパス 40 :return: 作成したフォルダーのパス 41 """ 42 EXIF_DTO = 36867 #Exifの撮影日のタグ番号 43 44 # 移動先フォルダー作成。フォルダー名はExifの撮影日からyyyymmdd形式で生成 45 exif = img._getexif() 46 dt = datetime.strptime(exif[EXIF_DTO], '%Y:%m:%d %H:%M:%S') 47 output_sub_dir = dt.strftime('%Y%m%d') 48 output_path = os.path.join(output_dir_path, output_sub_dir) 49 os.makedirs(output_path, exist_ok=True) 50 51 return output_path 52 53def make_img(img, img_name, mode, watermark, output_path): 54 """画像をリサイズし、ウォーターマークを貼り付け、別名で保存する 55 :param img: 画像(PIL) 56 :param img_name: 画像(PIL)ファイル名 57 :param mode: Mode.BLGならブログ用、Mode.TMBならサムネイル用 58 :param watermark: ウォーターマーク画像(PIL) 59 :param output_path: 出力先フォルダーのパス 60 """ 61 BLG_CHAR = '_s' #ブログ画像のファイル名に付加する文字列 62# TMB_CHAR = '_tmb' #サムネイル画像のファイル名に付加する文字列 63 MAX_W_BLG = 3600 #ブログ画像の幅の上限 64 MAX_H_BLG = 3600 #ブログ画像の高さの上限 ※こちらはあまり意味のない数値です 65# MAX_W_TMB = 300 #サムネイル画像の幅の上限 66# MAX_H_TMB = 300 #サムネイル画像の高さの上限 67 68 # サイズ、ファイル名の末尾に付加する文字列を設定 69 if (mode == Mode.BLG): #ブログ用 70 w, h = MAX_W_BLG, MAX_H_BLG 71 add_chr = BLG_CHAR 72# elif (mode == Mode.TMB): #サムネイル用 73# w, h = MAX_W_TMB, MAX_H_TMB 74# add_chr = TMB_CHAR 75 else: 76 return None 77 78 #リサイズ 79 img.thumbnail((w, h)) 80 81 #ウォーターマークを付加 82 w_img, h_img = img.size 83 w_wm, h_wm = watermark.size 84# img.paste(watermark, (w_img - w_wm-180, h_img- h_wm-110), watermark)#ロゴの程良い位置を右下から(x,y)=(-180,-120)として座標を決定してます 85 img.paste(watermark, (95, 1800), watermark)#ロゴの程良い位置を右下から(x,y)=(-180,-120)として座標を決定してます 86 87 #ファイル名に文字列を付加して保存 88 fname, ext = os.path.splitext(img_name) 89 img.save(os.path.join(output_path, fname + add_chr + ext), quality=95, exif=img.info['exif'])#森谷追記 90 91 92# 顔アイコン画像とウォーターマーク画像読み込み 93#face_icon = Image.open(FACE_ICON_FILE) 94watermark = Image.open(WM_FILE) 95 96# 認識器生成 97#cascade = cv2.CascadeClassifier(CASCADE_FILE) 98 99#元画像フォルダー選択 100root = tkinter.Tk() 101root.withdraw() 102msg = '画像フォルダーを選択してください。' 103img_dir_path = tkinter.filedialog.askdirectory(title=msg) 104if (not img_dir_path): #[キャンセル]クリック時の処理 105 print('フォルダーを選んでください。') 106 sys.exit() 107 108#出力先フォルダー選択 109msg = '出力先フォルダーを選択してください。' 110output_dir_path = tkinter.filedialog.askdirectory(title=msg) 111if (not output_dir_path):#[キャンセル]クリック時の処理 112 print('フォルダーを選んでください。') 113 sys.exit() 114 115# 元画像フォルダー内のファイル1つずつ処理 116for img_file in os.listdir(img_dir_path): 117 #元画像読み込み (PIL) 118 img_path = os.path.join(img_dir_path, img_file) 119 img_pil = Image.open(img_path) 120 121 #顔認識用にOpenCVで元画像をグレースケールで別途読み込み 122# img_cv = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) 123 124 #顔を隠す 125# mask_face(img_cv, cascade, img_pil, face_icon) 126 127 #ファイルの移動先フォルダー作成 128 output_path = mkdir_dto(img_pil, output_dir_path) 129 130 #ブログ用画像とサムネイル用画像を作成 131 make_img(img_pil.copy(), img_file, Mode.BLG, watermark, output_path) 132# make_img(img_pil, img_file, Mode.TMB, watermark, output_path) 133 134 #元画像(PIL)を閉じる 135 img_pil.close()

投稿2019/09/06 12:51

TakayukiMoriya

総合スコア26

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問