在庫管理のための検出画像ディレクトリと推論モデルのディレクトリ設定

在庫管理のための検出画像ディレクトリと推論モデルのディレクトリ設定

モデルと
推論する画像を格納するディレクトリを
設定ファイルconfig.iniで指定しておき
切り替えを簡単にできるようにする

これはモデルを今後作成しなおすのと
画像の対象をwebカメラで撮影したものにするか
もしくはリアルタイムで監視したものにするかを切り替えるため

mkdir inventory_images

で画像ファイルの置き場所を作成

vim config.ini

で設定ファイルを作成

[Settings]
model_path = inventory_model/best.pt
image_directory = inventory_images

として保存

count_inventory.py
の中身を
import json
from ultralytics import YOLO
from collections import defaultdict

# JSONファイルからクラスラベルのマッピングを読み込み
with open('label_mapping.json', 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('inventory_model/best.pt')  # ここで適切なモデルを選択

# 画像のロード
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)

# 画像の検出
results = model(image)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果の表示
for label, count in object_counts.items():
    print(f'{label}: {count}個')

から

import json
import cv2
import configparser
from ultralytics import YOLO
from collections import defaultdict
from line_notify import send_line_notify  # インポートを追加
from datetime import datetime
from inventory_database_module 
 import save_detection_to_db  # データベース保存用の関数をインポート
import os

# 設定ファイルの読み込み
config = configparser.ConfigParser()
config.read('config.ini')

# 設定ファイルからモデルパスと画像ディレクトリを取得
model_path = config['Settings']['model_path']
image_directory = config['Settings']['image_directory']

# ラベルマッピングファイルのパス
label_mapping_path = 'label_mapping.json'

