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

WongKinYiu/PyTorch_YOLOv4-tiny,自己数据集,类别数为1,推理加速后目标上有很多框,该怎么处理? #29

Open
xinhappy1 opened this issue Nov 19, 2022 · 10 comments

Comments

@xinhappy1
Copy link

您好!我使用您的方法yolov4-tiny-tensorrt 、您的百度网盘里的pt 和 cfg 文件,可以生成 wts、engine,执行 ./yolov4-tiny -d ../samples 命令后生成的图片正常,每个目标上只有一个框
但当我使用训练好的WongKinYiu/PyTorch_YOLOv4-tiny时,使用我的 pt和cfg文件生成wts、engine后,对我自己的部分数据集图片进行推理时,生成的图片上每个目标会有多个框,就像这样 picture。我该如何做?
期待您的回复!

@tjuskyzhang
Copy link
Owner

你看看是不是这个情况#17

您好!我使用您的方法yolov4-tiny-tensorrt 、您的百度网盘里的pt 和 cfg 文件,可以生成 wts、engine,执行 ./yolov4-tiny -d ../samples 命令后生成的图片正常,每个目标上只有一个框。 但当我使用训练好的WongKinYiu/PyTorch_YOLOv4-tiny时,使用我的 pt和cfg文件生成wts、engine后,对我自己的部分数据集图片进行推理时,生成的图片上每个目标会有多个框,就像这样 picture。我该如何做? 期待您的回复!

@xinhappy1
Copy link
Author

xinhappy1 commented Nov 21, 2022

你看看是不是这个情况#17

您好!我使用您的方法yolov4-tiny-tensorrt 、您的百度网盘里的pt 和 cfg 文件,可以生成 wts、engine,执行 ./yolov4-tiny -d ../samples 命令后生成的图片正常,每个目标上只有一个框。 但当我使用训练好的WongKinYiu/PyTorch_YOLOv4-tiny时,使用我的 pt和cfg文件生成wts、engine后,对我自己的部分数据集图片进行推理时,生成的图片上每个目标会有多个框,就像这样 picture。我该如何做? 期待您的回复!

感谢回复!我尝试过那个方法,但是不行。这是我的 cfg、yololayer.h 文件和权重文件 yolov4-tiny+tensorrt.zip

这是 yololayer.h 部分截图:
image
这是 cfg 部分截图:
image
image

针对下图中的现象您是否有好的建议?期待回复,祝好!
_1

@tjuskyzhang
Copy link
Owner

tjuskyzhang commented Nov 22, 2022

你看看是不是这个情况#17

您好!我使用您的方法yolov4-tiny-tensorrt 、您的百度网盘里的pt 和 cfg 文件,可以生成 wts、engine,执行 ./yolov4-tiny -d ../samples 命令后生成的图片正常,每个目标上只有一个框。 但当我使用训练好的WongKinYiu/PyTorch_YOLOv4-tiny时,使用我的 pt和cfg文件生成wts、engine后,对我自己的部分数据集图片进行推理时,生成的图片上每个目标会有多个框,就像这样 picture。我该如何做? 期待您的回复!

感谢回复!我尝试过那个方法,但是不行。这是我的 cfg、yololayer.h 文件和权重文件 yolov4-tiny+tensorrt.zip

这是 yololayer.h 部分截图: image 这是 cfg 部分截图: image image

针对下图中的现象您是否有好的建议?期待回复,祝好! _1

试试将yololayer.cu中188~191改成:
det->bbox[0] = (col + Logist(curInput[idx + k * info_len_i * total_grid + 0 * total_grid]) * 2 -0.5) * INPUT_W / yoloWidth;
det->bbox[1] = (row + Logist(curInput[idx + k * info_len_i * total_grid + 1 * total_grid]) * 2 -0.5) * INPUT_H / yoloHeight;
det->bbox[2] = (2 * Logist(curInput[idx + k * info_len_i * total_grid + 2 * total_grid])) * (2 * Logist(curInput[idx + k * info_len_i * total_grid + 2 * total_grid])) * anchors[2*k];
det->bbox[3] = (2 * Logist(curInput[idx + k * info_len_i * total_grid + 3 * total_grid])) * (2 * Logist(curInput[idx + k * info_len_i * total_grid + 3 * total_grid])) * anchors[2*k + 1];
从你的结果图上看目标框的分布趋势大致是正确的,一般是这的问题,不同yolo算法有点区别,可以对照训练代码再确认下,具体可以参考ultralytics/yolov5#471

