chooseTarget

本函数是循环candidateArmors容器 推理numROIs容器内所有数字将推理结果,置信度,ID传入get_max() 更新装甲板的置信度和ID将符合要求的装甲板放入finalArmors容器

这个函数是非常重要的一个函数,可以直接判断装甲板的正确与否(通过数字识别),同时对装甲板的击打策略进行调整

    if(candidateArmors.empty())
    {
        //cout<<"no target!!"<<endl;
        return;
    }

空容器检测,不可或缺的异常检测机制


单个装甲板的检测机制,分数直接打满,DNN推理是采用onnx模型,这里简单介绍一些数字识别的部分

数字识别的实现方法较多,我们采用机器学习的方法,数字识别主要是一种图像分类的问题,使用SVM、聚类算法、神经网络均可以实现

数字识别的训练我们通常会使用Python来进行,Pytorch框架是目前非常流行的一套深度学习框架,搭配Numpy我们可以轻松实现非常多的东西

我们使用 Pytorch 搭建出来的模型通常是 pt 格式,无法在C++下使用,但是有一种通用的模型结构 onnx

因为深度学习的框架和模型格式过多和杂,所以推出了一种标准的格式,也就是 onnx ,其允许在不同的深度框架之间使用

通过 onnx 模型,我们就可以轻松实现模型的部署,从而实现数字识别

如果你对机器学习、深度学习部分有一定的兴趣,可以观看最后的数字识别篇章

将会告诉你部分机器学习、深度学习的知识,同时给出深度学习的部分学习方法

不感兴趣可以直接跳过,不要求一定掌握数字识别部分

    else if(candidateArmors.size() == 1)
    {
//        cout<<"get 1 target!!"<<endl;

        // DNN推理
        Mat out_blobs = Dnn_Detect.net_forward(numROIs);
        float *outs = (float*)out_blobs.data;

        if (get_max(outs, candidateArmors[0].confidence, candidateArmors[0].id))
        {
#ifdef SHOW_NUMROI
            cv::Mat numDst;
            resize(numROIs[0],numDst,Size(200,300));
            string name = to_string(candidateArmors[0].id) + ":" + to_string(candidateArmors[0].confidence*100) + "%";
//            namedWindow("name",WINDOW_NORMAL);
            imshow("name",numDst);
//            printf("%d",armor.id);
//            std::cout<<"number:   "<<armor.id<<"   type:   "<<armor.type<<std::endl;
//            string file_name = "../data/"+std::to_string(0)+"_"+std::to_string(cnt_count)+".jpg";
//            cout<<file_name<<endl;
//            imwrite(file_name,numDst);
//            cnt_count++;
#endif
            // 一个装甲板分数直接打满
            candidateArmors[0].grade = 100;
            finalArmors.emplace_back(candidateArmors[0]);
        }
    }

这里通过数字识别的方法得到装甲板的ID

bool ArmorDetector::get_max(const float *data, float &confidence, int &id)
{
    // 默认初始化
    confidence = data[0];
    id = 0;
    // 寻找最大置信度的ID
    for (int i=0;i<categories;i++)
    {
        if (data[i] > confidence)
        {
            confidence = data[i];
            id = i;
        }
    }
    // 如果id为0或者id为2(工程) | 置信度小于阈值
    if(id == 0 || id == 2 || confidence < thresh_confidence)
        return false;
    else
        return true;
}

get_max函数是对模型的推导结果进行判断,得到最大置信度的ID,同时在这里会将工程机器人和错误ID进行删除

这意味着我们将不会对工程机器人进行锁定


int ArmorDetector::armorGrade(const Armor& checkArmor)
{
    /////////id优先级打分项目////////////////////////
    int id_grade;
    int check_id = checkArmor.id;
    id_grade = check_id == 1 ? 100 : 80;
    ////////end///////////////////////////////////

    /////////最大装甲板板打分项目/////////////////////
    // 最大装甲板,用面积,找一个标准值(固定距离(比如3/4米),装甲板大小(Armor.area)大约是多少,分大小装甲板)
    // 比标准大就是100,小就是做比例,,,,可能小的得出来的值会很小
    int height_grade;
    double hRotation = checkArmor.size.height / height_standard;
    if(candidateArmors.size()==1)  hRotation=1;
    height_grade = hRotation * 60;
    //////////end/////////////////////////////////

    ////////靠近图像中心打分项目//////////////////////
    // 靠近中心,与中心做距离,设定标准值,看图传和摄像头看到的画面的差异
    int near_grade;
    double pts_distance = POINT_DIST(checkArmor.center, Point2f(_src.cols * 0.5, _src.rows * 0.5));
    near_grade = pts_distance/near_standard < 1 ? 100 : (near_standard/pts_distance) * 100;
    ////////end//////////////////////////////////

    // 下面的系数得详细调节;
    int final_grade = id_grade * id_grade_ratio +
                      height_grade  * height_grade_ratio +
                      near_grade  * near_grade_ratio;

    return final_grade;
}

armorGrade 函数是装甲板的打分策略,我们通过ID、装甲板面积大小、与图像的中心距离来进行打分

选出我们认为当前最好的一个装甲板,为后续装甲板的锁定做准备

到此,整个识别的流程基本结束,其中一些不展开讲解的细节,例如数字识别(非必须掌握)、Number_DNN

将会在后面展开讲解

results matching ""

    No results matching ""