pjreddie / darknet

Convolutional Neural Networks
http://pjreddie.com/darknet/
Other
25.8k stars 21.33k forks source link

Object of thype 'METADATA' has no len() #2297

Open phil100vol opened 4 years ago

phil100vol commented 4 years ago

Hi,

I want to detect objects on my rtsp stream. Unfortunate the code ends in the following error:

File "/home/cctv/darknet/darknet.py", line 174, in detect_image
    do_nms_sort(detections, num, len(class_names), nms)
TypeError: object of type 'METADATA' has no len()

My minimal example looks like that:

# -*- coding: utf-8 -*-

import os
import cv2
import numpy as np
import time
import darknet

######################
sUser = "user"
sPassword = "1234"
sChannel = str(12)

configPath = "./cfg/yolov4.cfg"
weightPath = "./yolov4.weights"
metaPath = "./cfg/coco.data"

def cvDrawBoxes(detections, img):
    # Colored labels dictionary
    color_dict = {
        "person" : [0, 255, 255]
    }

    for detection in detections:
        x, y, w, h = detection[2][0],\
            detection[2][1],\
            detection[2][2],\
            detection[2][3]
        name_tag = str(detection[0].decode())
        for name_key, color_val in color_dict.items():
            if name_key == name_tag:
                color = color_val 
                xmin, ymin, xmax, ymax = convertBack(
                float(x), float(y), float(w), float(h))
                pt1 = (xmin, ymin)
                pt2 = (xmax, ymax)
                cv2.rectangle(img, pt1, pt2, color, 1)
                cv2.putText(img,
                            detection[0].decode() +
                            " [" + str(round(detection[1] * 100, 2)) + "]",
                            (pt1[0], pt1[1] - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                            color, 2)
    return img

netMain = darknet.load_net_custom(configPath.encode("ascii"), weightPath.encode("ascii"), 0, 1)   
metaMain = darknet.load_meta(metaPath.encode("ascii"))

#convertion rtsp stream
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp"

cap = cv2.VideoCapture(str('rtsp://')+sUser+str(':')+sPassword+str('@')+str('192.168.0.21')+str(':554/')+sChannel,cv2.CAP_FFMPEG)

_, frame = cap.read()
rows,cols,channels = frame.shape
darknet_image = darknet.make_image(cols,rows,3)

### LOOP ###

while True:

    _, frame = cap.read()
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) 
    frame_resized = cv2.resize(frame_rgb,
                                   (cols, rows),
                                   interpolation=cv2.INTER_LINEAR)
    darknet.copy_image_from_bytes(darknet_image,frame_resized.tobytes()) 

    ###########
    detections = darknet.detect_image(netMain, metaMain, darknet_image, thresh=0.25)
    ###########

    image = cvDrawBoxes(detections, frame)

    cv2.imshow("image", frame)

    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

cap.release
cv2.destroyAllWindows()`

Hope someone can give me a hand. Thanks

Phil

eandert commented 4 years ago

It seems you wrote this code for an older version of darknet.py prior to the changes made in 52c7314. The newest version of darknet.py has changed in some subtle ways. I suggest checking out https://github.com/AlexeyAB/darknet/blob/master/darknet_images.py for examples of how the newer version can be called.

You will need to change your code here:

netMain = darknet.load_net_custom(configPath.encode("ascii"), weightPath.encode("ascii"), 0, 1)
metaMain = darknet.load_meta(metaPath.encode("ascii"))

to be compatable with the newer version to something along these lines:

network, class_names, class_colors = darknet.load_network(configPath,  metaPath, weightPath, batch_size=1)

and then change your old call to detect_image: detections = darknet.detect_image(netMain, metaMain, darknet_image, thresh=0.25) to something more along these lines: detections = darknet.detect_image(network, class_names, darknet_image, thresh=0.25)

And finally within your cvDrawBoxes function:

for detection in detections:
        x, y, w, h = detection[2][0],\
            detection[2][1],\
            detection[2][2],\
            detection[2][3]
        name_tag = str(detection[0].decode())

Will need to be changed to something along the lines of:

for label, confidence, bbox in detections:
       x, y, w, h = (bbox[0],
             bbox[1],
             bbox[2],
             bbox[3])
       name_tag = label

and finally any reference to detection[1] in cvDrawBoxes should be changed to confidence

Hopefully I hit all of the major points here but I can't guarantee I caught every error. I recently had to update some older code as well and was having the same error so hope this helps. My code seems to be working after all of these fixes.

sumanjob1988 commented 4 years ago

@eandert I got the same error and thanks to you, your solution works for me.

tejask00 commented 3 years ago

netMain = darknet.load_net_custom(configPath.encode("ascii"), weightPath.encode("ascii"), 0, 1) metaMain = darknet.load_meta(metaPath.encode("ascii"))

do i have to change these lines with network, class_names, class_colors = darknet.load_network(configPath, metaPath, weightPath, batch_size=1) these?

sfc9982 commented 2 years ago

also helpful for me, same issue

Fadil-1 commented 2 years ago

@eandert YOU ROCK!. You saved me hours of headache. Thank you so much! And to the people who are not sure about @eandert answer's because he/she wrote "along these lines", try to do exactly what he/she said. It worked for me.

Namely replace each of netMain = darknet.load_net_custom(configPath.encode("ascii"), weightPath.encode("ascii"), 0, 1) and metaMain = darknet.load_meta(metaPath.encode("ascii")) with network, class_names, class_colors = darknet.load_network(configPath, metaPath, weightPath, batch_size=1)

detections = darknet.detect_image(netMain, metaMain, darknet_image, thresh=0.25) with detections = darknet.detect_image(network, class_names, darknet_image, thresh=0.25)

as well as the modifications in the for loop! Try it it works.

Thanks again @eandert