検索:
Pyserialを使ってシリアル通信

Pythonでシリアル通信を実装する場合、Pyserialが便利でしたので、簡単に紹介します。


最初にPyserialをインストールします。

pip install pyserial

COMポートをデバイスマネージャーで確認して、シリアル通信のインスタンスを定義します。

serial.Serialの1つ目の引数がポート番号、2つ目がボーレート、3つ目がタイムアウトの設定です。

import serial

ser = serial.Serial('COM9', 307200, timeout=1)

.writeコマンドを使ってメッセージを送信します。

#任意のメッセージを記述
senddata = [0x55, 0x0D, 0x0A] 

#送信
send_binary = bytes(senddata)
ser.write(send_binary)

受信は.readコマンドを用います。

#受信
res = ser.read(4)
print(res)

readのカッコ内の数で受信するByte数を設定できます。

.readline () というコマンドを使えば、改行コードまでを受信してくれますが、今回試した機器は改行コードを返さない仕様だったため readline ではうまくいきませんでした。

硬貨認識AI ② ~YOLOを使って硬貨を認識する~

前回はCVATを使ったアノテーションを紹介しました。
今回は実際にYOLOを使って硬貨の認識までを実施してみます。

ここではGoogle Colaboratory のGPUを使って学習してみたいと思います。
まずはGoogle Colaboratoryのサイトに行き、右上の「Open Colab」をクリックし、その後 Googleアカウントでログインします。

① ノートブックの新規作成、Runtimeの変更

「ファイル」から「ノートブックを新規作成」をクリックします。

GPUを用いて学習を行いたいため、「ランタイム」から「ランタイムタイプを変更」をクリックし、 T4 GPUを選択します。

② 必要なライブラリのインストール

pip install コマンドを使って必要なライブラリをインストールします。

!pip install ultralytics

③ Googleドライブにアクセスするため、マウント処理を実行。

from google.colab import drive
drive.mount('/content/drive')

④ 学習データ、テストデータをフォルダに格納。

「train」「val」フォルダを用意して画像ファイルとアノテーションファイルを同ファイル名(ここでは.jpgファイルと.txtファイル)にして格納します。

アノテーションデータのCOCO 1.0 -> YOLO形式への変換は、こちらを参考にいたしました。

⑤ 学習の実行

下記のコマンドで学習を実行することができます。
学習回数(epochs=)やバッチサイズ(batch=)なども引数として変更可能です。

!yolo task=segment mode=train model=yolov8n-seg.pt data=/content/drive/MyDrive/COIN/YOLO/coin_config.yaml epochs=400 imgsz=640 batch=2 project=/content/drive/MyDrive/COIN/YOLO/output name=coin_detection

ここで指定している「coin_config.yami」内では、下記のようにフォルダパスとラベルの種類を指定しています。

train: /content/drive/MyDrive/ISSEI/COIN/train # train images (relative to 'path') 128 images
val: /content/drive/MyDrive/ISSEI/COIN/val # val images (relative to 'path') 128 images
# test:  # test images (optional)

# Classes
nc: 5  # number of classes
names: ['1yen','5yen','10yen','50yen','100yen']

⑥ 学習結果の確認。

学習した結果が⑤で指定したフォルダ(/content/drive/MyDrive/COIN/YOLO/output)に格納されるので確認してみます。

results.png を確認すると下記のように学習回数(epochs)とロス関数の推移やRecall(再現性), Precision(適合率) などの関係を確認することができます。

また、「train_batch*.jpg」で、実際のYOLOでの認識結果を確認することができます。

ちゃんとコインを種類ごとに識別できていることが確認できました!

硬貨認識AI ① ~CVATのAI Toolsを使ってアノテーションをしてみたらすごく楽だった~

AIで物体認識を行うためには

① 画像

② アノテーション「=注釈」データ(どこに何が写っているかの情報)

が必要になります。

アノテーションデータを生成するための便利なツールがいくつも開発されています。

ここでは Intel 社が開発した CVAT(Computer VIsion Annotation Tool)を使って、硬貨を認識するためのアノテーションデータを生成してみます。


CVATのサイトへ行き、「Try for free」をクリックします。

ユーザー登録を行い、右上の「+」マークから “Create a nes task” を選択します。
下記の “Create a nes task” が開くので、タスク名とラベル名(分類したい種別)を入力します。ラベル名はEnterまたは ”Continue” ボタンで、次のラベル名を入力できます。

画像をウインドウにドラッグ&ドロップして”Submit & Open” をクリックすると、作業用のページが開きます。

左側のメニューから “AI Tools” を選択します。”Convert masks to polugons” にチェックを入れます。

次に “AI Tools” を使って硬貨を選択していきます。硬貨の上で左クリックすると、下図のように多角形で自動的に硬貨の領域を囲んでくれます。(最初の1回だけ少し時間がかかります)

ここで硬貨の種類を示すラベルを選択しても良いのですが、個人的には、硬貨の領域を教える作業だけを先にやってしまい、ラベリングはあとでまとめてやった方が効率が良いと思います。

キーボードの ”N” を押すと領域が確定でき、もう一度”N” を押すと “AI Tools” が再起動されるので、

「左クリック」⇒ 「N」⇒ 「N」

を連続でやっていけば、領域を教える作業は次々と進めることができます。また一度クリックしただけでは、所望の領域が選択されないことがありますが、同じ硬貨の上の別の場所を再度クリックすることで領域が修正されます。

全ての画像の領域チェックが終わったら、ラベリングをしていきます。右のリストでドロップボックスから選択しても良いですし、画像の上で右クリックでも選択可能です。

