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.
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.
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.
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
Yanlış düşünmüşüm, çok teşekkür ederim yardımınız için.