|
14 | 14 | import pandas as pd
|
15 | 15 |
|
16 | 16 | def Point_in_Rectangle(Point, Rectangle):
|
17 |
| - '''Return True if a point (x,y) is contained in a Rectangle(x, y, width, height)''' |
18 |
| - # unpack variables |
19 |
| - Px, Py = Point |
20 |
| - Rx, Ry, w, h = Rectangle |
| 17 | + '''Return True if a point (x,y) is contained in a Rectangle(x, y, width, height)''' |
| 18 | + # unpack variables |
| 19 | + Px, Py = Point |
| 20 | + Rx, Ry, w, h = Rectangle |
21 | 21 |
|
22 |
| - return (Rx <= Px) and (Px <= Rx + w -1) and (Ry <= Py) and (Py <= Ry + h -1) # simply test if x_Point is in the range of x for the rectangle |
| 22 | + return (Rx <= Px) and (Px <= Rx + w -1) and (Ry <= Py) and (Py <= Ry + h -1) # simply test if x_Point is in the range of x for the rectangle |
23 | 23 |
|
24 | 24 |
|
25 | 25 | def computeIoU(BBox1,BBox2):
|
26 |
| - ''' |
27 |
| - Compute the IoU (Intersection over Union) between 2 rectangular bounding boxes defined by the top left (Xtop,Ytop) and bottom right (Xbot, Ybot) pixel coordinates |
28 |
| - Code adapted from https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/ |
29 |
| - ''' |
30 |
| - #print('BBox1 : ', BBox1) |
31 |
| - #print('BBox2 : ', BBox2) |
32 |
| - |
33 |
| - # Unpack input (python3 - tuple are no more supported as input in function definition - PEP3113 - Tuple can be used in as argument in a call but the function will not unpack it automatically) |
34 |
| - Xleft1, Ytop1, Width1, Height1 = BBox1 |
35 |
| - Xleft2, Ytop2, Width2, Height2 = BBox2 |
36 |
| - |
37 |
| - # Compute bottom coordinates |
38 |
| - Xright1 = Xleft1 + Width1 -1 # we remove -1 from the width since we start with 1 pixel already (the top one) |
39 |
| - Ybot1 = Ytop1 + Height1 -1 # idem for the height |
40 |
| - |
41 |
| - Xright2 = Xleft2 + Width2 -1 |
42 |
| - Ybot2 = Ytop2 + Height2 -1 |
43 |
| - |
44 |
| - # determine the (x, y)-coordinates of the top left and bottom right points of the intersection rectangle |
45 |
| - Xleft = max(Xleft1, Xleft2) |
46 |
| - Ytop = max(Ytop1, Ytop2) |
47 |
| - Xright = min(Xright1, Xright2) |
48 |
| - Ybot = min(Ybot1, Ybot2) |
49 |
| - |
50 |
| - # Compute boolean for inclusion |
51 |
| - BBox1_in_BBox2 = Point_in_Rectangle((Xleft1, Ytop1), BBox2) and Point_in_Rectangle((Xleft1, Ybot1), BBox2) and Point_in_Rectangle((Xright1, Ytop1), BBox2) and Point_in_Rectangle((Xright1, Ybot1), BBox2) |
52 |
| - BBox2_in_BBox1 = Point_in_Rectangle((Xleft2, Ytop2), BBox1) and Point_in_Rectangle((Xleft2, Ybot2), BBox1) and Point_in_Rectangle((Xright2, Ytop2), BBox1) and Point_in_Rectangle((Xright2, Ybot2), BBox1) |
53 |
| - |
54 |
| - # Check that for the intersection box, Xtop,Ytop is indeed on the top left of Xbot,Ybot |
55 |
| - if BBox1_in_BBox2 or BBox2_in_BBox1: |
56 |
| - #print('One BBox is included within the other') |
57 |
| - IoU = 1 |
58 |
| - |
59 |
| - elif Xright<Xleft or Ybot<Ytop : # it means that there is no intersection (bbox is inverted) |
60 |
| - #print('No overlap') |
61 |
| - IoU = 0 |
62 |
| - |
63 |
| - else: |
64 |
| - # Compute area of the intersecting box |
65 |
| - Inter = (Xright - Xleft + 1) * (Ybot - Ytop + 1) # +1 since we are dealing with pixels. See a 1D example with 3 pixels for instance |
66 |
| - #print('Intersection area : ', Inter) |
67 |
| - |
68 |
| - # Compute area of the union as Sum of the 2 BBox area - Intersection |
69 |
| - Union = Width1 * Height1 + Width2 * Height2 - Inter |
70 |
| - #print('Union : ', Union) |
71 |
| - |
72 |
| - # Compute Intersection over union |
73 |
| - IoU = Inter/Union |
74 |
| - |
75 |
| - #print('IoU : ',IoU) |
76 |
| - return IoU |
77 |
| - |
78 |
| - |
79 |
| - |
80 |
| -def NMS(List_Hit, scoreThreshold=None, sortDescending=True, N_object=float("inf"), maxOverlap=0.5): |
81 |
| - ''' |
82 |
| - Perform Non-Maxima supression : it compares the hits after maxima/minima detection, and removes the ones that are too close (too large overlap) |
83 |
| - This function works both with an optionnal threshold on the score, and number of detected bbox |
84 |
| -
|
85 |
| - if a scoreThreshold is specified, we first discard any hit below/above the threshold (depending on sortDescending) |
86 |
| - if sortDescending = True, the hit with score below the treshold are discarded (ie when high score means better prediction ex : Correlation) |
87 |
| - if sortDescending = False, the hit with score above the threshold are discared (ie when low score means better prediction ex : Distance measure) |
88 |
| -
|
89 |
| - Then the hit are ordered so that we have the best hits first. |
90 |
| - Then we iterate over the list of hits, taking one hit at a time and checking for overlap with the previous validated hit (the Final Hit list is directly iniitialised with the first best hit as there is no better hit with which to compare overlap) |
91 |
| - |
92 |
| - This iteration is terminate once we have collected N best hit, or if there are no more hit left to test for overlap |
| 26 | + ''' |
| 27 | + Compute the IoU (Intersection over Union) between 2 rectangular bounding boxes defined by the top left (Xtop,Ytop) and bottom right (Xbot, Ybot) pixel coordinates |
| 28 | + Code adapted from https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/ |
| 29 | + ''' |
| 30 | + #print('BBox1 : ', BBox1) |
| 31 | + #print('BBox2 : ', BBox2) |
| 32 | + |
| 33 | + # Unpack input (python3 - tuple are no more supported as input in function definition - PEP3113 - Tuple can be used in as argument in a call but the function will not unpack it automatically) |
| 34 | + Xleft1, Ytop1, Width1, Height1 = BBox1 |
| 35 | + Xleft2, Ytop2, Width2, Height2 = BBox2 |
| 36 | + |
| 37 | + # Compute bottom coordinates |
| 38 | + Xright1 = Xleft1 + Width1 -1 # we remove -1 from the width since we start with 1 pixel already (the top one) |
| 39 | + Ybot1 = Ytop1 + Height1 -1 # idem for the height |
| 40 | + |
| 41 | + Xright2 = Xleft2 + Width2 -1 |
| 42 | + Ybot2 = Ytop2 + Height2 -1 |
| 43 | + |
| 44 | + # determine the (x, y)-coordinates of the top left and bottom right points of the intersection rectangle |
| 45 | + Xleft = max(Xleft1, Xleft2) |
| 46 | + Ytop = max(Ytop1, Ytop2) |
| 47 | + Xright = min(Xright1, Xright2) |
| 48 | + Ybot = min(Ybot1, Ybot2) |
| 49 | + |
| 50 | + # Compute boolean for inclusion |
| 51 | + BBox1_in_BBox2 = Point_in_Rectangle((Xleft1, Ytop1), BBox2) and Point_in_Rectangle((Xleft1, Ybot1), BBox2) and Point_in_Rectangle((Xright1, Ytop1), BBox2) and Point_in_Rectangle((Xright1, Ybot1), BBox2) |
| 52 | + BBox2_in_BBox1 = Point_in_Rectangle((Xleft2, Ytop2), BBox1) and Point_in_Rectangle((Xleft2, Ybot2), BBox1) and Point_in_Rectangle((Xright2, Ytop2), BBox1) and Point_in_Rectangle((Xright2, Ybot2), BBox1) |
| 53 | + |
| 54 | + # Check that for the intersection box, Xtop,Ytop is indeed on the top left of Xbot,Ybot |
| 55 | + if BBox1_in_BBox2 or BBox2_in_BBox1: |
| 56 | + #print('One BBox is included within the other') |
| 57 | + IoU = 1 |
| 58 | + |
| 59 | + elif Xright<Xleft or Ybot<Ytop : # it means that there is no intersection (bbox is inverted) |
| 60 | + #print('No overlap') |
| 61 | + IoU = 0 |
| 62 | + |
| 63 | + else: |
| 64 | + # Compute area of the intersecting box |
| 65 | + Inter = (Xright - Xleft + 1) * (Ybot - Ytop + 1) # +1 since we are dealing with pixels. See a 1D example with 3 pixels for instance |
| 66 | + #print('Intersection area : ', Inter) |
| 67 | + |
| 68 | + # Compute area of the union as Sum of the 2 BBox area - Intersection |
| 69 | + Union = Width1 * Height1 + Width2 * Height2 - Inter |
| 70 | + #print('Union : ', Union) |
| 71 | + |
| 72 | + # Compute Intersection over union |
| 73 | + IoU = Inter/Union |
| 74 | + |
| 75 | + #print('IoU : ',IoU) |
| 76 | + return IoU |
| 77 | + |
| 78 | + |
| 79 | + |
| 80 | +def NMS(tableHit, scoreThreshold=None, sortDescending=True, N_object=float("inf"), maxOverlap=0.5): |
| 81 | + ''' |
| 82 | + Perform Non-Maxima supression : it compares the hits after maxima/minima detection, and removes the ones that are too close (too large overlap) |
| 83 | + This function works both with an optionnal threshold on the score, and number of detected bbox |
| 84 | +
|
| 85 | + if a scoreThreshold is specified, we first discard any hit below/above the threshold (depending on sortDescending) |
| 86 | + if sortDescending = True, the hit with score below the treshold are discarded (ie when high score means better prediction ex : Correlation) |
| 87 | + if sortDescending = False, the hit with score above the threshold are discared (ie when low score means better prediction ex : Distance measure) |
| 88 | +
|
| 89 | + Then the hit are ordered so that we have the best hits first. |
| 90 | + Then we iterate over the list of hits, taking one hit at a time and checking for overlap with the previous validated hit (the Final Hit list is directly iniitialised with the first best hit as there is no better hit with which to compare overlap) |
| 91 | + |
| 92 | + This iteration is terminate once we have collected N best hit, or if there are no more hit left to test for overlap |
93 | 93 |
|
94 | 94 | INPUT
|
95 | 95 | - tableHit : (Panda DataFrame) Each row is a hit, with columns "TemplateName"(String),"BBox"(x,y,width,height),"Score"(float)
|
|
0 commit comments