YOLO Opencv Orta Noktayı Bulmak

Merhaba,
YOLO ile nesne tanıyıp, tanıdığım nesnenin orta noktasını bulmak istiyorum. x, y, w, h değerleri elimde var. Mesela (x,y) dikdörtgenin en sol üst köşesi. Bu köşeden yola çıkarak orta noktayı bulabiliyorum. Fakat çoğu zaman yanlış gösteriyor. Mesela tanıdığı nesne ekranın kenarlarında ise bu hata oluyor(resimde ki). Neden olduğunu çözebilmiş değilim. Yardımcı olursanız çok sevinirim.

Merhaba. Orta noktayı hesaplayan kodu paylaşmamışsınız.

1 Beğeni

Elinizdeki kodu görmeden doğru bir şey söylemek zor.

Teoride bir çerçeve çiziyorsa nesne etrafına, çerçevenin genişliğinin yarısı ve çerçevenin yüksekliğinin yarısı hesabıyla orta noktası bulunabilir gibi duruyor.

Ama nokta neden yanlış yerde duruyor derseniz.

Aynı anda kaç nesne algıladığı, hangi nesnelerin koordinatlarının gösterildiği ile alakalı olabilir.

Elinizdeki kodu paylaşırsanız bakabiliriz.

Olmadı bir parça kod yazarız yine de nesne yakalayan kodların davranışları arasında bazan beklemediğiniz nesneler yakaladığı oluyor.

Belki onunla alakalı olabilir.

Ben bari kendime kod ekleyim.

Onun üzerinde konuşalım. Daha kolay olur.

import argparse
import glob
import time
from pathlib import Path
import cv2
import numpy as np

CONFIDENCE_THRESHOLD =0.5
NMS_THRESHOLD =0.4

vc = cv2.VideoCapture(0, cv2.CAP_DSHOW)
weights = glob.glob("yolo/*.weights")[0]
labels = glob.glob("yolo/*.txt")[0]
cfg = glob.glob("yolo/*.cfg")[0]

class_names = list()
with open(labels, "r") as f:
    class_names = [cname.strip() for cname in f.readlines()]

COLORS = np.random.randint(0, 255, size=(len(class_names), 3), dtype="uint8")

net = cv2.dnn.readNetFromDarknet(cfg, weights)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)

layer = net.getLayerNames()

layer = [layer[i - 1] for i in net.getUnconnectedOutLayers()]
#layer = [layer[i[0] - 1] for i in net.getUnconnectedOutLayers()]

def detect(frm, net, ln):
    (H, W) = frm.shape[:2]
    blob = cv2.dnn.blobFromImage(frm, 1 / 255.0, (416, 416), swapRB=True, crop=False)
    net.setInput(blob)
    start_time = time.time()
    layerOutputs = net.forward(ln)
    end_time = time.time()

    boxes = []
    classIds = []
    confidences = []
    for output in layerOutputs:
        for detection in output:
            scores = detection[5:]
            classID = np.argmax(scores)
            confidence = scores[classID]

            if confidence > CONFIDENCE_THRESHOLD:
                box = detection[0:4] * np.array([W, H, W, H])
                (centerX, centerY, width, height) = box.astype("int")
                x = int(centerX - (width / 2))
                y = int(centerY - (height / 2))

                boxes.append([x, y, int(width), int(height)])
                classIds.append(classID)
                confidences.append(float(confidence))

    idxs = cv2.dnn.NMSBoxes(boxes, confidences, CONFIDENCE_THRESHOLD, NMS_THRESHOLD)

    if len(idxs) > 0:
        for i in idxs.flatten():
            (x, y) = (boxes[i][0], boxes[i][1])
            (w, h) = (boxes[i][2], boxes[i][3])

            color = [int(c) for c in COLORS[classIds[i]]]
            cv2.rectangle(frm, (x, y), (x + w, y + h), color, 2)
            text = "{}: {:.4f}".format(class_names[classIds[i]], confidences[i])
            cv2.putText(
                frm, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2
            )

            fps_label = "FPS: %.2f" % (1 / (end_time - start_time))
            cv2.putText(
                frm, fps_label, (0, 25), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2
            )


while cv2.waitKey(1) < 1:
    (grabbed, frame) = vc.read()
    if not grabbed:
        break
    frame = cv2.resize(frame, (600,480))
    detect(frame, net, layer)

    cv2.imshow("detections", frame)


cv2.destroyAllWindows()

Burada sadece nesneleri tanımlayan bir kod.

GPU desteği durumuna göre kodunuz çalışmazsa;

