车辆检测计数算法

发布时间 2023-12-11 10:27:47作者: 澳大利亚树袋熊

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

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

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

 

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

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

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

void MarkNumber(vector<vector<Detection>> &new_det, vector<vector<Detection>> &old_det)
    {
        if (old_det.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[1].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(line_pt[0].x, line_pt[1].x) && theta_y >= min(line_pt[0].y, line_pt[1].y) && theta_x <= max(line_pt[0].x, line_pt[1].x) && theta_y <= max(line_pt[0].y, line_pt[1].y))
                    {
                        count++;
                    }
                }
            }
        }


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


    }