@xinhappy1
Copy link
Author

xinhappy1 commented Nov 23, 2022

试试将yololayer.cu中188~191改成:
det->bbox[0] = (col + Logist(curInput[idx + k * info_len_i * total_grid + 0 * total_grid]) * 2 -0.5) * INPUT_W / yoloWidth;
det->bbox[1] = (row + Logist(curInput[idx + k * info_len_i * total_grid + 1 * total_grid]) * 2 -0.5) * INPUT_H / yoloHeight;
det->bbox[2] = (2 * Logist(curInput[idx + k * info_len_i * total_grid + 2 * total_grid])) * (2 * Logist(curInput[idx + k * info_len_i * total_grid + 2 * total_grid])) * anchors[2k];
det->bbox[3] = (2 * Logist(curInput[idx + k * info_len_i * total_grid + 3 * total_grid])) * (2 * Logist(curInput[idx + k * info_len_i * total_grid + 3 * total_grid])) * anchors[2
k + 1];
从你的结果图上看目标框的分布趋势大致是正确的,一般是这的问题,不同yolo算法有点区别,可以对照训练代码再确认下,具体可以参考ultralytics/yolov5#471

非常感谢!修改后识别效果很好,起作用了。[抱拳][抱拳][抱拳]

@xinhappy1
Copy link
Author

还有一个问题,我该怎么去推理加速视频文件?我试过 ./yolov4-tiny -d the/path/of/my/video 这个命令,但是报错了。报错信息如下:
image

@tjuskyzhang
Copy link
Owner

还有一个问题,我该怎么去推理加速视频文件?我试过 ./yolov4-tiny -d the/path/of/my/video 这个命令,但是报错了。报错信息如下: image

视频的话可以基于OpenCV VideoCapture读视频的每一帧进行推理

@xinhappy1
Copy link
Author

视频的话可以基于OpenCV VideoCapture读视频的每一帧进行推理

感谢回复!可以实现直接对视频进行推理吗?如果需要修改您的代码来达到这个目的,我该在哪个文件里哪个部分进行修改呢?

@tjuskyzhang
Copy link
Owner

视频的话可以基于OpenCV VideoCapture读视频的每一帧进行推理

感谢回复!可以实现直接对视频进行推理吗?如果需要修改您的代码来达到这个目的,我该在哪个文件里哪个部分进行修改呢?

可以,通过OpenCV VideoCapture读每一帧得到cv::Mat,等效cv::imread读一张图像得到cv::Mat

@xinhappy1
Copy link
Author

xinhappy1 commented Nov 23, 2022

感谢回复!可以实现直接对视频进行推理吗?如果需要修改您的代码来达到这个目的,我该在哪个文件里哪个部分进行修改呢?

可以,通过OpenCV VideoCapture读每一帧得到cv::Mat,等效cv::imread读一张图像得到cv::Mat

请问是在 yolov4-tiny.cpp 的 main 函数里进行修改吗?具体修改位置是?
yolov4-tiny.cpp 的 main 函数:

