質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Jupyter

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

Anaconda

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

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

Q&A

解決済

1回答

2614閲覧

Pythonの"'NoneType' object is not subscriptable"エラーが解消できません

TakayukiMoriya

総合スコア26

Jupyter

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

Anaconda

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

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

0グッド

0クリップ

投稿2019/09/04 08:50

何をしたいか

「いろいろ作りながら学ぶPython入門」という書籍を参考にPythonによる画像処理の自動化やOpenCVの活用方法を学習中です。

Jupyter Notebookにて打ち込んだコードを実行すると、編集する画像が入ったフォルダを選択するよう要求され、これに従って画像が格納されたフォルダと出力先のフォルダを指定すると

・画像のリサイズ
・顔認識した部分をスマイルマークで隠す
・右下にウォーターマーク画像を入れる
・EIXF情報から取得した日付名のフォルダを編集後の写真が格納される

という処理を行うものです。

開発環境

Jupyter notebook
Python 3.7.3
MacBook Proを使用しています

コード

書籍を参考に打ち込んだコードが以下になります。

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

発生しているエラー

上記コードを実行し、用意した画像のフォルダを指定しましたが、出力先フォルダを指定するタイミングで以下エラーメッセージが表示され処理が止まってしまいます。

--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-1-70972c780404> in <module> 123 124 #ファイルの移動先フォルダー作成 --> 125 output_path = mkdir_dto(img_pil, output_dir_path) 126 127 #ブログ用画像とサムネイル用画像を作成 <ipython-input-1-70972c780404> in mkdir_dto(img, output_dir_path) 43 # 移動先フォルダー作成。フォルダー名はExifの撮影日からyyyymmdd形式で生成 44 exif = img._getexif() ---> 45 dt = datetime.strptime(exif[EXIF_DTO], '%Y:%m:%d %H:%M:%S') 46 output_sub_dir = dt.strftime('%Y%m%d') 47 output_path = os.path.join(output_dir_path, output_sub_dir) TypeError: 'NoneType' object is not subscriptable

打ち込んだコードを何度も読み返しましたが、誤っている箇所もないようで、NoneType' object is not subscriptableエラーの対処法がわからなくなってしまっている状況です。

小生の力不足で恐縮ですが、アドバイスなど頂戴できれば幸いです。

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

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

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

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

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

can110

2019/09/04 08:55

「exif = img._getexif()」の後に「print(exif)」して出力された結果を確認ください。 そのうえで補足すべき情報などあれば追記ください。
tiitoi

2019/09/04 09:18

exif 情報は画像ファイルに必ずあるものではないため、exif があるかどうかで条件分岐が必要ではないでしょうか。
TakayukiMoriya

2019/09/04 09:54

皆様のご指摘通りでした。exif情報が入っている画像のみ処理ができました。 解決済みとさせていただきます。
guest

回答1

0

ベストアンサー

PNGはエラーになるかと思います。
JpegかTiffでやってみてください。

投稿2019/09/04 09:53

meg_

総合スコア10580

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

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

TakayukiMoriya

2019/09/04 10:02

画像そのもののEixfに問題があったようです。無事画像処理が自動で行われていることが確認できました。meg_様ご指摘の画像形式にも注意して今後の学習を進めたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問