7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Streamlitで画像を読み込んで表示させたい

Last updated at Posted at 2023-11-20

はじめに

今回は、Pythonの代表的な画像処理ライブラリであるPillowとOpenCVを用いて、Streamlitで画像を読み込んで表示する方法についてまとめたいと思います。
普段Pillowを用いて読み込んでいましたが、OpenCVを用いて表示させようとしたところうまくいかなかったため、それの対処法を併せてまとめます。

Pillowで読み込む場合

まずはPillowで読み込んだ場合について紹介します。

import streamlit as st
from PIL import Image

file_path = st.file_uploader('', type=['png', 'jpg', 'jpeg'])
img = Image.open(file_path)
st.image(img)

簡単ですね。
必要最低限しか書いておりません。

OpenCVで読み込む場合

一方、OpenCVで画像ファイルを読み込もうとした場合、OpenCVを使用している人からすると

import streamlit as st
import cv2

file_path = st.file_uploader('', type=['png', 'jpg', 'jpeg'])
img = cv2.imread(file_path)
st.image(img)

となると思うじゃないですか?????
これを実行したとき、

TypeError: Can't convert object to 'str' for 'filename'

というエラーが生じます。

なんでやねん!!!
ファイル読み込んで、そのファイルをそのまま渡してるやんけ!
Pillowではうまくいったのに、なんでOpenCVだとできないんや!
とブチ切れているときに、暇~?って声かけてきた上司は未来永劫孫子の代まで恨みます。

このエラーについて調べてみると、
st.file_uploaderから返されるオブジェクトは、ファイルのバイナリデータを含むものであり、直接 cv2.imreadに渡すことはできず、cv2.imreadはファイルパス (str) を受け取る関数であり、バイナリデータを直接渡すことはできない。とのこと。
よくわからんけど、strで渡せばええんやろと。

そして、以下が読み込むための対策

import streamlit as st
import cv2
import tempfile

file_path = st.file_uploader('', type=['png', 'jpeg', 'jpg'])

if img_file:
    temp_file = tempfile.NamedTemporaryFile(delete=False)
    temp_file.write(file_path.read())

    img = cv2.imread(temp_file.name)

    temp_file.close()

    st.image(img)

このように、一時ファイルに一旦読み込んだファイルを保存し、その保存名をtemp_file.nameで引っ張ってきてます。
リソースの無駄遣いになるので、一時ファイルは不要になったら消しときましょうね(temp_file.close())。
これでOpenCVで画像を読み込み、表示することができました。

追記

imdecodeを用いることで直接データを渡すことができるようです。

import streamlit as st
import cv2
import numpy as np

file_path = st.file_uploader('', type=['png', 'jpg', 'jpeg'])
# img = cv2.imdecode(file_path)
# st.image(img)

if file_path :
    # ファイルをバイト列として読み込む
    image_bytes = file_path.read()
    
    # バイト列から画像をデコードする
    img = cv2.imdecode(np.frombuffer(image_bytes, np.uint8), cv2.IMREAD_COLOR)

    # 画像を表示する
    # BGR チャンネルで表示(一般的な画像フォーマットはRGBであるため)
    st.image(img, channels="BGR")  

一時ファイルに保存する方法と画像をデコードして読み込む方法、どちらのコードが良いコードなのかはさっぱりです(;'∀')

まとめ

今回はStreamlitアプリで画像を読み込み、表示させる方法を紹介しました。
基本的なことですが、StreamlitとOpenCVの仕様であったり、同じように困っている人のお役に立てば幸いです。
今後画像解析のライブラリはメインで勉強しようと思っておりますので、また備忘録として残していこうと思います。
それでは!!!

7
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?