ayooshkathuria / YOLO_v3_tutorial_from_scratch

Accompanying code for Paperspace tutorial series "How to Implement YOLO v3 Object Detector from Scratch"
https://blog.paperspace.com/how-to-implement-a-yolo-object-detector-in-pytorch/
2.32k stars 725 forks source link

OpenCV(4.5.2) :-1: error: (-5:Bad argument) in function 'rectangle' #69

Open vineeth357 opened 3 years ago

vineeth357 commented 3 years ago

Objects Detected: bicycle truck dog

Traceback (most recent call last): File "detect.py", line 201, in list(map(lambda x: write(x, loaded_ims), output)) File "detect.py", line 201, in list(map(lambda x: write(x, loaded_ims), output)) File "detect.py", line 193, in write cv2.rectangle(img, c1, c2, color, 1) cv2.error: OpenCV(4.5.2) :-1: error: (-5:Bad argument) in function 'rectangle'

Overload resolution failed:

  • Can't parse 'pt1'. Sequence item with index 0 has a wrong type
  • Can't parse 'pt1'. Sequence item with index 0 has a wrong type
  • Can't parse 'rec'. Expected sequence length 4, got 2
  • Can't parse 'rec'. Expected sequence length 4, got 2

I am getting this error when I ran the detect.py file for testing. There is some error in the cv2.rectangle(). If anyone knows help me.

EZ4BRUCE commented 3 years ago

this is because cv2.rectangle(). only take int ,u can copy my write(x, results) below

def write(x, results):
    c1 = tuple(x[1:3].int())
    c2 = tuple(x[3:5].int())
    d1=(int(c1[0]), int(c1[1]))
    d2=(int(c2[0]), int(c2[1]))
    img = results[int(x[0])]
    cls = int(x[-1])
    color = random.choice(colors)
    label = "{0}".format(classes[cls])
    cv2.rectangle(img, d1, d2, color, 1)
    t_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_PLAIN, 1, 1)[0]
    c2 = c1[0] + t_size[0] + 3, c1[1] + t_size[1] + 4
    cv2.rectangle(img, d1, d2, color, -1)
    cv2.putText(img, label, (int(c1[0]), int(c1[1] + t_size[1] + 4)),
                cv2.FONT_HERSHEY_PLAIN, 1, [225, 255, 255], 1)
    return img
WenqingZong commented 3 years ago

Got the same problem and applied @EZ4BRUCE suggestion. The program runs smoothly, but the output image is a bit strange, the detected bounding boxes are no longer boxes, they become some pure colour rectangles.

Here is the det image I have now: det_dog-cycle-car

I'm still digging in this issue, will update if I found the solution.

WenqingZong commented 3 years ago

Update: The 5th parameter of cv2.rectangle is thickness, according to OpenCV documentation, negative values, like FILLED, mean that the function has to draw a filled rectangle. The bug is caused by the second cv2.rectangle call, which intends to draw a small filled rectangle only for the label text. The right bottom coordinate of the filled rectangle is not updated.

Here is the modified (and should be bug-free) code:

def write(x, results):
    c1 = tuple(x[1:3].int())
    c2 = tuple(x[3:5].int())
    d1 = (int(c1[0]), int(c1[1]))
    d2 = (int(c2[0]), int(c2[1]))
    img = results[int(x[0])]
    cls = int(x[-1])
    color = random.choice(colors)
    label = "{0}".format(classes[cls])
    cv2.rectangle(img, d1, d2, color, 1)
    t_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_PLAIN, 1, 1)[0]
    c2 = c1[0] + t_size[0] + 3, c1[1] + t_size[1] + 4
    d2 = (int(c2[0]), int(c2[1]))
    cv2.rectangle(img, d1, d2, color, -1)
    cv2.putText(img, label, (int(c1[0]), int(c1[1] + t_size[1] + 4)), cv2.FONT_HERSHEY_PLAIN, 1, [225, 255, 255], 1)
    return img
Dawn11041107 commented 1 year ago

You can change c1,c2 from tensor to int type,such as

c1 = (int(c1[0].item()), int(c1[1].item()))
c2 = (int(c2[0].item()), int(c2[1].item()))

Therefore, the whole function is

def write(x, results):
    c1 = tuple(x[1:3].int())
    c2 = tuple(x[3:5].int())

    # 将c1和c2的值转换为整数类型
    c1 = (int(c1[0].item()), int(c1[1].item()))
    c2 = (int(c2[0].item()), int(c2[1].item()))

    img = results[int(x[0])]
    cls = int(x[-1])
    color = random.choice(colors)
    label = "{0}".format(classes[cls])
    cv2.rectangle(img, c1, c2, color, 2)
    t_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_PLAIN, 1 , 1)[0]
    c2 = c1[0] + t_size[0] + 3, c1[1] + t_size[1] + 4
    cv2.rectangle(img, c1, c2,color, -1)
    cv2.putText(img, label, (c1[0], c1[1] + t_size[1] + 4), cv2.FONT_HERSHEY_PLAIN, 1, [225,255,255], 1);
    return img