dme-compunet / YoloV8

Use YOLOv8 in real-time, for object detection, instance segmentation, pose estimation and image classification, via ONNX Runtime.
https://www.nuget.org/packages/YoloV8
GNU Affero General Public License v3.0
241 stars 45 forks source link

There are false positives occurring in the detection task #13

Closed FunJoo closed 1 year ago

FunJoo commented 1 year ago

I have a project about "Identifying Vessels in Ultrasound Imaging", but when using the code from this repository, I encountered false positives. It mistakenly identifies the topmost and bottommost parts of the image as vessels. 001

However, when I predict using the python YOLOv8 or other YOLOv8-C#Onnx repositories, there are no false positives. 002

I can provide test images and the .onnx model ( 331 .jpg images, 1 .onnx file, 170MB). Can you help analyze where the issue might be? I will continue to look into this over the next few days, as I need to push forward with this project.

The image below is from my training dataset. The aforementioned false positives are where the topmost and bottommost parts of the image are identified as this type: 003

FunJoo commented 1 year ago

I compared the source code of this repository with sstainba/Yolov8.Net and noticed a difference here. You've used padding. What's the purpose of this padding? Could this be the reason for the false positives? 004

FunJoo commented 1 year ago

My test image has an original resolution of 1280x960, my model size is 640x640.

In this repository, after resizing, my test image is 640x480, and through breakpoint inspection, I found the yPadding used is 80. 005

I noticed that sstainba/Yolov8.Net's approach during preprocessing is to directly resize my test image to 640x640 and then scale the bounding boxes in the output to correspond to the original dimensions and size. 007 006

dme-compunet commented 1 year ago

The purpose of padding is to improve the results, because when the aspect ratio remains the same as the original image the predictions are more accurate.

It would be good if you give me a minimal way to reproduce the problem at my, and I hope I can fix it soon

FunJoo commented 1 year ago

@dme-compunet I think sending you my .onnx model and test images for testing would be the most straightforward. You can compare the results from running this repository to those from running python YOLOv8. How would you recommend receiving the images? Via e-mail, OneDrive/Google Drive, or is there a file-sharing website you'd recommend?

dme-compunet commented 1 year ago

@FunJoo Google Drive is excellent for me

FunJoo commented 1 year ago

@dme-compunet https://drive.google.com/drive/folders/1to6dEr7hXMTRaoOtAH-iyDZjcC2aU4OU?usp=sharing

dme-compunet commented 1 year ago

@FunJoo a temporary solution for you is to change the YoloV8.Preprocess method to something like this:

private Tensor<float> Preprocess(Image<Rgb24> image)
{
    var modelSize = _metadata.ImageSize;

    var ratio = Math.Min((float)modelSize.Width / image.Width, (float)modelSize.Height / image.Height);

    var processSize = new Size((int)(image.Width * ratio), (int)(image.Height * ratio));

    var xPadding = (modelSize.Width - processSize.Width) / 2;
    var yPadding = (modelSize.Height - processSize.Height) / 2;

    image.Mutate(x => x.Resize(processSize));

    var dimensions = new int[] { 1, 3, modelSize.Height, modelSize.Width };
    var input = new DenseTensor<float>(dimensions);

    input.Fill(1f); // fill padding background with white color

    image.ForEachPixel((point, pixel) =>
    {
        var x = point.X + xPadding;
        var y = point.Y + yPadding;

        var r = pixel.R / 255f;
        var g = pixel.G / 255f;
        var b = pixel.B / 255f;

        input[0, 0, y, x] = r;
        input[0, 1, y, x] = g;
        input[0, 2, y, x] = b;
    });

    return input;
}

(the input.Fill(1f); was added)

Your problem was that the model predicted the black padding as a vessels, maybe the right solution is to padding the image with a stretch of the last row of pixels to the end, in addition to adding PreprocessWithAspectRatio property to YoloV8Parameters that will give the possibility to perform pre-processing without the use of padding.

FunJoo commented 1 year ago

@dme-compunet Thank you, I will take this as my temporary solution. It indeed avoids the false positives, but the preprocessing adds 20~40 milliseconds.

dme-compunet commented 1 year ago

@FunJoo I updated the repo, now the default is processing without keeping original aspect ratios, to process with original aspect ratios (sometimes improves the prediction results) you need to change the ProcessWithOriginalAspectRatio property in YoloV8Parameters to true

FunJoo commented 1 year ago

@dme-compunet I've already updated and successfully implemented it. Thank you so much :)