Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make the changes in darknet_images.py work? #8615

Open
LeongVan opened this issue Jul 28, 2022 · 5 comments
Open

How to make the changes in darknet_images.py work? #8615

LeongVan opened this issue Jul 28, 2022 · 5 comments

Comments

@LeongVan
Copy link

I want to get the original coordinates of detected objects. Firstly, I used the command below.

./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/images/test4.png -save_labels -dont_show -ext_output

And I got a .txt file in the same directory with source image in data/images/test4.png named data/images/test4.txt, and it looks like below.
728-2
But I want original coordinates of the objects (the pixel coordinates, before scaled), so I change the source code of writing function called save_annotations and convert2relative in darknet_images.py, showing as below.
728-3
Then, I saved the code file and ran make clean and make -j commands in terminal. After these, I delete data/images/test4.txt and ran the command below again.

./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/images/test4.png -save_labels -dont_show -ext_output

But I got the same result as I changed the code before. How can I make my changes work so that I can get original coordinates of the detected objects?

Appreciate any attempts and answers!

@LeongVan LeongVan changed the title How to make darknet_images.py work? How to make the changes in darknet_images.py work? Jul 28, 2022
@LeongVan
Copy link
Author

When I changed image_opencv.cpp and image.c in /darknet/src, and then ran make clean, make -j, I can observed the changes I make, but this do NOT works for darknet_images.py.

@bariscankurtkaya
Copy link

Hello @LeongVan ! I'm not sure. So, we will solve this problem with collaboration I guess 😄. I think you misunderstand the way Makefile works. If I'm not wrong Makefile builds the c and cpp files instead of python files. So when you change something in python and build it again the ./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/images/test4.png -save_labels -dont_show -ext_output output will not change because ./darknet is build of c and cpp files. If you want to use the command you should change the c files instead of python but you can write a python script to use the darknet_images.py file too.

So, If you want to apply the changes to the python file you need to use a python script that calls darknet_images.py but If you want to use ./darknet command you should change the c file. I hope I could explain.

@LeongVan
Copy link
Author

LeongVan commented Aug 3, 2022

Hello @LeongVan ! I'm not sure. So, we will solve this problem with collaboration I guess 😄. I think you misunderstand the way Makefile works. If I'm not wrong Makefile builds the c and cpp files instead of python files. So when you change something in python and build it again the ./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/images/test4.png -save_labels -dont_show -ext_output output will not change because ./darknet is build of c and cpp files. If you want to use the command you should change the c files instead of python but you can write a python script to use the darknet_images.py file too.

So, If you want to apply the changes to the python file you need to use a python script that calls darknet_images.py but If you want to use ./darknet command you should change the c file. I hope I could explain.

Thanks! I think you're right with how Makefile works, and I already have change the C and C++ files so that I can get what I want. And it worked. But here's the problem. If I run ./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/images/test.png -dont_show -save_labels, there is an output file called test.txt saving all the detected information, showing as below.
image
I assume the codes that write down these information are in darknet_images.py, which means that this file are called (maybe). But any changes in this file do not works. If this file is not called, how is this test.txt saved? If this file is called, why any changes to it do not work? Maybe we can figure it out together.

@bariscankurtkaya
Copy link

bariscankurtkaya commented Aug 3, 2022

Yes, I finally solved the problem @LeongVan !

You can use the #8622 branch with

./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/dog.jpg -save_labels -dont_show -ext_output

If you are curious about my adventure you can read below 🥳

I dig it up a little bit and I found a code block that checks the -save_labels flag.
You can find the code in ./src/detector.c - line 1732.

if (save_labels)
        {
            char labelpath[4096];
            replace_image_to_label(input, labelpath);

            FILE* fw = fopen(labelpath, "wb");
            int i;
            for (i = 0; i < nboxes; ++i) {
                char buff[1024];
                int class_id = -1;
                float prob = 0;
                for (j = 0; j < l.classes; ++j) {
                    if (dets[i].prob[j] > thresh && dets[i].prob[j] > prob) {
                        prob = dets[i].prob[j];
                        class_id = j;
                    }
                }
                if (class_id >= 0) {
                    sprintf(buff, "%d %2.4f %2.4f %2.4f %2.4f\n", class_id, dets[i].bbox.x, dets[i].bbox.y, dets[i].bbox.w, dets[i].bbox.h);
                    fwrite(buff, sizeof(char), strlen(buff), fw);
                }
            }
            fclose(fw);
        }

after that I looked the code and try to find where we assign the dets array. Then I found out there is a function which is creating bounding boxes. get_network_boxes You can find the function in ./src/network.c line 964.

detection *get_network_boxes(network *net, int w, int h, float thresh, float hier, int *map, int relative, int *num, int letter)
{
    detection *dets = make_network_boxes(net, thresh, num);
    fill_network_boxes(net, w, h, thresh, hier, map, relative, dets, letter);
    return dets;
}

Then as you can see It calls another function 🤣 and FINALLY we can find the main code in ./src/network.c line 814

detection *make_network_boxes(network *net, float thresh, int *num)
{
    int i;
    layer l = net->layers[net->n - 1];
    for (i = 0; i < net->n; ++i) {
        layer l_tmp = net->layers[i];
        if (l_tmp.type == YOLO || l_tmp.type == GAUSSIAN_YOLO || l_tmp.type == DETECTION || l_tmp.type == REGION) {
            l = l_tmp;
            break;
        }
    }

    int nboxes = num_detections(net, thresh);
    if (num) *num = nboxes;
    detection* dets = (detection*)xcalloc(nboxes, sizeof(detection));
    for (i = 0; i < nboxes; ++i) {
        dets[i].prob = (float*)xcalloc(l.classes, sizeof(float));
        // tx,ty,tw,th uncertainty
        if(l.type == GAUSSIAN_YOLO) dets[i].uc = (float*)xcalloc(4, sizeof(float)); // Gaussian_YOLOv3
        else dets[i].uc = NULL;

        if (l.coords > 4) dets[i].mask = (float*)xcalloc(l.coords - 4, sizeof(float));
        else dets[i].mask = NULL;

        if(l.embedding_output) dets[i].embeddings = (float*)xcalloc(l.embedding_size, sizeof(float));
        else dets[i].embeddings = NULL;
        dets[i].embedding_size = l.embedding_size;
    }
    return dets;
}

Then I realize this isn't what they want LoL 😭 So I look at the draw_detections_v3 function which is inside of the ./src/image.c line 329 and I found out a new function which is:

detection_with_class* selected_detections = get_actual_detections(dets, num, thresh, &selected_detections_num, names);

Then I refactored the whole save_labels code block and on the other hand, I added -save_labels_actual for your problem.

You can find the refactored code blocks from ./src/utils.c line 224 in #8622 branch.

@LeongVan
Copy link
Author

LeongVan commented Aug 4, 2022

BRILLIANT!!!
I'll try it out later.
THANKS!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants