LeetCode高频题:图像交并比IoU计算方法和手撕代码
提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目
互联网大厂们在公司养了一大批ACM竞赛的大佬们,吃完饭就是设计考题,然后去考应聘人员,你要做的就是学基础树结构与算法,然后打通任督二脉,以应对波云诡谲的大厂笔试面试题!
你要是不扎实学习数据结构与算法,好好动手手撕代码,锻炼解题能力,你可能会在笔试面试过程中,连题目都看不懂!比如华为,字节啥的,足够让你读不懂题
题目
请你说说iou怎么计算的,写出iou的计算方法
一、审题
示例:
给你的俩矩阵的下标为:
rect1:左上角x1,y1,右下角x2,y2
rect2:左上角a1,b1,右下角a2,b2
这个题经常在互联网大厂的笔试面试中出现
很简单的思想
啥是iou?
IoU,即 intersection over Union,
就是两个矩形框的交集面积与他们并集面积的比值。
(其实也不一定是矩形框,这里以矩形框进行说明)
IoU也是一种算法性能的指标,例如在语义分割时就会用IoU来衡量分割效果的好坏。
举例说明,如下图所示:
给你的输入是俩数组:
rect1:左上角x1,y1,右下角x2,y2【分别是0123位置】
rect2:左上角a1,b1,右下角a2,b2【分别是0123位置】
则相交的矩形框假设为X,左上角坐标设为点A,右下角坐标设为点B;
现在要计算 IoU = area_X / (area_1 + area_2 - area_X)
懂?
计算思路
相交的情况
两个矩形相交情况,如上图所示,只要矩形框A和B点的坐标,即可求出相交区域的面积,从而求得IoU。
AB坐标计算思路如下:【你面试的时候,直接画个图就完事了,非常简单】
A的横坐标 等于 两个矩形框左上角横坐标较大的那个,即Ax = max(x1, a1)
A的纵坐标 等于 两个矩形框左上角纵坐标较大的那个,即Ay = max(y1, b1)
B的横坐标 等于 两个矩形框右下角横坐标较小的那个,即Bx = min(x2, a2)
B的纵坐标 等于 两个矩形框右下角纵坐标较小的那个,即By = min(y2, b2)
显然,X的宽w=Bx-Ax,X的长是h=By-Ay
如果w或者h有一个小于0,说明他们俩压根没有交集!!!
那iou必然是0
因此我们过滤掉这个条件
最后得到了X的面积Sx=w*h
S1原本也好求:S1=(x2-x1)×(y2-y1)
S2原本也好求:S2=(a2-a1)×(b2-b1)
就是长乘宽就行
并集的面积,需要减x的面积,因为S1+S2重复加了x
故iou的三个元素都出来了,Sx,S1,S2都有了,那手撕代码问题就不大了吧
遇到输入是数组rect1,rect2,建议你先把坐标转化为自己熟悉的xy和ab,这样我们就好对应了
手撕代码:
//计算 IoU = area_X / (area_1 + area_2 - area_X)
//给你的输入是俩数组:
//rect1:左上角x1,y1,右下角x2,y2【分别是0123位置】
//rect2:左上角a1,b1,右下角a2,b2【分别是0123位置】
//转化为自己熟悉的形式
public static double iou(int[] rect1, int[] rect2){
if (rect1 == null || rect1.length == 0 ||
rect2 == null || rect2.length == 0) return 0;
int x1 = rect1[0];
int y1 = rect1[1];
int x2 = rect1[2];
int y2 = rect1[3];//rect1
int a1 = rect2[0];
int b1 = rect2[1];
int a2 = rect2[2];
int b2 = rect2[3];//rect2
//草稿纸自己画个图就知道了
//S1//S2
double S1 = (x2 - x1) * (y2 - y1);
double S2 = (a2 - a1) * (b2 - b1);
//iou
int Ax = Math.max(x1, a1);//交集左上角
int Ay = Math.max(y1, b1);
int Bx = Math.min(x2, y2);//交集右下角
int By = Math.min(y2, b2);
int w = Bx - Ax;
int h = By - Ay;//交集长宽
if (w <= 0 || h <= 0) return 0;//无交集
double Sx = w * h;
double ans = Sx / (S1 + S2 - Sx);
System.out.println("交集面积:"+ Sx);
return ans;
}
测试一把:
public static void test(){
int[] rect1 = {2,1,4,3};
int[] rect2 = {1,2,3,4};
//画个图看看,交集A,B在
System.out.println(iou(rect1, rect2));
}
public static void main(String[] args) {
test();
}
结果:
交集面积:1.0
0.14285714285714285
非常OK
所以笔试面试都好说,拿个图,直接画一下就行了,不是背公式,更不是背代码的事
总结
提示:重要经验:
1)笔试面试都好说,拿个图,直接画一下就行了,不是背公式,更不是背代码的事
2)IoU = area_X / (area_1 + area_2 - area_X)
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。