当前位置:   article > 正文

三维目标检测中IoU的计算(C++实现)_c++计算目标检测iou

c++计算目标检测iou

一、三维目标表示
世界坐标系下的三维目标有9个自由度,分别为三个自由度的平移量(中心点坐标){x,y,z},三自由度的旋转{roll, pitch, yaw},三自由度的尺寸{length,width,height}。通常假设物体都是水平放置,所以roll = 0,pitch = 0;因此一个立方体可以表示为{x,y,z,0,0,yaw,len,wid,hei}。其中len、wid、hei分别是立方体长宽高的一半。
三、代码实现

bool bInBox(const vector<cv::Point2f> &vpBoxA, const cv::Point2f &p)
{
    std::vector<cv::Point2f> corners = vpBoxA;
    for(int i = 0; i<vpBoxA.size(); i++)   //01230123
        corners.push_back(vpBoxA[i]);

    std::vector< std::vector<double> > linesA;
    for(int i = 0; i<vpBoxA.size(); i++)
    {
        cv::Point2f p1 = corners[i];
        cv::Point2f p2 = corners[i+1];
        cv::Point2f p3 = corners[i+2];
        double a;
        if(p1.x - p2.x == 0)
            a = -(p1.y - p2.y)/0.0001;
        else
            a = -(p1.y - p2.y)/(p1.x - p2.x);

        double b = 1;
        double c = -a * p2.x - p2.y;
        double d = a*p3.x + b*p3.y + c;

        std::vector<double> line{a,b,c,d};
        linesA.push_back(line);
    }

    for(int i=0; i<linesA.size(); i++)
    {
        vector<double > l = linesA[i];
        double y = l[0] * p.x + l[1] * p.y +l[2];
        if(y * l[3] < 0)
            return false;
    }
    return true;
}