すべてのラベリングが完了したら、左上の ”MENU”から”Export job dataset”を選択。
「COCO 1.0」形式でエクスポートします。

以上で、アノテーションデータ「.jsonファイル」が完成しました。

AnacondaでPythonの仮想環境を構築する

Pythonでの開発において、Pythonのバージョン、インストールされているライブラリの種類・ライブラリのバージョンの状態をまとめて「環境」と呼びます。Pythonを実行するには環境の構築が必要です。

仮想環境とは

Pythonに限った話ではありませんが、プログラムを作成する際、「このライブラリのこのバージョンはPythonのこのバージョンにしか対応していない」のようなことがよくあります。
また、ライブラリをアップデートすることで以前作ったプログラムが動かなくなってしまったら困ります。

そこで「仮想環境」と言われる所望のパッケージの所望のバージョンをインストールした環境を用意し、環境を切り替えることで、簡単に実行できる環境を構築することができます。

ここではAnacondaを使用した仮想環境の構築につて紹介します。

仮想環境の生成

実際に仮想環境を作成してみます。
Windows PowerShell や Anaconda Powershell Prompt で下記のコマンドを実行してください。

PowerShell
conda create -n vir_env1 python=3.11.4

ここでは「vir_env1」という名前の仮想環境を構築しています。

仮想環境が正しく作成されたか、下記コマンドで確認します。

PowerShell
conda info -e

コマンドを打つと、下記のような結果が出力されます。

PowerShell
 base               *  C:\ProgramData\anaconda3 
 vir_env1              C:\Users\Users\.conda\envs\vir_env1

base 環境の他に、「vir_env1」が生成されていることが確認できます。

仮想環境の切り替え

仮想環境は activate/deactivate して切り替えます。
仮想環境「vir_env1」をactivateする方法は下記になります

PowerShell
conda activate vir_env1

コマンドを実行すると、「vir_env1」の仮想環境がアクティベートされます。

念のため「conda info -e」を実行すると、下記のように仮想環境が切り替えられたことを確認できます。

PowerShell
 base                  C:\ProgramData\anaconda3 
 vir_env1           *  C:\Users\Users\.conda\envs\vir_env1

「*」印が、有効になっている仮想環境を示しています。
Anaconda Powershell Prompt を使っている場合、コマンドラインの左端の表記が(base)から(vir_env1)に変わっているかで、環境の切り替えを確認することもできます。

OpenCVとPythonで硬貨を検出してみた

OpenCVをPythonで走らせてコインの認識を行ってみました。

まずはカメラの映像をライブでウィンドウにキャプチャします。

Python
import cv2

# カメラを開く
cap = cv2.VideoCapture(1)

while True:

    # 画像をキャプチャする
    ret, frame = cap.read() #カメラ動画
    
    # 画像の表示
    cv2.imshow("Image", frame)
    
    # `q`キーを押すとループを終了する
    if cv2.waitKey(1) == ord('q'):
        break

# カメラを閉じる
cap.release()

# すべてのウィンドウを閉じる
cv2.destroyAllWindows()

実行結果がこちら↓↓

接続するカメラが違う場合は、4行目の関数の閾値の数字を変えてみてください。これでUSBカメラの映像をライブで取り込めるようになりました。

次に Hough 関数を使って円を検出してみます。

Python
import cv2
import numpy as np

# カメラを開く
cap = cv2.VideoCapture(1)

#フォントの指定
fontType = cv2.FONT_HERSHEY_DUPLEX

while True:

    # 画像をキャプチャする
    ret, frame = cap.read() #カメラ動画

    # グレースケール画像の生成
    image_gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

    #==============================================
    # Cannyでエッジ検出処理
    canny_gray = cv2.Canny(image_gray,100,200)
    cimg = canny_gray

    j = 0
    
    # hough関数
    circles = cv2.HoughCircles(cimg, cv2.HOUGH_GRADIENT, 1, 20, param1 = 120, param2 = 15, minRadius = 10,maxRadius = 30)
        # param1 : canny()エッジ検出器に渡される2つの閾値のうち、大きいほうの閾値0
        # param2 : 円の中心を検出する際の投票数の閾値。小さくなるほど、誤検出が起こる可能性がある。
        # minRadius : 検出する円の最小値
        # maxRadius : 検出する円の最大値

    #検出された際に動くようにする。
    if circles is not None and len(circles) > 0:

        #型をfloat32からunit16に変更。
        circles = np.uint16(np.around(circles))
        
        for i in circles[0,:]:
            # 外側の円を描く
            cv2.circle(frame,(i[0], i[1]), i[2], (0, 191, 255), 2)
            # 中心の円を描く
            cv2.circle(frame,(i[0], i[1]), 2, (255, 255, 0), 2)
            # 円の数を数える
            j = j + 1

    #円の合計数を表示
    cv2.putText(frame,'Total :'+str(j), (30,30), fontType, 1, (0, 0, 0), 1, cv2.LINE_AA)

    #==============================================

    # 画像の表示
    cv2.imshow("Image", frame)
 
  # `s`キーを押すと画像を保存する
   if cv2.waitKey(1) == ord('s'):
        #結果の書き込み
        cv2.imwrite('image1.jpg',frame)   
  
    # `q`キーを押すとループを終了する
    if cv2.waitKey(1) == ord('q'):
        break

# カメラを閉じる
cap.release()

# すべてのウィンドウを閉じる
cv2.destroyAllWindows()

実行結果がこちら↓↓

これで円形状のものを検出し、数をカウントできるようになりました。