pysimpleGUIで2画面ビューワーをつくって画像処理

python

pysimpleGUIで画像ビューワーの第2弾webカメラの画像を表示して、リアルタイム処理を行う

いままでの記事ではHello medical-python, 画像ビューワーアプリを作成しました。
今回は2つの事を行います
1.pysimpleGUIでWebカメラの画像をリアルタイム表示する
2.2画面ビューワーを作成して2画面目では画像のリアルタイム処理を行う

同じくchatGTPにだいたいの事をやってもらいましょう
chatGPTで迷走したのでBingAIに変更しました

Webカメラのリアルタイム処理(Canny変換)

openCVを使って画像データを表示してきます、GUI処理はpysimpleGUIで行います。

画像はCanny変換して表示します、なぜCanny変換?かっこいいからです。
Canny変換についてBingAIに説明してもらいました。(人任せ、、、)

Canny変換は、画像からエッジを検出するためのアルゴリズムです。エッジとは、画像中の輝度が急激に変化する領域のことを指します。Canny変換は、次のステップで構成されます。

  1. ノイズ除去: 画像にガウシアンフィルターを適用して、ノイズを除去します。
  2. 勾配計算: 画像の勾配(輝度の変化量)を計算します。これにより、エッジの方向と強さが求められます。
  3. 非最大値抑制: 勾配画像中の非最大値を抑制して、細いエッジを得ます。
  4. ヒステリシスしきい値処理: 2つのしきい値(上限値と下限値)を設定し、勾配強度が上限値より大きいピクセルはエッジとして確定し、下限値より小さいピクセルは非エッジとして除外し、上限値と下限値の間にあるピクセルは、周囲に確定したエッジがある場合にのみエッジとして扱われます。

Canny変換により、画像から輪郭線が抽出されます。このアルゴリズムは、画像処理において広く使用されています。

BingAI

以下指示を与えます
pysimpleGUIを使ってwebカメラの画像をリアルタイム取得し、さらにその画像をcanny処理して表示するコードを教えてください。ただし、canny変換の閾値はスライダーバーで調整できるようにしてください

ちなみにwebカメラのカメラ番号はcap = cv2.VideoCapture(0) の0にしています。複数のカメラがある場合はこの番号を変更します。

import cv2
import PySimpleGUI as sg

# define the window layout
layout = [
    [sg.Text("Canny Edge Detection")],
    [sg.Image(key="-CANNY-")],
    [sg.Text("Threshold 1"), sg.Slider(range=(0, 255), orientation="h", size=(40, 15), default_value=100, key="-THRESHOLD1-")],
    [sg.Text("Threshold 2"), sg.Slider(range=(0, 255), orientation="h", size=(40, 15), default_value=200, key="-THRESHOLD2-")],
]

# create the window and show it without the plot
window = sg.Window("Canny Edge Detection", layout)

# ---===--- Event LOOP Read and display frames, operate the GUI --- #
cap = cv2.VideoCapture(0)
while True:
    event, values = window.read(timeout=20)
    if event == "Exit" or event == sg.WIN_CLOSED:
        break

    ret, frame = cap.read()

    # apply Canny edge detection
    edges = cv2.Canny(frame, values["-THRESHOLD1-"], values["-THRESHOLD2-"])
    imgbytes = cv2.imencode(".png", edges)[1].tobytes()
    window["-CANNY-"].update(data=imgbytes)

window.close()

上記のコードを実行するとこんな感じで動きます。

Webカメラの画像とCanny処理した画像の2画面ビューワーを作る!

上記のコードに追加してwebカメラの生画像を追加します。細かいとこはBingAIに任せます。

pysimpleGUIを使ってwebカメラの画像をリアルタイム表示し、さらにその画像をcanny処理して隣に表示するコードを教えてください。ただし、canny変換の閾値はスライダーバーで調整できるようにしてください。2つの画面は横に並べて表示して下さい。

BingAIの回答は英語が多いです、、
Here is the modified code that displays the webcam feed and its Canny edge detection side by side: 横に並べてってside-by-sideでいいのね

import cv2
import PySimpleGUI as sg

# define the window layout
layout = [
    [sg.Text("Canny Edge Detection")],
    [sg.Image(key="-IMAGE-"), sg.Image(key="-CANNY-")],
    [sg.Text("Threshold 1"), sg.Slider(range=(0, 255), orientation="h", size=(40, 15), default_value=100, key="-THRESHOLD1-")],
    [sg.Text("Threshold 2"), sg.Slider(range=(0, 255), orientation="h", size=(40, 15), default_value=200, key="-THRESHOLD2-")],
]

# create the window and show it without the plot
window = sg.Window("Canny Edge Detection", layout)

# ---===--- Event LOOP Read and display frames, operate the GUI --- #
cap = cv2.VideoCapture(0)
while True:
    event, values = window.read(timeout=20)
    if event == "Exit" or event == sg.WIN_CLOSED:
        break

    ret, frame = cap.read()
    imgbytes = cv2.imencode(".png", frame)[1].tobytes()
    window["-IMAGE-"].update(data=imgbytes)

    # apply Canny edge detection
    edges = cv2.Canny(frame, values["-THRESHOLD1-"], values["-THRESHOLD2-"])
    imgbytes = cv2.imencode(".png", edges)[1].tobytes()
    window["-CANNY-"].update(data=imgbytes)