int main(int argc, char** argv) {
    cudaSetDevice(DEVICE);
    // create a model using the API directly and serialize it to a stream
    char *trtModelStream{nullptr};
    size_t size{0};

    if (argc == 2 && std::string(argv[1]) == "-s") {
        IHostMemory* modelStream{nullptr};
        APIToModel(BATCH_SIZE, &modelStream);
        assert(modelStream != nullptr);
        std::ofstream p("yolov4-tiny.engine", std::ios::binary);
        if (!p) {
            std::cerr << "could not open plan output file" << std::endl;
            return -1;
        }
        p.write(reinterpret_cast<const char*>(modelStream->data()), modelStream->size());
        modelStream->destroy();
        return 0;
    } else if (argc == 3 && std::string(argv[1]) == "-d") {
        std::ifstream file("yolov4-tiny.engine", std::ios::binary);
        if (file.good()) {
            file.seekg(0, file.end);
            size = file.tellg();
            file.seekg(0, file.beg);
            trtModelStream = new char[size];
            assert(trtModelStream);
            file.read(trtModelStream, size);
            file.close();
        }
    } else {
        std::cerr << "arguments not right!" << std::endl;
        std::cerr << "./yolov4-tiny -s  // serialize model to plan file" << std::endl;
        std::cerr << "./yolov4-tiny -d ../samples  // deserialize plan file and run inference" << std::endl;
        return -1;
    }

    std::vector<std::string> file_names;
    if (read_files_in_dir(argv[2], file_names) < 0) {
        std::cout << "read_files_in_dir failed." << std::endl;
        return -1;
    }

    // prepare input data ---------------------------
    static float data[BATCH_SIZE * 3 * INPUT_H * INPUT_W];
    //for (int i = 0; i < 3 * INPUT_H * INPUT_W; i++)
    //    data[i] = 1.0;
    static float prob[BATCH_SIZE * OUTPUT_SIZE];
    IRuntime* runtime = createInferRuntime(gLogger);
    assert(runtime != nullptr);
    ICudaEngine* engine = runtime->deserializeCudaEngine(trtModelStream, size);
    assert(engine != nullptr);
    IExecutionContext* context = engine->createExecutionContext();
    assert(context != nullptr);
    delete[] trtModelStream;

    int fcount = 0;
    for (int f = 0; f < (int)file_names.size(); f++) {
        fcount++;
        if (fcount < BATCH_SIZE && f + 1 != (int)file_names.size()) continue;
        for (int b = 0; b < fcount; b++) {
            cv::Mat img = cv::imread(std::string(argv[2]) + "/" + file_names[f - fcount + 1 + b]);
            if (img.empty()) continue;
            cv::Mat pr_img = preprocess_img(img);
            for (int i = 0; i < INPUT_H * INPUT_W; i++) {
                data[b * 3 * INPUT_H * INPUT_W + i] = pr_img.at<cv::Vec3b>(i)[2] / 255.0;
                data[b * 3 * INPUT_H * INPUT_W + i + INPUT_H * INPUT_W] = pr_img.at<cv::Vec3b>(i)[1] / 255.0;
                data[b * 3 * INPUT_H * INPUT_W + i + 2 * INPUT_H * INPUT_W] = pr_img.at<cv::Vec3b>(i)[0] / 255.0;
            }
        }

        // Run inference
        auto start = std::chrono::system_clock::now();
        doInference(*context, data, prob, BATCH_SIZE);
        auto end = std::chrono::system_clock::now();
        std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
        std::vector<std::vector<Yolo::Detection>> batch_res(fcount);
        for (int b = 0; b < fcount; b++) {
            auto& res = batch_res[b];
            nms(res, &prob[b * OUTPUT_SIZE]);
        }
        for (int b = 0; b < fcount; b++) {
            auto& res = batch_res[b];
            //std::cout << res.size() << std::endl;
            cv::Mat img = cv::imread(std::string(argv[2]) + "/" + file_names[f - fcount + 1 + b]);
            for (size_t j = 0; j < res.size(); j++) {
                //float *p = (float*)&res[j];
                //for (size_t k = 0; k < 7; k++) {
                //    std::cout << p[k] << ", ";
                //}
                //std::cout << std::endl;
                cv::Rect r = get_rect(img, res[j].bbox);
                cv::rectangle(img, r, cv::Scalar(0x27, 0xC1, 0x36), 2);
                cv::putText(img, std::to_string((int)res[j].class_id), cv::Point(r.x, r.y - 1), cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(0xFF, 0xFF, 0xFF), 2);
            }
            cv::imwrite("_" + file_names[f - fcount + 1 + b], img);
        }
        fcount = 0;
    }

    // Destroy the engine
    context->destroy();
    engine->destroy();
    runtime->destroy();

    //Print histogram of the output distribution
    //std::cout << "\nOutput:\n\n";
    //for (unsigned int i = 0; i < OUTPUT_SIZE; i++)
    //{
    //    std::cout << prob[i] << ", ";
    //    if (i % 10 == 0) std::cout << i / 10 << std::endl;
    //}
    //std::cout << std::endl;

    return 0;
}

@HelloWorld12369
Copy link

请问是在 yolov4-tiny.cpp 的 main 函数里进行修改吗?具体修改位置是?
yolov4-tiny.cpp 的 main 函数:

I have the same question. Can you give some guidelines on how to modify it? @tjuskyzhang

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

3 participants