layer = [layer[i - 1] for i in net.getUnconnectedOutLayers()]
#layer = [layer[i[0] - 1] for i in net.getUnconnectedOutLayers()]

Yukarıdaki satırlardan layer kodunun diğerini seçersiniz ben CPU kodunda kodladım.

Mesela aradığımız labels.txt dosyası içindeki.

“cell phone” olsun.

Orta nokta hesaplarken, önce bulunan nesnenin cell phone olduğunu doğrulayıp, sonrasında orta noktasını çizdirmektir.

Yoksa görüntü içinde bulduğu her şeyi indeksleyebilir ve bulduğu rastgele bir nesnenin orta noktasını veriyor olabilir.

Aklıma ilk gelen ihtimal bu. Tabi kodunuzu görme şansımız olursa daha fazla çözüme yaklaşabiliriz.

2 Beğeni

Hemen paylaşıyorum, teşekkürler.

Cevaplarınız ve ilgi, alakanız için gerçekten çok teşekkür ederim. Kodları hemen paylaşıyorum.

import cv2


# Opencv DNN
net = cv2.dnn.readNet("dnn_model/yolov4-tiny.weights", "dnn_model/yolov4-tiny.cfg")
model = cv2.dnn_DetectionModel(net)
model.setInputParams(size=(320, 320), scale=1/255)


# Load class lists
classes = []
with open("dnn_model/classes.txt", "r") as file_object:
    for class_name in file_object.readlines():
        #print(class_name)
        class_name = class_name.strip()  # satır arası boşluklar için

        classes.append(class_name)



# Initialize camera
cap = cv2.VideoCapture(0)


while True:
    # Get frames
    ret, frame = cap.read()



    # Object Detection
    (class_ids, scores, bboxes) = model.detect(frame, confThreshold=0.3, nmsThreshold=.4)
    for class_id, score, bbox in zip(class_ids, scores, bboxes):
        (x, y, w, h) = bbox
        cv2.rectangle(frame, (x, y), (x + w, y + h), (200,0,50), 3)
        print(bbox)
        a = x+w
        b = y+h
        cv2.circle(frame,((int(a/2)),(int(b/2))), 1, (0,0,255), 6)  #ORTA NOKTA HESAPLAMAK İÇİN YAPTIĞIM İŞLEM KISMI

        class_name = classes[class_id]
        cv2.putText(frame, class_name, (x, y - 10), cv2.FONT_HERSHEY_PLAIN, 3, (200,0,50), 2)
        
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1)
    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()


Ben şuan test amaçlı YOLO’ nun kendi modeli ile test yapıyorum. Ancak amacım tek bir nesne üzerine bu kodları çalıştırmak. Kendi özelleştirilmiş YOLO modelimizi de en kısa zamanda tamamlayıp onun üzerinde kullanacağız. Ancak dediğim gibi çok sağlıklı çalışmıyor, hatta genelde orta noktası sapıyor.

Teşekkür ederim, kodları paylaştım.

Buranın x+x+w olması lazım, w bir nokta temsil etmiyor. x+w ise en sağ noktayı temsil ediyor. Size iki noktanın ortalaması lazım.

Aynı şey b için de geçerli.

2 Beğeni

Kodu çalıştırmadım.

 cv2.rectangle(frame, (x, y), (x + w, y + h), (200,0,50), 3)
        print(bbox)
        a = x+w
        b = y+h
        cv2.circle(frame,((int(a/2)),(int(b/2))), 1, (0,0,255), 6)  #ORTA NOKTA HESAPLAMAK İÇİN YAPTIĞIM İŞLEM KISMI

Bu kısımda a/2 yerine a yazıp, a= x+(w/2) yapmak gerekmez mi?

Yani

a= x+(w/2)

cv2.circle(frame,((int(a)),…

Gibi, sanki bölme yanlış olmuş gibi.

Üstün körü cevapladım.

İnceleyin, vaktim olursa detaylı bakarım.

EDİT:

Bu kadar yapmışken ilgili kısmı da değiştirip koyayım bari:

 cv2.rectangle(frame, (x, y), (x + w, y + h), (200,0,50), 3)
        print(bbox)
        a = x+(w/2)  # Çerçeve genişliğinin yarısı
        b = y+(h/2)  # Çerçeve yüksekliğinin yarısı
        cv2.circle(frame,((int(a)),(int(b))), 1, (0,0,255), 6)  #ORTA NOKTA HESAPLAMAK İÇİN YAPTIĞIM İŞLEM KISMI
1 Beğeni

Yanlış düşünmüşüm, çok teşekkür ederim yardımınız için.

1 Beğeni