window.close()

これで2画面ビューワーができました。

2画面ビューワーに録画機能を付けて動画を保存する

では最後に、このアプリに録画と動画保存機能をつけます。さらに元動画とcanny変換動画を別々に保存しておきます。何故か? 今後の展開を待っててください。

BingAIにいろいろ頼みます。(何回かチャットしたのを端折っています)
上記のコードにstart_recとstop_recのボsave_movieのボタンを追加して、start_recで画面の録画を開始、stop_recで録画を終了、save_movieで録画した動画をmp4で保存するコードをおしえてください。
ただし、mp4のファイル名は現在の時刻としてください。
canny処理した画像も別のmp4に保存するコードを追加してください。

英語でたくさん解説してくれたのですが、日本語に訳してもらいました。

このコードでは、録画の開始と停止、および動画の保存を行うための3つの新しいボタン要素がレイアウトに追加されています。Start Recordingボタンがクリックされると、各フレームがリストに追加され、Webカメラのフィードが記録されます。Stop Recordingボタンがクリックされると、録画が停止します。Save Movieボタンがクリックされると、記録されたフレームがOpenCVのcv2.VideoWriterを使用してMP4ファイルとして保存されます。保存された動画のファイル名は、現在の日付と時刻をYYYY-MM-DD_HH-MM-SS.mp4の形式で設定されます。

このコードは、必要なライブラリ(PySimpleGUIおよびopencv-python)をpip install PySimpleGUI opencv-pythonを使用してインストールした後、コンピューターで実行できます。コードを実行する前に、コンピューターにWebカメラが接続されていることを確認してください。

import cv2
import PySimpleGUI as sg
from datetime import datetime

# define the window layout
layout = [
    [sg.Text("Canny Edge Detection")],
    [sg.Image(key="-IMAGE-"), sg.Image(key="-CANNY-")],
    [sg.Text("Threshold 1"), sg.Slider(range=(0, 255), orientation="h", size=(40, 15), default_value=100, key="-THRESHOLD1-")],
    [sg.Text("Threshold 2"), sg.Slider(range=(0, 255), orientation="h", size=(40, 15), default_value=200, key="-THRESHOLD2-")],
    [sg.Button("Start Recording", key="-START-"), sg.Button("Stop Recording", key="-STOP-", disabled=True), sg.Button("Save Movie", key="-SAVE-", disabled=True)],
]

# create the window and show it without the plot
window = sg.Window("Canny Edge Detection", layout)

# ---===--- Event LOOP Read and display frames, operate the GUI --- #
cap = cv2.VideoCapture(0)
recording = False
frames = []
canny_frames = []
while True:
    event, values = window.read(timeout=20)
    if event == "Exit" or event == sg.WIN_CLOSED:
        break

    ret, frame = cap.read()
    imgbytes = cv2.imencode(".png", frame)[1].tobytes()
    window["-IMAGE-"].update(data=imgbytes)

    # apply Canny edge detection
    edges = cv2.Canny(frame, values["-THRESHOLD1-"], values["-THRESHOLD2-"])
    imgbytes = cv2.imencode(".png", edges)[1].tobytes()
    window["-CANNY-"].update(data=imgbytes)

    # handle recording
    if recording:
        frames.append(frame)
        canny_frames.append(edges)
    if event == "-START-":
        recording = True
        window["-START-"].update(disabled=True)
        window["-STOP-"].update(disabled=False)
    elif event == "-STOP-":
        recording = False
        window["-START-"].update(disabled=False)
        window["-STOP-"].update(disabled=True)
        window["-SAVE-"].update(disabled=False)
    elif event == "-SAVE-" and frames:
        # save frames as MP4 file
        height, width, _ = frames[0].shape
        fourcc = cv2.VideoWriter_fourcc(*"mp4v")
        filename = datetime.now().strftime("%Y-%m-%d_%H-%M-%S.mp4")
        out = cv2.VideoWriter(filename, fourcc, 20.0, (width, height))
        for frame in frames:
            out.write(frame)
        out.release()
        frames.clear()

        # save canny frames as MP4 file
        height, width = canny_frames[0].shape
        fourcc = cv2.VideoWriter_fourcc(*"mp4v")
        filename = datetime.now().strftime("%Y-%m-%d_%H-%M-%S_canny.mp4")
        out = cv2.VideoWriter(filename, fourcc, 20.0, (width,height))
        for frame in canny_frames:
            out.write(cv2.cvtColor(frame,cv2.COLOR_GRAY2BGR))
        out.release()
        canny_frames.clear()

        window["-SAVE-"].update(disabled=True)

window.close()

実行すると現在の作業フォルダにwebカメラの動画と、canny処理後の動画が保存されます。

pysimpleGUIとopenCVを使って、webカメラから動画とcanny変換した動画を保存しました。本日はここまで!

PythonによるOpenCV4画像処理プログラミング+Webアプリ入門 [ 北山直洋 ]
価格:4,400円(税込、送料無料) (2023/5/12時点)楽天で購入

コメント

Copied title and URL