kesu yotei

bikoudesu kesu yotei

import torch

import cv2

import numpy as np

from PIL import Image

from torchvision.transforms import Compose, Resize, ToTensor, Normalize

from ultralytics import YOLO



# MiDaSモデルのロード

midas = torch.hub.load("intel-isl/MiDaS", "DPT_Large")


# MiDaS用の前処理設定

midas_transforms = Compose([

    Resize(384),  # モデルに合わせたリサイズ

    ToTensor(),  # テンソルに変換

    Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # 正規化

])


# モデルを評価モードに設定

midas.eval()


# YOLOv8n-segモデルをロード

model = YOLO("./weights/yolov8n-seg.pt")


# 画像を読み込む

image = cv2.imread("./target/0001.jpg")


# 物体を検出

results = model(image)


# 画像を深度推定モデルに入力する前に変換

input_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

input_image = Image.fromarray(input_image)  # numpy配列からPILイメージに変換

input_image = midas_transforms(input_image).unsqueeze(0)


# 深度推定

with torch.no_grad():

    depth_map = midas(input_image).squeeze().cpu().numpy()


# 深度マップをリサイズして元の画像サイズに合わせる

depth_map = cv2.resize(depth_map, (image.shape[1], image.shape[0]))


# カメラの焦点距離(キャリブレーションから取得した値を使用)

focal_length = 500.0  # 例として500としています。実際にはキャリブレーションで取得した値を使用


# 信頼度の閾値を設定

confidence_threshold = 0.5  # 0.5以上の信頼度を持つ検出のみを処理


# クラス名の取得

class_names = model.names  # クラス名はモデルの `names` 属性から取得


# 物体が検出されたかどうかのフラグ

objects_detected = False


# 物体の高さと横幅を計算

for result in results:

    if result.boxes is not None and len(result.boxes) > 0:

        for box, mask in zip(result.boxes, result.masks.data):  # 各検出に対して処理

            if box.conf > confidence_threshold:  # 信頼度が閾値以上のもののみ処理

                mask = mask.cpu().numpy()  # テンソルからnumpy配列に変換

                mask = (mask * 255).astype(np.uint8)  # マスクを2値化


                # バウンディングボックスを取得

                x, y, w, h = cv2.boundingRect(mask)


                # マスク領域の深度を取得

                mask_depth = depth_map[y:y+h, x:x+w]

                avg_depth = np.mean(mask_depth)


                # 物体の現実世界での高さと横幅を計算

                real_height = (h * avg_depth) / focal_length

                real_width = (w * avg_depth) / focal_length

                print(f'物体の現実世界での高さ: {real_height:.2f} メートル')

                print(f'物体の現実世界での横幅: {real_width:.2f} メートル')


                # クラス名の取得

                class_id = int(box.cls)  # クラスIDを取得

                class_name = class_names[class_id]  # クラス名を取得


                # バウンディングボックスを画像に描画

                cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)


                # テキストを画像に書き込み

                confidence = box.conf.item()  # テンソルからスカラー値に変換

                text = f'{class_name}: H={real_height:.2f} m, W={real_width:.2f} m, Confidence: {confidence:.2f}'

                cv2.putText(image, text, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)


                objects_detected = True


# 物体が検出されなかった場合の処理

if not objects_detected:

    cv2.putText(image, 'No objects detected', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)


# 結果を表示

cv2.imshow("Detected Image", image)

cv2.waitKey(0)

cv2.destroyAllWindows()





この記事が気に入ったらサポートをしてみませんか?