double InterSection_2D(const vector<cv::Point2f> &vpBoxA, const vector<cv::Point2f> &vpBoxB)
{
    double min_x, max_x, min_y, max_y;
    min_x = vpBoxA[0].x;
    max_x = vpBoxA[0].x;
    min_y = vpBoxA[0].y;
    max_y = vpBoxA[0].y;

    for(int i=1; i<vpBoxA.size(); i++)
    {
        cv::Point2f p = vpBoxA[i];
        if(p.x > max_x)
            max_x = p.x;
        if(p.x < min_x)
            min_x = p.x;
        if(p.y > max_y)
            max_y = p.y;
        if(p.y < min_y)
            min_y = p.y;
    }
    for(int i=0; i<vpBoxB.size(); i++)
    {
        cv::Point2f p = vpBoxB[i];
        if(p.x > max_x)
            max_x = p.x;
        if(p.x < min_x)
            min_x = p.x;
        if(p.y > max_y)
            max_y = p.y;
        if(p.y < min_y)
            min_y = p.y;
    }

    //将两个BBox的定点坐标最小值设置为0, 以防止有负数的产生
    vector<cv::Point2f> vpBoxAA = vpBoxA;
    vector<cv::Point2f> vpBoxBB = vpBoxB;

    //if(min_x < 0 && min_y < 0)
    for(int i=0; i<vpBoxA.size(); i++)
    {
        vpBoxAA[i].x = vpBoxAA[i].x - min_x;
        vpBoxAA[i].y = vpBoxAA[i].y - min_y;
        vpBoxBB[i].x = vpBoxBB[i].x - min_x;
        vpBoxBB[i].y = vpBoxBB[i].y - min_y;
    }

    int imax_x = (int)((max_x - min_x) * 10000);
    int imax_y = (int)((max_y - min_y) * 10000);

    double points_inA = 0, points_inB = 0, points_inAB = 0;
    srand((int)time(0));
    for(int i = 0; i<100000; i++)
    {
        int xx = rand()%(imax_x)+1;  //生成[1, imax_x]之间的整数
        int yy = rand()%(imax_y)+1;  //生成[1, imax_y]之间的整数

        cv::Point2f p((float)xx / 10000.0, (float)yy / 10000.0);
        if( bInBox(vpBoxAA, p) )
            ++points_inA;
        if( bInBox(vpBoxBB, p) )
            ++points_inB;
        if( bInBox(vpBoxAA, p) && bInBox(vpBoxBB, p) )
            ++points_inAB;
    }

    double iou = points_inAB / (points_inA + points_inB - points_inAB);
    //cout<<"points_inA : "<<points_inA<<",  points_inB: "<<points_inB<<" ,points_inAB: "<<points_inAB<<endl;
    return iou;
}
double CuboidIoU(const Eigen::MatrixXd &truth_poses, const Eigen::MatrixXd &landmark_poses)
{

    std::vector<cv::Point2f>  vground_points;
    std::vector<cv::Point2f>  vlandmark_points;
    if(1)  //通过坐标旋转求取groundtruth立方体中 2D-Boundbox四个顶点的坐标
    {
        double cen_x = truth_poses(0,0);
        double cen_y = truth_poses(0,1);
        double len = truth_poses(0,6);
        double wid = truth_poses(0,7);
        double yaw = truth_poses(0,5);

        double x, y, xx, yy;
        x = cen_x - len;
        y = cen_y - wid;
        xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
        yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
        cv::Point2f p0(xx, yy);

        x = cen_x - len;
        y = cen_y + wid;
        xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
        yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
        cv::Point2f p1(xx, yy);

        x = cen_x + len;
        y = cen_y + wid;
        xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
        yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
        cv::Point2f p2(xx, yy);

        x = cen_x + len;
        y = cen_y - wid;
        xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
        yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
        cv::Point2f p3(xx, yy);

        vground_points = {p0, p1, p2, p3};
    }

    if(1)//通过坐标旋转求取landmark中 2D-Boundbox四个顶点的坐标
    {
        double cen_x = landmark_poses(0,0);
        double cen_y = landmark_poses(0,1);
        double len = landmark_poses(0,6);
        double wid = landmark_poses(0,7);
        double yaw = landmark_poses(0,5);

        double x, y, xx, yy;
        x = cen_x - len;
        y = cen_y - wid;
        xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
        yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
        cv::Point2f p0(xx, yy);

        x = cen_x - len;
        y = cen_y + wid;
        xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
        yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
        cv::Point2f p1(xx, yy);

        x = cen_x + len;
        y = cen_y + wid;
        xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
        yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
        cv::Point2f p2(xx, yy);

        x = cen_x + len;
        y = cen_y - wid;
        xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
        yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
        cv::Point2f p3(xx, yy);

        vlandmark_points = {p0, p1, p2, p3};
    }

    double iou_2d = InterSection_2D(vlandmark_points, vground_points);
    double iou_3d = 0;
    if (iou_2d > 0) {
        double tru_minz = truth_poses(0, 2) - truth_poses(0, 8);
        double tru_maxz = truth_poses(0, 2) + truth_poses(0, 8);

        double land_minz = landmark_poses(0, 2) - landmark_poses(0, 8);
        double land_maxz = landmark_poses(0, 2) + landmark_poses(0, 8);

        if (land_maxz < tru_maxz && land_maxz > tru_minz) {
            double height_iou = (land_maxz - tru_minz) / (tru_maxz - land_minz);
            iou_3d = iou_2d * height_iou;
        } else if (tru_maxz < land_maxz && tru_maxz > land_minz) {
            double height_iou = (tru_maxz - land_minz) / (land_maxz - tru_minz);
            iou_3d = iou_2d * height_iou;
        }
    }

    return iou_3d;
}


void main(int argc, char **argv)
{
    Eigen::MatrixXd truth_poses(1,9);
    truth_poses<<-0.4875, -0.798913, -1.125, 0, 0, -1.27409, 0.240477, 0.235315, 0.375;
    Eigen::MatrixXd landmark_poses(1,9);
    landmark_poses<<-0.506616, -0.796303, -1.20499, 0, 0, -0.345443, 0.22,  0.22, 0.4 ;
    double iou_3d = CuboidIoU_once(truth_poses, landmark_poses);
    cout<<"the iou of two cuboid is: "<<iou_3d<<endl;
    return;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/114100
推荐阅读
相关标签
  

闽ICP备14008679号