车辆检测计数算法

车辆检测计数算法是一个经典的算法,可以使用目标跟踪+目标识别的方案来解决。

但是经过几天的调研后,我发现了一种简单的解决方案。

https://blog.csdn.net/taifyang/article/details/128264192

 

只需要前后两帧做一个最短路径匹配,然后利用直线与检测点是否相交,进行车辆计数。

这样的好处是显然易见的,足够简单并且依据也符合常理。

下面给出了一段我自己编写的计数函数:

复制代码
void MarkNumber(vector<vector<Detection>>& new_det, vector<vector<Detection>>& old_det,string folder,cv::Mat &img)
    {
        if (old_det.size() == 0|| new_det.size() == 0|| old_det[0].size()==0||new_det[0].size() == 0)
        {
            old_det = new_det;
            return;
        }
        vector<vector<float>> dis_matrix;
        vector<Rect> new_rct;
        vector<Rect> old_rct;

        for (const auto& detection : new_det[0])
        {
            cv::Rect temp;
            temp.x = (double)detection.bbox.x;
            temp.y = (double)detection.bbox.y;// - ori_center.y+ detection.bbox.height/2.0
            temp.height = (double)detection.bbox.height;
            temp.width = (double)detection.bbox.width;
            new_rct.push_back(temp);
        }

        for (const auto& detection : old_det[0])
        {
            cv::Rect temp;
            temp.x = (double)detection.bbox.x;
            temp.y = (double)detection.bbox.y;// - ori_center.y+ detection.bbox.height/2.0
            temp.height = (double)detection.bbox.height;
            temp.width = (double)detection.bbox.width;
            old_rct.push_back(temp);
        }

        for (int i = 0; i < new_rct.size(); i++)
        {
            vector<float> dis_vec;
            for (int j = 0; j < old_rct.size(); j++)
            {
                Point new_center = Point(new_rct[i].x + new_rct[i].width / 2, new_rct[i].y + new_rct[i].height / 2);
                Point old_center = Point(old_rct[j].x + old_rct[j].width / 2, old_rct[j].y + old_rct[j].height / 2);

                float temp_dis = sqrt(pow(new_center.x - old_center.x, 2) + pow(new_center.y - old_center.y, 2));

                dis_vec.push_back(temp_dis);
            }
            dis_matrix.push_back(dis_vec);
        }

        for (int i = 0; i < new_rct.size(); i++)
        {
            int min_index= std::min_element(dis_matrix[i].begin(), dis_matrix[i].end()) - dis_matrix[i].begin();

            if (dis_matrix[i][min_index]< max_dis && dis_matrix[i][min_index] > min_dis)
            {
                Point new_center = Point(new_rct[i].x + new_rct[i].width / 2, new_rct[i].y + new_rct[i].height / 2);
                Point old_center = Point(old_rct[min_index].x + old_rct[min_index].width / 2, old_rct[min_index].y + old_rct[min_index].height / 2);
                float tx=new_center.x - old_center.x;
                float ty = new_center.y - old_center.y;
                if (vector_x * tx + vector_y * ty > 0)
                {
                    cv::Mat A = cv::Mat::zeros(2, 2, CV_32F);
                    A.at<float>(0, 0) = old_center.y - new_center.y;
                    A.at<float>(0, 1) = new_center.x - old_center.x;
                    A.at<float>(1, 0) = line_pt[0].y - line_pt[1].y;
                    A.at<float>(1, 1) = line_pt[1].x - line_pt[0].x;

                    cv::Mat B = cv::Mat::zeros(2, 1, CV_32F);
                    B.at<float>(0, 0) = old_center.y * new_center.x - old_center.x * new_center.y;
                    B.at<float>(1, 0) = line_pt[0].y * line_pt[1].x - line_pt[0].x * line_pt[1].y;

                    cv::Mat theta = A.inv() * B;
                    float theta_x = theta.at<float>(0, 0);
                    float theta_y = theta.at<float>(1, 0);


                    if (theta_x >= min(new_center.x, old_center.x) && theta_x <= max(new_center.x, old_center.x))
                    {
                        count++;
                        imwrite(folder + "\\" + getCurrentSystemTime() + ".jpg", img);
                    }
                }
            }
        }

        auto tt = std::chrono::system_clock::to_time_t
        (std::chrono::system_clock::now());
        struct tm* ptm = new tm();
        localtime_s(ptm, &tt);
        if ((int)ptm->tm_hour ==0 && (int)ptm->tm_min == 0)
        {
            count = 0;
        }
        old_det = new_det;
    }
复制代码

 

posted @   澳大利亚树袋熊  阅读(40)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示