# JSONファイルからクラスラベルのマッピングを読み込み
with open(label_mapping_path, 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO(model_path)  # 設定ファイルからモデルパスを使用

# 画像ディレクトリ内の全画像ファイルを処理
for image_filename in os.listdir(image_directory):
    image_path = os.path.join(image_directory, image_filename)
    if os.path.isfile(image_path) and image_path.lower().endswith(('.png', '.jpg', '.jpeg')):
        # 画像のロード
        image = cv2.imread(image_path)

        # 画像の検出
        results = model(image, save=True, conf=0.2, iou=0.5)

        # 検出結果の取得
        detections = results[0]  # 最初の結果を取得
        classes = detections.boxes.cls

        # 検出物体のカウント
        object_counts = defaultdict(int)
        for cls in classes:
            class_label = model.names[int(cls)]
            if class_label in label_mapping:
                label = label_mapping[class_label]
            else:
                label = class_label
            object_counts[label] += 1

        # 検出結果のフィルタリング(1以下のもの)
        filtered_object_counts = {label: count for label, count in object_counts.items() if count <= 1}

        # フィルタリングされた検出結果のメッセージ生成
        message_lines = [f'{label}: {count}個' for label, count in filtered_object_counts.items()]
        message = '\n'.join(message_lines)

        # 現在の時刻を取得
        current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        message = f"{message}\n\nMessage sent at: {current_time}"

        # 検出結果の表示
        for line in message_lines:
            print(line)

        # LINE Notifyにメッセージを送信(フィルタリングされた結果のみ)
        if message_lines:
            send_line_notify(message)
            save_detection_to_db(filtered_object_counts)  # データベースに検出結果を保存
        else:
            print("No objects with counts of 1 or less detected in file:", image_filename)

へ変更

試しに

cp data_bak/Baskulin4.jpg inventory_images

でデータを写し

python count_inventory.py

を実行すると

0: 640x512 1 baskulin, 131.0ms
Speed: 5.6ms preprocess, 131.0ms inference, 6.6ms postprocess per image at shape (1, 3, 640, 512)
Results saved to runs/detect/predict22
バスクリン: 1個
File: runs/detect/predict22/image0.jpg
200
{"status":200,"message":"ok"}

というようにLINEへ送信される

とりあえずここまでできたので
githubで公開し
モデルは roboflowなどを使って改良して後々公開する

yolov8の検出結果のDB格納

検出結果のDB格納

vim create_table.py

を作成

import sqlite3

def create_table():
    conn = sqlite3.connect('detections.db')
    cursor = conn.cursor()

    # テーブルを作成
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS detections (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            label TEXT NOT NULL,
            count INTEGER NOT NULL,
            timestamp TEXT NOT NULL
        )
    ''')

    conn.commit()
    conn.close()

if __name__ == '__main__':
    create_table()

これを実行し
DBを作成

次にDBへ保存するモジュールの作成

vim inventory_database_module.py

でファイルを作成

import sqlite3
from datetime import datetime

def save_detection_to_db(detections):
    conn = sqlite3.connect('detections.db')
    cursor = conn.cursor()

    # 現在の時刻を取得
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    # 検出結果をテーブルに挿入
    for label, count in detections.items():
        cursor.execute('''
            INSERT INTO detections (label, count, timestamp)
            VALUES (?, ?, ?)
        ''', (label, count, current_time))

    conn.commit()
    conn.close()

として保存

import argparse
import json
import cv2
from ultralytics import YOLO
from collections import defaultdict
from line_notify import send_line_notify  # インポートを追加
from datetime import datetime
from inventory_database_module import save_detection_to_db  # データベース保存用の関数をインポート

# コマンドライン引数の解析
parser = argparse.ArgumentParser(description="YOLOv8 Object Detection")
parser.add_argument('image_path', type=str, help='Path to the input image file')
args = parser.parse_args()

# ラベルマッピングファイルのパス
label_mapping_path = 'label_mapping.json'

# JSONファイルからクラスラベルのマッピングを読み込み
with open(label_mapping_path, 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('inventory_model/best.pt')  # ここで適切なモデルを選択

# 画像のロード
image = cv2.imread(args.image_path)

# 画像の検出
results = model(image, save=True, conf=0.1, iou=0.5)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果のフィルタリング(1以下のもの)
filtered_object_counts = {label: count for label, count in object_counts.items() if count <= 1}

# フィルタリングされた検出結果のメッセージ生成
message_lines = [f'{label}: {count}個' for label, count in filtered_object_counts.items()]
message = '\n'.join(message_lines)

# 現在の時刻を取得
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
message = f"{message}\n在庫チェックの時刻: {current_time}"

# 検出結果の表示
for line in message_lines:
    print(line)

# LINE Notifyにメッセージを送信(フィルタリングされた結果のみ)
if message_lines:
    send_line_notify(message)
    save_detection_to_db(filtered_object_counts)  # データベースに検出結果を保存
else:
    print("No objects with counts of 1 or less detected.")

というように
結果をDBに保存し
在庫チェックの時刻も送信するようにコード変更

なお実行した後に
DBの中身を見るには

vim view_detections.py

import sqlite3

def view_detections(db_path='detections.db'):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    # テーブルの内容を取得
    cursor.execute('SELECT * FROM detections')
    rows = cursor.fetchall()

    # カラム名を取得
    column_names = [description[0] for description in cursor.description]

    # 結果を表示
    print(f"{' | '.join(column_names)}")
    print("-" * 50)
    for row in rows:
        print(" | ".join(str(value) for value in row))

    conn.close()

if __name__ == '__main__':
    view_detections()

として保存

python view_detections.py

を実行すると

id | label | count | timestamp
--------------------------------------------------
1 | バスクリン | 1 | 2024-07-07 06:45:47
2 | バスクリン | 1 | 2024-07-07 06:50:42
3 | バスクリン | 1 | 2024-07-07 06:51:43

となり検出結果の確認ができる

認識精度が低いため
精度を0.1まで下げないと認識しないし
並べた時の複数の検出ができていない

とりあえず指定ディレクトリの画像から検出するようにコード変更する

Yolov8検出結果と文字列の結び付け

Yolov8検出結果と文字列の結び付け

在庫管理のため yolov8で在庫対象とするものを検出し
その在庫数が2以下になれば
LINEで買い物リストを送信するものを作成したい
このためには検出結果のカウント
そして
検出されたものを日本語にする必要がある

YOLOv8の検出結果と対応する文字列を結びつけるためには、
検出されたクラスのラベルを
日本語の対応するラベルに変換するマッピングを作成する必要があり

まずYOLOv8の結果取得:
画像をYOLOv8に入力し、検出結果を取得
検出結果には
各物体のクラスラベル
バウンディングボックスの座標などが含まれている

そして
クラスラベルのマッピング作成
検出されたクラスラベルを
日本語の対応するラベルに変換する辞書を作成

例として

label_mapping = {
    'baskulin': 'バスクリン',
    'potato_starch': '片栗粉',
    'shampoo': 'シャンプー'
}

という感じ

以下はchatgptのコード例

import json

# YOLOv8の検出結果の例
# ここではJSON形式で表現されていますが、実際にはYOLOv8から得られたデータ形式に合わせてください
detection_results = [
    {"class": "baskulin", "bbox": [100, 100, 150, 150]},
    {"class": "potato_starch", "bbox": [200, 200, 250, 250]},
    {"class": "shampoo", "bbox": [300, 300, 350, 350]},
]

# クラスラベルのマッピング
label_mapping = {
    'baskulin': 'バスクリン',
    'potato_starch': '片栗粉',
    'shampoo': 'シャンプー'
}

# マッピングの適用
for detection in detection_results:
    class_label = detection['class']
    if class_label in label_mapping:
        detection['class'] = label_mapping[class_label]

# 結果の表示
print(json.dumps(detection_results, ensure_ascii=False, indent=2))

yolov8の検出結果を表示するには?
とすると

import cv2
import matplotlib.pyplot as plt
from ultralytics import YOLO

# YOLOv8モデルのロード
model = YOLO('yolov8s.pt')  # ここで適切なモデルを選択

# 画像のロード
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 画像の検出
results = model(image)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls
boxes = detections.boxes.xyxy
scores = detections.boxes.conf

# クラスラベルのマッピング
label_mapping = {
    'baskulin': 'バスクリン',
    'potato_starch': '片栗粉',
    'shampoo': 'シャンプー'
}

# バウンディングボックスとラベルの描画
for cls, box, score in zip(classes, boxes, scores):
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    x1, y1, x2, y2 = map(int, box)
    cv2.rectangle(image, (x1, y1), (x2, y2), (255, 0, 0), 2)
    cv2.putText(image, f'{label} {score:.2f}', (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255, 0, 0), 2)

# 結果の表示
plt.figure(figsize=(10, 10))
plt.imshow(image)
plt.axis('off')
plt.show()

となるが

バウンディングボックスとラベルを画像に描画
結果をMatplotlibを使って表示
となる

結果の表示で画像での結果表示は不要

from ultralytics import YOLO

# YOLOv8モデルのロード
model = YOLO('yolov8s.pt')  # ここで適切なモデルを選択

# 画像のロード
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)

# 画像の検出
results = model(image)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls
boxes = detections.boxes.xyxy
scores = detections.boxes.conf

# クラスラベルのマッピング
label_mapping = {
    'baskulin': 'バスクリン',
    'potato_starch': '片栗粉',
    'shampoo': 'シャンプー'
}

# 検出結果のテキスト表示
for cls, box, score in zip(classes, boxes, scores):
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    x1, y1, x2, y2 = map(int, box)
    print(f'検出: {label}, 信頼度: {score:.2f}, バウンディングボックス: ({x1}, {y1}, {x2}, {y2})')

バウンディングボックスの座標も不要

from ultralytics import YOLO

# YOLOv8モデルのロード
model = YOLO('yolov8s.pt')  # ここで適切なモデルを選択

# 画像のロード
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)

# 画像の検出
results = model(image)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls
scores = detections.boxes.conf

# クラスラベルのマッピング
label_mapping = {
    'baskulin': 'バスクリン',
    'potato_starch': '片栗粉',
    'shampoo': 'シャンプー'
}

# 検出結果のテキスト表示
for cls, score in zip(classes, scores):
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    print(f'検出: {label}, 信頼度: {score:.2f}')

次に
検出した物体のそれぞれの個数をカウントして表示

from ultralytics import YOLO
from collections import defaultdict

# YOLOv8モデルのロード
model = YOLO('yolov8s.pt')  # ここで適切なモデルを選択

# 画像のロード
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)

# 画像の検出
results = model(image)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# クラスラベルのマッピング
label_mapping = {
    'baskulin': 'バスクリン',
    'potato_starch': '片栗粉',
    'shampoo': 'シャンプー'
}

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果の表示
for label, count in object_counts.items():
    print(f'{label}: {count}個')

これでほぼ目的のものに近くなった

from collections import defaultdict

これは
Pythonの標準ライブラリであるcollectionsモジュールから
defaultdictクラスをインポートしています

defaultdictは、
キーが存在しない場合にデフォルト値を
自動的に提供する辞書を作成するために使用

この場合、物体のカウントを行うために使用している

ただ、在庫管理のものはどんどん追加していくため
別のファイルにして読み込むようにする

vim label_mapping.json

でJSONファイルを作成

{
    "baskulin": "バスクリン",
    "potato_starch": "片栗粉",
    "shampoo": "シャンプー"
}

次にJSON ファイルの読み込み

import json
from ultralytics import YOLO
from collections import defaultdict

# JSONファイルからクラスラベルのマッピングを読み込み
with open('label_mapping.json', 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('yolov8s.pt')  # ここで適切なモデルを選択

# 画像のロード
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)

# 画像の検出
results = model(image)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果の表示
for label, count in object_counts.items():
    print(f'{label}: {count}個')

これを書き換える

コマンドラインで動作するようにする

コマンドラインから画像ファイルを指定して使用するようには
Pythonのargparseモジュールを使用

これにより
コマンドラインから画像ファイルのパスを指定できるようになる

また使用するモデルは

inventory_model/best.pt

とする

vim count_inventory_terminal.py

で中身を

import argparse
import json
import cv2
from ultralytics import YOLO
from collections import defaultdict

# コマンドライン引数の解析
parser = argparse.ArgumentParser(description="YOLOv8 Object Detection")
parser.add_argument('image_path', type=str, help='Path to the input image file')
args = parser.parse_args()

# ラベルマッピングファイルのパス
label_mapping_path = 'label_mapping.json'

# JSONファイルからクラスラベルのマッピングを読み込み
with open(label_mapping_path, 'r', encoding='utf-8') as f:
    label_mapping = json.load(f)

# YOLOv8モデルのロード
model = YOLO('inventory_model/best.pt')  # ここで適切なモデルを選択

# 画像のロード
image = cv2.imread(args.image_path)

# 画像の検出
results = model(image)

# 検出結果の取得
detections = results[0]  # 最初の結果を取得
classes = detections.boxes.cls

# 検出物体のカウント
object_counts = defaultdict(int)
for cls in classes:
    class_label = model.names[int(cls)]
    if class_label in label_mapping:
        label = label_mapping[class_label]
    else:
        label = class_label
    object_counts[label] += 1

# 検出結果の表示
for label, count in object_counts.items():
    print(f'{label}: {count}個')

これで実行すると

python count_inventory_terminal.py data_bak/Baskulin1.jpg

0: 640x512 1 baskulin, 114.8ms
Speed: 9.4ms preprocess, 114.8ms inference, 7.5ms postprocess per image at shape (1, 3, 640, 512)
バスクリン: 1個

となって検出結果の日本語表示ができる

とりあえず対象物の日本語化とカウントができたので
次はLINEで送信機能を作成する

yolov8 を Google Colab で実行

yolov8のテスト

自動ラベルで作成したものが間違っているのか
それとも変換したのが問題なのかを知りたいので
一度試す

Colabで実験する

# Install ultralytics
!pip install ultralytics

でyolov8インストール

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

でマウント

!yolo obb train data=/content/drive/MyDrive/InventoryControl/daily_necessities_label/data.yaml pretrained=yolov8n-obb.pt epochs=100 imgsz=640 exist_ok=True

で学習

このコマンドは、YOLO (You Only Look Once) モデルを用いて物体検出の学習を行うためのものです。特に、YOLOv8n-obbモデルを用いて、向き付き境界ボックス(Oriented Bounding Boxes, OBB)を使用して物体を検出する訓練を行います。以下は各パラメータの詳細です:
* train: このオプションは、モデルを訓練モードに設定します。
* data=/content/drive/MyDrive/InventoryControl/daily_necessities_label/data.yaml: 訓練に使用するデータセットの設定ファイルのパスです。このYAMLファイルには、訓練データ、検証データのパスや、クラス名が含まれています。
* pretrained=yolov8n-obb.pt: 事前訓練済みのモデルファイル。このファイルを初期の重みとして使用して、訓練を開始します。
* epochs=100: モデルが訓練データを何回繰り返して学習するかを指定します。この場合、100回繰り返します。
* imgsz=640: 入力画像のサイズを640ピクセルにリサイズします。
* exist_ok=True: 既に訓練結果のフォルダが存在しても、エラーを出さずに上書きまたは新たに訓練を開始することを許可します。
このコマンドを実行することで、指定されたパラメータでYOLOモデルの訓練が行われ、物体検出の精度を向上させることができます。

とりあえず、バスクリンだけでなく
バスロマンも学習させる

そして肌おもいも学習させて、その状態から実行してみる

とりあえずバスロマンと肌おもいの画像からは
バスロマンをバスクリンと誤認識してるけど
カウントはできた

バスクリンの在庫を使い切ったため
バスロマンと肌おもいの写真で識別してみました

バスクリンとバスロマンを誤認識してますが
数は合っていますので
在庫管理には使えるとは思います

いっそバスロマンも学習すれば誤認識はなくなるかもしれません

以下ログと使用したテストの画像です

# Install ultralytics
!pip install ultralytics

でyolov8インストール

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

でgoogle driveマウント

!yolo obb train data=/content/drive/MyDrive/InventoryControl/daily_necessities_label/data.yaml pretrained=yolov8n-obb.pt epochs=400 exist_ok=True

で前回370程度のエポックで停止したので
今回は400にしてA100で実行

import os
import subprocess

source_file = '/content/drive/MyDrive/PXL_20240617_182349485.jpg'
# テキストファイルのパスを構築(画像ファイル名と同じ)
file_name, file_extension = os.path.splitext(source_file)
label_file_path = '/content/runs/obb/predict/labels/' + os.path.basename(file_name) + '.txt'
# ファイルの存在を確認し、存在する場合は削除
if os.path.exists(label_file_path):
    os.remove(label_file_path)
# YOLOを使用して予測を実行
!yolo obb predict model=/content/runs/obb/train/weights/best.pt source='{source_file}' save=True save_txt=True exist_ok=True
# ファイルが存在する場合のみ、テキストファイルの行数を取得して表示
if os.path.exists(label_file_path):
    num_lines = subprocess.check_output(["wc", "-l", label_file_path]).decode().split()[0]
    print("バスクリンの数は", num_lines)
else:
    print("ファイルが見つかりませんでした。")

実行結果は

Ultralytics YOLOv8.2.35 :rocket: Python-3.10.12 torch-2.3.0+cu121 CUDA:0 (NVIDIA A100-SXM4-40GB, 40514MiB)
YOLOv8n-obb summary (fused): 187 layers, 3077804 parameters, 0 gradients, 8.3 GFLOPs

image 1/1 /content/drive/MyDrive/PXL_20240617_182349485.jpg: 1024x800 143.7ms
Speed: 12.4ms preprocess, 143.7ms inference, 197.3ms postprocess per image at shape (1, 3, 1024, 800)
Results saved to runs/obb/predict
1 label saved to runs/obb/predict/labels
:bulb: Learn more at https://docs.ultralytics.com/modes/predict
バスクリンの数は 1

日用品の買い物の時に少しずつ写真を撮影し
学習データに使っていこうと思います

 

Yolov8 を webカメラで使う

Yolov8 を webカメラで使う

import cv2
from yolov8.utils.webcam import Webcam

def main():
    webcam = Webcam(source=0)  # 通常、0はデフォルトのWebカメラを示します
    while True:
        frame = webcam.get_frame()
        if frame is None:
            break
        # YOLOv8を使って画像上で物体検出を実行
        results = webcam.model(frame)
        # 検出結果の表示
        results.show()
        # 'q'キーが押されたら終了
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

if __name__ == '__main__':
    main()


chatgptの答えだが

実行すると

Traceback (most recent call last):
  File "/Users/snowpool/aw10s/inventory/webcam_yv8.py", line 2, in <module>
    from yolov8.utils.webcam import Webcam
ModuleNotFoundError: No module named 'yolov8'

となるので
yolov8 webカメラ
で検索し調べる

【やってみた】YOLOv8の機能試す&Webカメラでリアルタイム推論

によれば
Webカメラの場合はカメラ番号を入れれば実行可能とのこと

from ultralytics import YOLO

model = YOLO("yolov8n.pt")
results = model(0 , show=True) 
for i in enumerate(results):
    print(i)

を実行したら
M1macbookair のカメラからyolov8が起動し
該当するものが判定された

なおこのコードの場合
Ctrl + c で止めるまでずっと動きます

Yolov8 を M1 Mac で使う

Yolov8 を M1 Mac で使う

YOLOv8導入まとめ
を参考に

pip install ultralytics

を実行

物体検出

yolo predict model=yolov8n.pt source='https://ultralytics.com/images/bus.jpg'

というように
Source に画像ファイルを指定すればOKみたい

物体検出ではなくセグメンテーションしたい場合は、yolov8n.ptではなくyolov8n-seg.ptを使う

yolo predict model=yolov8n-seg.pt source='https://ultralytics.com/images/bus.jpg'

これもsourceで画像ファイルを指定する

コマンドを実行すると

runs/detect/predict/

に指定したファイル名と同じファイル名で検出結果が作成される
とあるが

Results saved to runs/detect/predict

でどこに保存されているかわからないため

更新日が最近のファイルを見つける(findコマンド)
を参考に

find . -mtime -1 -ls | top

で検索し

ls ./runs/detect/predict 

でファイルができているのを確認

Finder から開くと面倒なので

MacでターミナルからFinderを開くコマンド「open」
を参考に

open .

でカレントディレクトリを Finder で開いて確認

ちなみに
yolov8n.pt
yolov8n-seg.pt

Nはモデルのサイズで
x > l > m > s > n
の順に大きなモデルになっている

xが最も大きいモデルで、nが最も小さいモデル

大きいモデルは検出にパワーが必要になるものの、検出精度が高くなる

xサイズのモデルで検出なら

yolo predict model=yolov8x.pt source='https://ultralytics.com/images/bus.jpg'

M1Mac 16GB で22秒ほどで処理できた

ポーズ検出には
yolov8x.ptの代わりにyolov8x-pose.ptを使う

yolo predict model=yolov8x-pose.pt source='https://ultralytics.com/images/bus.jpg'

これで
首から上が緑、腕が青、体がパープル、足がオレンジ色で、それぞれポーズが検出される

大体20秒くらいで処理

yolov8n.pt、yolov8n-seg.pt、yolov8n-pose.ptなどについての情報は、YOLOv8 Modelsにある

なおGPUを活用するには
Google Colaboratory
を使う

ちなみに興味があったんで
maMacbookAir 16GBでどのくらいかかるか実験

yolo predict model=yolov8x-seg.pt source='https://youtu.be/Zgi9g1ksQHc'

を実験したけど

Ultralytics YOLOv8.0.132 🚀 Python-3.10.6 torch-2.0.1 CPU
YOLOv8x-seg summary (fused): 295 layers, 71797696 parameters, 0 gradients

ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.
Traceback (most recent call last):
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 815, in wrapper
    return func(self, *args, **kwargs)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 836, in __extract_info
    ie_result = ie.extract(url)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/extractor/common.py", line 534, in extract
    ie_result = self._real_extract(url)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/extractor/youtube.py", line 1794, in _real_extract
    'uploader_id': self._search_regex(r'/(?:channel|user)/([^/?&#]+)', owner_profile_url, 'uploader id') if owner_profile_url else None,
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/extractor/common.py", line 1012, in _search_regex
    raise RegexNotFoundError('Unable to extract %s' % _name)
youtube_dl.utils.RegexNotFoundError: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/backend_youtube_dl.py", line 40, in _fetch_basic
    self._ydl_info = ydl.extract_info(self.videoid, download=False)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 808, in extract_info
    return self.__extract_info(url, ie, download, extra_info, process)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 824, in wrapper
    self.report_error(compat_str(e), e.format_traceback())
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 628, in report_error
    self.trouble(error_message, tb)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 598, in trouble
    raise DownloadError(message, exc_info)
youtube_dl.utils.DownloadError: ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/snowpool/.pyenv/versions/3.10.6/bin/yolo", line 8, in <module>
    sys.exit(entrypoint())
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/cfg/__init__.py", line 407, in entrypoint
    getattr(model, mode)(**overrides)  # default args from model
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/torch/utils/_contextlib.py", line 115, in decorate_context
    return func(*args, **kwargs)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/engine/model.py", line 255, in predict
    return self.predictor.predict_cli(source=source) if is_cli else self.predictor(source=source, stream=stream)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/engine/predictor.py", line 195, in predict_cli
    for _ in gen:  # running CLI inference without accumulating any outputs (do not modify)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/torch/utils/_contextlib.py", line 35, in generator_context
    response = gen.send(None)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/engine/predictor.py", line 222, in stream_inference
    self.setup_source(source if source is not None else self.args.source)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/engine/predictor.py", line 203, in setup_source
    self.dataset = load_inference_source(source=source, imgsz=self.imgsz, vid_stride=self.args.vid_stride)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/data/build.py", line 159, in load_inference_source
    dataset = LoadStreams(source, imgsz=imgsz, vid_stride=vid_stride)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/data/dataloaders/stream_loaders.py", line 48, in __init__
    s = get_best_youtube_url(s)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/data/dataloaders/stream_loaders.py", line 386, in get_best_youtube_url
    return pafy.new(url).getbest(preftype='mp4').url
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/pafy.py", line 124, in new
    return Pafy(url, basic, gdata, size, callback, ydl_opts=ydl_opts)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/backend_youtube_dl.py", line 31, in __init__
    super(YtdlPafy, self).__init__(*args, **kwargs)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/backend_shared.py", line 97, in __init__
    self._fetch_basic()
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/backend_youtube_dl.py", line 43, in _fetch_basic
    raise IOError(str(e).replace('YouTube said', 'Youtube says'))
OSError: ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

で終了してしまった

とりあえず静止画像はここまででできそうなので
【やってみた】YOLOv8の機能試す&Webカメラでリアルタイム推論
を参考に
リアルタイムでできるようにする