Python3エラー「AttributeError: read」を解消し、顔検出アプリを完成させたい
解決したいこと
【概要】
Python3エラー「AttributeError: read」を解消し、顔検出アプリを完成させたい
【詳細】
下記の動画及びドキュメントを参考に、streamlitとAzure Face APIをつかって顔検出アプリを作成しています。
【有料級】今話題のPythonライブラリStreamlitを用いて、顔検出アプリの作成から公開までの流れをわかりやすく解説
https://www.youtube.com/watch?v=zpBjbK6jic0&t=4217s
Azure FaceAPIクイックスタート
https://docs.microsoft.com/ja-jp/azure/cognitive-services/face/quickstarts/client-libraries?tabs=visual-studio&pivots=programming-language-python
発生している問題・エラー
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/streamlit/script_runner.py", line 379, in _run_script
exec(code, module.__dict__)
File "/Users/user/Desktop/python_lesson/顔検出アプリ/main.py", line 98, in <module>
detected_faces = face_client.face.detect_with_stream(
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/azure/cognitiveservices/vision/face/operations/_face_operations.py", line 779, in detect_with_stream
response = self._client.send(request, stream=False, **operation_config)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/service_client.py", line 336, in send
pipeline_response = self.config.pipeline.run(request, **kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/pipeline/__init__.py", line 197, in run
return first_node.send(pipeline_request, **kwargs) # type: ignore
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/pipeline/__init__.py", line 150, in send
response = self.next.send(request, **kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/pipeline/requests.py", line 72, in send
return self.next.send(request, **kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/pipeline/requests.py", line 137, in send
return self.next.send(request, **kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/pipeline/__init__.py", line 150, in send
response = self.next.send(request, **kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/pipeline/requests.py", line 193, in send
self.driver.send(request.http_request, **kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/universal_http/requests.py", line 333, in send
return super(RequestsHTTPSender, self).send(request, **requests_kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/universal_http/requests.py", line 139, in send
response = session.request(
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/requests/sessions.py", line 542, in request
resp = self.send(prep, **send_kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/requests/sessions.py", line 655, in send
r = adapter.send(request, **kwargs)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/requests/adapters.py", line 469, in send
for i in request.body:
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/msrest/service_client.py", line 137, in stream_upload
chunk = data.read(self.config.connection.data_block_size)
File "/Users/user/opt/anaconda3/lib/python3.9/site-packages/PIL/Image.py", line 546, in __getattr__
raise AttributeError(name)
AttributeError: read
該当するソースコード
from sqlalchemy import column
import streamlit as st
import pandas as pd
import numpy as np
import asyncio
import io
import glob
import os
from urllib.parse import urlparse
from io import BytesIO
st.title('顔認識アプリ')
KEY = "自分のKeyを入力"
ENDPOINT = "自分のENDPOINTを入力"
face_client = FaceClient(ENDPOINT, CognitiveServicesCredentials(KEY))
upload_file = st.file_uploader("Choose an image...", type = 'JPG')
#変数に値が入っていたら
if upload_file is not None:
#アップロードした画像を開く
image_data = Image.open(upload_file)
with io.BytesIO() as output:
image_data.save(output, format="JPEG")
binary_img = output.getvalue() #バイナリーデータ取得
# 認識された顔周辺に四角を描く関数
def getRectangle(faceDictionary):
rect = faceDictionary.face_rectangle
left = rect.left
top = rect.top
right = left + rect.width
bottom = top + rect.height
return ((left, top), (right, bottom))
# 認識された顔の上に年齢を描く関数
def getAge(faceDictionary):
rect = faceDictionary.face_rectangle
left = rect.left
top = rect.top - 20
return (left, top)
# イメージオブジェクト生成
drawing = ImageDraw.Draw(image_data)
detected_faces = face_client.face.detect_with_stream(
image_data,
return_face_landmarks=True,
return_face_attributes=['accessories','age','emotion','gender','glasses','hair','makeup','smile']
)
# 関数を呼び出して、顔に四角を描く
for face in detected_faces:
drawing.rectangle(getRectangle(face), outline='Blue', width = 3)
drawing.text(getAge(face), str(face.face_attributes.age), align = 'Left',
fill = 'Red')
#画像の表示
image_data.show()
追記情報
・1記事目で作っているアプリを作りたいのですが、動画作成から1年経過しており、情報が古かったため、MircroAzureの公式ドキュメントを参考に改変しています。
・初期画面(アップロード画面の表示)の表示と、アップロード画像の選択まではできています。
・Python3.9を使っています。
・アプリ部分(streamlit)とロジック部分(FaceAPI)を結合する時に、25行目以降のwith部分を追加していた時に下記エラーが発生しました。
→streamlitの実装部分は正常に動いているので、FaceAPIの実装でうまく行っていません。
・エラーがPILのImage.pyで生じているため、Image.open(upload_file)で開けない(read)できないということなのかと思いますが、どのように変更したらよいか皆目検討も付きませんでした。
試したこと
・image_data.show()のコメントアウト
→同じエラーが発生
・ with io.BytesIO()~の削除
・FACEAPIのロジック部分削除
・detected_faces = face_client.face.detect_with_stream(image_data,のimage_dataをbinary_imgに変更
→別のエラーが発生。(byte型はreadを持っていない)
以上、よろしくお願いいたします。