当前位置:   article > 正文

c++ iou学习笔记_图像交并比代码c++

图像交并比代码c++

以下内容转自:

图像处理之IOU, NMS原理及C++实现 - 灰信网(软件开发博客聚合)

1. IOU

交并比(Intersection-over-Union,IoU),目标检测中使用的一个概念,是产生的候选框(candidate bound)与原标记框(ground truth bound)的交叠率,即它们的交集与并集的比值。最理想情况是完全重叠,即比值为1。


计算公式:


C++代码:

opencv:

  1. float bbOverlap(const cv::Rect_<float>& box1,const cv::Rect_<float>& box2)
  2. {
  3. if (box1.x > box2.x+box2.width) { return 0.0; }
  4. if (box1.y > box2.y+box2.height) { return 0.0; }
  5. if (box1.x+box1.width < box2.x) { return 0.0; }
  6. if (box1.y+box1.height < box2.y) { return 0.0; }
  7. float colInt = min(box1.x+box1.width,box2.x+box2.width) - max(box1.x, box2.x);
  8. float rowInt = min(box1.y+box1.height,box2.y+box2.height) - max(box1.y,box2.y);
  9. float intersection = colInt * rowInt;
  10. float area1 = box1.width*box1.height;
  11. float area2 = box2.width*box2.height;
  12. return intersection / (area1 + area2 - intersection);
  13. }

自定义结构:

  1. struct bbox
  2. {
  3. int m_left;
  4. int m_top;
  5. int m_width;
  6. int m_height;
  7. bbox() {}
  8. bbox(int left, int top, int width, int height)
  9. {
  10. m_left = left;
  11. m_top = top;
  12. m_width = width;
  13. m_height = height;
  14. }
  15. };
  16. float IOU_compute(const bbox b1, const bbox b2)
  17. {
  18. w = max(min((b1.m_left + b1.m_width), (b2.m_left + b2.m_width)) - max(b1.m_left, b2.m_left), 0);
  19. h = max(min((b1.m_top + b1.m_height), (b2.m_top + b2.m_height)) - max(b1.m_top, b2.m_top), 0);
  20. return w*h / (b1.m_width*b1.m_height + b2.m_width*b2.m_height - w*h);
  21. }

3维目标检测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分别是立方体长宽高的一半。

