Python

【Python】OpenCVとStreamlitを使用して粒子の画像処理を行う

最近話題のStreamlitを使用してOpenCVで粒子画像処理を行ったので紹介します。大学や企業では材料粒子などを調べる際に顕微鏡写真などを調査することがあると思いますが、その際に粒子計測や粒径を調査する際の役に立つと思います。Streamlitを使用するとhtmlやcss, Javaなどを使用することなく簡単にWebブラウザを作ることができるので非常におすすめです。

PythonでOpenCVを使用すると簡単に画像処理ができることがわかりましたが、ソフトとして使用するにはどうやったらいいですか?

アプリやWebで使用するにはJavaやhtml, cssなどのコードが必要となるので、少し難しいのですが、最近ではstreamlitと呼ばれる非常に簡単なフレームワークができているのでおすすめです。

Streamlit?初めて聞きました。一時htmlなども使用しましたが、なかなか複雑で理解できませんでした。

Streamlitはかなり簡単にPythonで作ったプログラムをブラウザ上で起動できるのでかなりおすすめです。ではやってみましょう。

【今回の内容】
 ・Streamlitとは
 ・StreamlitでWeb アプリケーションを作成
 ・2値化処理の参考プログラム紹介

🚀 0円で現役エンジニアから学べる【Techスクールオンライン】のお申込みをお勧めします。 このオンラインスクールでは、現役のエンジニアから直接学ぶことができ、プログラミングの基礎から高度なスキルまでを習得できます。しかも、今なら 0円 で受講できるチャンスです。 エンジニア転職を考えている方やプログラミングに興味がある方、新しいスキルを習得したい方に特におすすめです。

Streamlitとは

Streamlitとはhtmlやcsvなどを使用することなくWebアプリケーションを作成することができる非常に便利なフレームワークとなります。下記のサイトに公式ホームページを参照願います。
https://streamlit.io/

Streamlitの使用方法・マニュアル紹介

使用方法は簡単です。まずpipコマンドを使用してstreamlitをインストールしましょう。

pip install streamlit

上記コマンドでインストールを行いましょう。
その後、ターミナル上でStreamlit helloと入力すると、ターミナル上に下記コメントが記載され、Local URLが表示されます。

documentationを選択します。
API referenceを選択します。
こちらのマニュアルの中に使用方法がしっかりと記載されているので、これらを使用してみましょう。今回は、st.writeとst.titleを使用してみます。下記コードを記載してください。ファイル名称は”test.py”とします。
import streamlit as st
st.title('Streamlit テスト')
st.write('Hello world')
'''
マジックコマンド
'''
コマンド記載後、ターミナル上でStreamlit run test.pyと入力し、Enterを押します。(今回のファイル)

Enterを押すと、Local URLが表示されますので、自動でURLに移動しない場合は、選択して移動します。すると下記のようなページが表示されます。このように簡単にWebページを作ることができます。今回はtitleと入力したものが見出しとなっております。

Streamlitを使用した画像処理プログラムを作ってみた

最終的には、OpenCVとStreamlitを使用して下記のようなYou Tubeのようなスライダーやボタンを配置したWebブラウザを作ることができます。コードはこちらになります。とりあえず途中までですが、これから粒径のカウントや画像にナンバリングを行う処理をしていきたいと思います。

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

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")
    )
    erosion=st.button("Erosion",key=1)
    dilation=st.button("Dilation",key=2)

st.title('Streamlit を使った画像処理')
'''
### 画像処理プログラム
'''
uploaded_image=st.file_uploader("ファイルアップロード", type='jpg')
col1, col2= st.columns(2)
image_loc = st.empty()

col1.header("Original image")
col2.header("Binary image")
with col1:
    # st.header("A cat")
    if uploaded_image is not None:
        image=Image.open(uploaded_image,)
        img_array = np.array(image)
        st.image(img_array,caption = '元画像',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)
        # image2 = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        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)   

if radio=="Threshold" and uploaded_image is not None:
    col2.image(th1)
elif radio=="Adaptive threshold mean" and uploaded_image is not None:
    col2.image(th2)
elif radio=="Adaptive threshold Gaussian" and uploaded_image is not None:
    col2.image(th3)
elif radio=="Otsu' thresholding" and uploaded_image is not None:
    col2.image(th4)
elif radio=="Otsu's thresholding + Gaussian fileter" and uploaded_image is not None:
    col2.image(th5)

if erosion:
    kernel = np.ones((5,5),np.uint8)
    erodedimage = cv2.erode(th5,kernel,iterations = 1)
    col1.image(erodedimage)

🚀 0円で現役エンジニアから学べる【Techスクールオンライン】のお申込みをお勧めします。 このオンラインスクールでは、現役のエンジニアから直接学ぶことができ、プログラミングの基礎から高度なスキルまでを習得できます。しかも、今なら 0円 で受講できるチャンス。
私がツナグバに登録してから、求人情報が豊富に届き、自分に合った仕事を見つけることができました。特に、第二新卒向けの求人情報が多いので、自分のスキルや経験を活かしながら新たなキャリアに挑戦することができました。転職活動は不安も多いですが、ツナグバのサポートがあれば、成功への道が明るく感じました。