手軽にwebアプリケーションが作成できるStreamlitを使用して、OpenCVで画像の2値化処理をするアプリケーションを作成しました。今回は、ローカル環境のDocker上で稼働させるところまでを確認しています。以下にコードと実行結果を紹介します。
ディレクトリ構成
.
├── Dockerfile
├── requirements.txt
└── test.py
アプリ作成
イメージのもとになるDockerfileは以下の通りです。
FROM python:3.9
USER root
EXPOSE 8501
WORKDIR /app
COPY ./requirements.txt requirements.txt
COPY ./test.py test.py
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
CMD streamlit run test.py
Pythonでインストールするライブラリは以下のrequirements.txtにまとめました。
numpy==1.22.3
Pillow==9.1.0
streamlit==1.10.0
opencv-python-headless==4.6.0.66
この際、opencv-pythonをpipで入れるとtest.pyを実行した際に以下のエラーが出るため、opencv-python-headlessを入れています。(参考:https://itsmycode.com/importerror-libgl-so-1-cannot-open-shared-object-file-no-such-file-or-directory/)
ImportError: libGL.so.1: cannot open shared object file: No such file or directory
webアプリケーションのtest.pyは以前と同じです。
import os
import streamlit as st
import numpy as np
from PIL import Image
import cv2
def pil2cv(image):
''' PIL型 -> OpenCV型 '''
new_image = np.array(image, dtype=np.uint8)
if new_image.ndim == 2: # モノクロ
pass
elif new_image.shape[2] == 3: # カラー
new_image = cv2.cvtColor(new_image, cv2.COLOR_RGB2BGR)
elif new_image.shape[2] == 4: # 透過
new_image = cv2.cvtColor(new_image, cv2.COLOR_RGBA2BGRA)
return new_image
def main():
os.makedirs('./data', exist_ok=True)
st.set_page_config(page_icon="📷", page_title="画像2値化アプリ")
with st.sidebar:
th = st.slider('Threshold value', 0, 255, 125)
st.write("Threshold value", th)
with st.sidebar:
radio = st.radio(
"Choose a binary method",
("Threshold", "Adaptive threshold mean","Adaptive threshold Gaussian",
"Otsu' thresholding", "Otsu's thresholding + Gaussian fileter")
)
st.title('画像2値化アプリ')
# アップローダー
uploaded_image=st.file_uploader("以下からファイルアップロード", type=['jpg','png'])
# カラム設定
col1, col2 = st.columns(2)
col1.header("Original image")
col2.header("Binary image")
# original画像表示、2値化処理
with col1:
if uploaded_image is not None:
image=Image.open(uploaded_image,)
img_array = np.array(image)
st.image(img_array,use_column_width = None)
img=pil2cv(image)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,th1 = cv2.threshold(gray,th,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY,11,2)
ret2,th4 = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
blur = cv2.GaussianBlur(gray,(5,5),0)
ret3,th5 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# binary画像表示、保存
if radio=="Threshold" and uploaded_image is not None:
col2.image(th1)
cv2.imwrite('./data/image.png', th1)
elif radio=="Adaptive threshold mean" and uploaded_image is not None:
col2.image(th2)
cv2.imwrite('./data/image.png', th2)
elif radio=="Adaptive threshold Gaussian" and uploaded_image is not None:
col2.image(th3)
cv2.imwrite('./data/image.png', th3)
elif radio=="Otsu' thresholding" and uploaded_image is not None:
col2.image(th4)
cv2.imwrite('./data/image.png', th4)
elif radio=="Otsu's thresholding + Gaussian fileter" and uploaded_image is not None:
col2.image(th5)
cv2.imwrite('./data/image.png', th5)
# ダウンロードボタン作成
if uploaded_image is not None:
col2.download_button('Download',
open('./data/image.png', 'br'),
file_name='image.png')
if __name__ == '__main__':
main()
実行結果
以下のコマンドを実行します。docker runする際に、オプションでホスト側ポート8501番とコンテナ側ポート8501番をつなぐように指定して、コンテナを起動します。
# dockerfileからimageをビルド
docker build -t streamlit .
# コンテナの起動 -d:バックグラウンドで実行
docker run --name stream01 -itd -p 8501:8501 streamlit
その他の基本的なコマンドは以下の通り
# imageの一覧を表示
docker image ls
# 稼働中のコンテナ一覧
docker ps
# コンテナ内のbashシェルを起動
docker exec -it stream01 bash
# コンテナ内のbashシェルを終了
exit
# コンテナの停止
docker stop stream01
# コンテナの削除
docker rm stream01
コンテナ起動後、ブラウザからhttp://localhost:8501にアクセスするとアプリに接続できます。
実際のアプリ画面
Browse filesからの画像をアップロードも実行できた。
まとめ
以上、Streamlitを使用したアプリケーションをDocker上で稼働させ、アクセスできることを確認しました。次回は、Docker Composeを使用してみようと思います。最終的にはサーバー上での実行を目指していきます。
コメント