原文链接:https://blog.csdn.net/qq_27399933/article/details/110876763

  1. bool bInBox(const vector<cv::Point2f> &vpBoxA, const cv::Point2f &p)
  2. {
  3. std::vector<cv::Point2f> corners = vpBoxA;
  4. for(int i = 0; i<vpBoxA.size(); i++) //01230123
  5. corners.push_back(vpBoxA[i]);
  6. std::vector< std::vector<double> > linesA;
  7. for(int i = 0; i<vpBoxA.size(); i++)
  8. {
  9. cv::Point2f p1 = corners[i];
  10. cv::Point2f p2 = corners[i+1];
  11. cv::Point2f p3 = corners[i+2];
  12. double a;
  13. if(p1.x - p2.x == 0)
  14. a = -(p1.y - p2.y)/0.0001;
  15. else
  16. a = -(p1.y - p2.y)/(p1.x - p2.x);
  17. double b = 1;
  18. double c = -a * p2.x - p2.y;
  19. double d = a*p3.x + b*p3.y + c;
  20. std::vector<double> line{a,b,c,d};
  21. linesA.push_back(line);
  22. }
  23. for(int i=0; i<linesA.size(); i++)
  24. {
  25. vector<double > l = linesA[i];
  26. double y = l[0] * p.x + l[1] * p.y +l[2];
  27. if(y * l[3] < 0)
  28. return false;
  29. }
  30. return true;
  31. }
  32. double InterSection_2D(const vector<cv::Point2f> &vpBoxA, const vector<cv::Point2f> &vpBoxB)
  33. {
  34. double min_x, max_x, min_y, max_y;
  35. min_x = vpBoxA[0].x;
  36. max_x = vpBoxA[0].x;
  37. min_y = vpBoxA[0].y;
  38. max_y = vpBoxA[0].y;
  39. for(int i=1; i<vpBoxA.size(); i++)
  40. {
  41. cv::Point2f p = vpBoxA[i];
  42. if(p.x > max_x)
  43. max_x = p.x;
  44. if(p.x < min_x)
  45. min_x = p.x;
  46. if(p.y > max_y)
  47. max_y = p.y;
  48. if(p.y < min_y)
  49. min_y = p.y;
  50. }
  51. for(int i=0; i<vpBoxB.size(); i++)
  52. {
  53. cv::Point2f p = vpBoxB[i];
  54. if(p.x > max_x)
  55. max_x = p.x;
  56. if(p.x < min_x)
  57. min_x = p.x;
  58. if(p.y > max_y)
  59. max_y = p.y;
  60. if(p.y < min_y)
  61. min_y = p.y;
  62. }
  63. //将两个BBox的定点坐标最小值设置为0, 以防止有负数的产生
  64. vector<cv::Point2f> vpBoxAA = vpBoxA;
  65. vector<cv::Point2f> vpBoxBB = vpBoxB;
  66. //if(min_x < 0 && min_y < 0)
  67. for(int i=0; i<vpBoxA.size(); i++)
  68. {
  69. vpBoxAA[i].x = vpBoxAA[i].x - min_x;
  70. vpBoxAA[i].y = vpBoxAA[i].y - min_y;
  71. vpBoxBB[i].x = vpBoxBB[i].x - min_x;
  72. vpBoxBB[i].y = vpBoxBB[i].y - min_y;
  73. }
  74. int imax_x = (int)((max_x - min_x) * 10000);
  75. int imax_y = (int)((max_y - min_y) * 10000);
  76. double points_inA = 0, points_inB = 0, points_inAB = 0;
  77. srand((int)time(0));
  78. for(int i = 0; i<100000; i++)
  79. {
  80. int xx = rand()%(imax_x)+1; //生成[1, imax_x]之间的整数
  81. int yy = rand()%(imax_y)+1; //生成[1, imax_y]之间的整数
  82. cv::Point2f p((float)xx / 10000.0, (float)yy / 10000.0);
  83. if( bInBox(vpBoxAA, p) )
  84. ++points_inA;
  85. if( bInBox(vpBoxBB, p) )
  86. ++points_inB;
  87. if( bInBox(vpBoxAA, p) && bInBox(vpBoxBB, p) )
  88. ++points_inAB;
  89. }
  90. double iou = points_inAB / (points_inA + points_inB - points_inAB);
  91. //cout<<"points_inA : "<<points_inA<<", points_inB: "<<points_inB<<" ,points_inAB: "<<points_inAB<<endl;
  92. return iou;
  93. }
  94. double CuboidIoU(const Eigen::MatrixXd &truth_poses, const Eigen::MatrixXd &landmark_poses)
  95. {
  96. std::vector<cv::Point2f> vground_points;
  97. std::vector<cv::Point2f> vlandmark_points;
  98. if(1) //通过坐标旋转求取groundtruth立方体中 2D-Boundbox四个顶点的坐标
  99. {
  100. double cen_x = truth_poses(0,0);
  101. double cen_y = truth_poses(0,1);
  102. double len = truth_poses(0,6);
  103. double wid = truth_poses(0,7);
  104. double yaw = truth_poses(0,5);
  105. double x, y, xx, yy;
  106. x = cen_x - len;
  107. y = cen_y - wid;
  108. xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
  109. yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
  110. cv::Point2f p0(xx, yy);
  111. x = cen_x - len;
  112. y = cen_y + wid;
  113. xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
  114. yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
  115. cv::Point2f p1(xx, yy);
  116. x = cen_x + len;
  117. y = cen_y + wid;
  118. xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
  119. yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
  120. cv::Point2f p2(xx, yy);
  121. x = cen_x + len;
  122. y = cen_y - wid;
  123. xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
  124. yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
  125. cv::Point2f p3(xx, yy);
  126. vground_points = {p0, p1, p2, p3};
  127. }
  128. if(1)//通过坐标旋转求取landmark中 2D-Boundbox四个顶点的坐标
  129. {
  130. double cen_x = landmark_poses(0,0);
  131. double cen_y = landmark_poses(0,1);
  132. double len = landmark_poses(0,6);
  133. double wid = landmark_poses(0,7);
  134. double yaw = landmark_poses(0,5);
  135. double x, y, xx, yy;
  136. x = cen_x - len;
  137. y = cen_y - wid;
  138. xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
  139. yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
  140. cv::Point2f p0(xx, yy);
  141. x = cen_x - len;
  142. y = cen_y + wid;
  143. xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
  144. yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
  145. cv::Point2f p1(xx, yy);
  146. x = cen_x + len;
  147. y = cen_y + wid;
  148. xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
  149. yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
  150. cv::Point2f p2(xx, yy);
  151. x = cen_x + len;
  152. y = cen_y - wid;
  153. xx = (x - cen_x)*cos(yaw) - (y - cen_y)*sin(yaw) + cen_x;
  154. yy = (x - cen_x)*sin(yaw) + (y - cen_y)*cos(yaw) + cen_y;
  155. cv::Point2f p3(xx, yy);
  156. vlandmark_points = {p0, p1, p2, p3};
  157. }
  158. double iou_2d = InterSection_2D(vlandmark_points, vground_points);
  159. double iou_3d = 0;
  160. if (iou_2d > 0) {
  161. double tru_minz = truth_poses(0, 2) - truth_poses(0, 8);
  162. double tru_maxz = truth_poses(0, 2) + truth_poses(0, 8);
  163. double land_minz = landmark_poses(0, 2) - landmark_poses(0, 8);
  164. double land_maxz = landmark_poses(0, 2) + landmark_poses(0, 8);
  165. if (land_maxz < tru_maxz && land_maxz > tru_minz) {
  166. double height_iou = (land_maxz - tru_minz) / (tru_maxz - land_minz);
  167. iou_3d = iou_2d * height_iou;
  168. } else if (tru_maxz < land_maxz && tru_maxz > land_minz) {
  169. double height_iou = (tru_maxz - land_minz) / (land_maxz - tru_minz);
  170. iou_3d = iou_2d * height_iou;
  171. }
  172. }
  173. return iou_3d;
  174. }
  175. void main(int argc, char **argv)
  176. {
  177. Eigen::MatrixXd truth_poses(1,9);
  178. truth_poses<<-0.4875, -0.798913, -1.125, 0, 0, -1.27409, 0.240477, 0.235315, 0.375;
  179. Eigen::MatrixXd landmark_poses(1,9);
  180. landmark_poses<<-0.506616, -0.796303, -1.20499, 0, 0, -0.345443, 0.22, 0.22, 0.4 ;
  181. double iou_3d = CuboidIoU_once(truth_poses, landmark_poses);
  182. cout<<"the iou of two cuboid is: "<<iou_3d<<endl;
  183. return;
  184. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/114096?site
推荐阅读
相关标签
  

闽ICP备14008679号