3

I want to get bounding box coordinates (as xmin, xmax, ymin, ymax) on darknet YOLOv3 i was tried some methods but when I compile the program after changing codes, I cant see any differences.

How can I find the bounding box coordinates of Darknette, or why do the changes not affect the program?

Emrah Kalfa
  • 31
  • 1
  • 2

2 Answers2

2

In Yolo, the coordinates are relative. Meaning that the annotations are written this way:

<object-class> <x_center> <y_center> <width> <height>

where x_center and y_center are float values relative to width and height of image, it can be equal from (0.0 to 1.0]. so:

<x> = <absolute_x> / <image_width>

<y> = <absolute_y> / <image_height>

<width> = <box_absolute_width> / <image_width>

<height> = <box_absolute_height> / <image_height>

If you are using AlexeyAB code, you can get the coordinates like this:

darknet.exe detector test cfg/coco.data yolov3.cfg yolov3.weights -ext_output dog.jpg

To get the coordinates for your code, you need to calculate each one first. For example, to get the xmin:

xmin = (box_x-center - box_width/2) * img_width

and so on.

Hadi GhahremanNezhad
  • 2,377
  • 5
  • 29
  • 58
  • I understand but i can't make any change as i said. You have any idea about it? – Emrah Kalfa Jul 29 '19 at 16:41
  • You should probably post the program here. Meanwhile, if your changes are not seen, maybe you are not making the changes in the right place. You can use print commands for example to see whether your changes are effective or not. – Hadi GhahremanNezhad Jul 29 '19 at 16:48
  • @EmrahKalfa how did you compile your program? Did you re-`make` the darknet after made some changes? – gameon67 Jul 30 '19 at 00:22
  • @HadiGhahremanNezhad formula used for xmin does it provides the exact coordinates of the test image . Could you please provide some reference link for the same to get only exact location of all the coordinates of the object present in image from_ext_output – insoftservice Aug 22 '21 at 18:04
2

If you want to get the coordinates of one detection you can use -ext_output flag of AlexeyAB/darknet code as @Hadi said:

./darknet detector test data/obj.data cfg/yolov4.cfg yolov4.weights -ext_output data/person.jpg

Or you can save it directly on a text file:

./darknet detector test data/obj.data cfg/yolov4.cfg yolov4.weights -ext_output data/person.jpg > output.txt

But if you have a big number of images, you need to detect them all at once and save it on a JSON file:

./darknet detector test data/obj.data cfg/yolov4.cfg yolov4.weights -ext_output -out train.json < train.txt

Where train.txt is the file where you have the directories of all your images you want to detect and train.json is the JSON file where the results are saved.

train.json file will look like this:

[
{
 "frame_id":1, 
 "filename":"data/dataset/val/dog/image.png", 
 "objects": [ 
  {"class_id":0, "name":"dog", "relative_coordinates":{"center_x":0.452191, "center_y":0.809318, "width":0.349666, "height":0.378723}, "confidence":0.418734}, 
  {"class_id":1, "name":"cat", "relative_coordinates":{"center_x":0.454491, "center_y":0.891459, "width":0.397718, "height":0.220163}, "confidence":0.024015}
 ] 
}, 
{
 "frame_id":2, 
 "filename":"data/dataset/val/dog/image2.jpg", 
 "objects": [ 
  {"class_id":0, "name":"dog", "relative_coordinates":{"center_x":0.444495, "center_y":0.539488, "width":0.297957, "height":0.307668}, "confidence":0.991456}
 ] 
}, 
...
...
]

And to access the values, you can use this code:

import json

def get_data(distros_dict):
    json_to_variable = []
    # For every frame.
    for distro in distros_dict:
        filename = distro['filename']
        if len(distro['objects']) != 0:
            # For every detection.
            for obj in range(len(distro['objects'])):
                # Get values.
                frame_id = distro['frame_id']
                class_id = distro['objects'][obj]["class_id"]
                x = distro['objects'][obj]["relative_coordinates"]["center_x"]
                y = distro['objects'][obj]["relative_coordinates"]["center_y"]
                width = distro['objects'][obj]["relative_coordinates"]["width"]
                height = distro['objects'][obj]["relative_coordinates"]["height"]
                confidence = distro['objects'][obj]["confidence"]
                # And save them.
                print(f"{frame_id} {class_id} {x} {y} {width} {height} {confidence}")
                json_to_variable.append([frame_id, class_id, x, y, width, height, confidence])

        # If you need to use json_to_variable here, move "json_to_variable = []" inside "for distro in distros_dict:"
    # Add your code here.
    # Or return json_to_variable to use it outside this function.

with open('train.json', 'r') as f:
    distros_dict_train = json.load(f)
with open('test.json', 'r') as f:
    distros_dict_test = json.load(f)
    
get_data(distros_dict_train)
get_data(distros_dict_test)

Another option is to import daknet like is mentioned here. The functions called here are the ones that you can find in the darknet.py file, but I think that the functions have been changed.