W testowaniu algorytmu detekcji obiektów w dużych obrazach sprawdzamy nasze wykryte pola obrywa przeciwko współrzędnym podanym dla prostokątów prawdy gruntu.
Według pascalowych wyzwań LZO, jest to:
Przewidywane pudełko obniża jest uważane za poprawne, jeśli nakłada się na ponad 50% z polem obniża prawdy, w przeciwnym razie obwiednia jest uważana za fałszywe wykrywanie dodatnie. Wiele wykrywania jest karane. Jeśli system przewiduje kilka ograniczających skrzynek, które nakładają się za pomocą pojedynczej skrzynki prawdy, tylko jedna prognoza jest uważana za prawidłową, pozostałe są uważane za fałszywe pozytywy.
Oznacza to, że musimy obliczyć procent nakładania się. Czy to oznacza, że pole ziemią jest 50% objęte wykrytym polem granicznym? Lub że 50% pola ograniczającego jest wchłaniane przez podstawowe pudełko prawdy?
Szukałem, ale nie znalazłem dla tego standardowego algorytmu - co jest zaskakujące, ponieważ pomyślałbym, że jest to coś dość powszechnego w wizji komputera. (Jestem nowy). Nie przegapiłem tego? Czy ktoś wie, co stanowi standardowy algorytm dla tego typu problemu?
7 odpowiedzi
Odkryłem, że koncepcyjna odpowiedź jest tutaj: http: //pascallin.ecs.soton. AC.UK/Challenges/voc/voc2012/htmldoc/devkit_doc.html#section00054000000000000000000.
Z tego wątku: Porównaj dwie obwiednie pudełka ze sobą matlab
Powinienem być w stanie tego kodować w Pythonie!
Najwyżej głosowana odpowiedź ma błąd matematyczny, jeśli pracujesz z współrzędnymi ekranem (Pixel)! Przesłałem Edycja kilka tygodni temu z długim wyjaśnieniem dla wszystkich czytelników, aby zrozumieli matematykę. Ale ta edycja nie była zrozumiana przez recenzentów i została usunięta, więc ponownie przesłałem tę samą edycję, ale bardziej krótko podsumowano tym razem. (Aktualizacja: Odrzucony 2VS1 ponieważ uznano za "znaczną zmianę", Heh).
Będę więc wyjaśnić duży problem z matematyką tutaj w tej osobnej odpowiedzi.
Tak, w ogóle, ogólnie, głosowana odpowiedź jest poprawna i jest dobrym sposobem na obliczenie IOU. Ale (jak również wskazali inne osoby), jego matematyka jest całkowicie niepoprawna dla ekranów komputerowych. Nie można po prostu zrobić (x2 - x1) * (y2 - y1)
, ponieważ nie spowoduje tego właściwego obliczenia obszaru. Indeksowanie ekranu Rozpoczyna się w Pixel 0,0
i kończy w width-1,height-1
. Zakres współrzędnych ekranów to inclusive:inclusive
(włącznie na obu końcach), więc zakres od 0
do 10
w współrzędnych pikseli wynosi 11 pikseli szerokości, ponieważ obejmuje 0 1 2 3 4 5 6 7 8 9 10
(11 pozycji). Tak więc, aby obliczyć obszar współrzędnych ekranu, należy zatem dodać +1 do każdego wymiaru, w następujący sposób: (x2 - x1 + 1) * (y2 - y1 + 1)
.
Jeśli pracujesz w innym układzie współrzędnych, w którym zakres nie jest włączony (taki jak system inclusive:exclusive
, gdzie 0
oznacza "Elementy 0-9, ale nie 10"), Wtedy ta dodatkowa matematyka nie byłaby konieczna. Ale najprawdopodobniej przetwarzasz oparte na pikselach skrzynek. Cóż, współrzędne ekranu zaczynają się od 0,0
i idź tam.
Ekran 1920x1080
jest indeksowany z 0
(pierwszy piksel) do 1919
(ostatni piksel poziomo) i z 0
(pierwszy piksel) do 1079
(Ostatni piksel) pionowo).
Więc jeśli mamy prostokąt w "przestrzeni współrzędnych pikseli", aby obliczyć jego obszar musi dodać 1 w każdym kierunku. W przeciwnym razie otrzymujemy niewłaściwą odpowiedź na obliczenie obszarze.
Wyobraź sobie, że ekran naszego 1920x1080
ma prostokąt na bazie pikseli z left=0,top=0,right=1919,bottom=1079
(obejmując wszystkie piksele na całym ekranie).
Cóż, wiemy, że 1920x1080
piksele to 2073600
piksele, który jest właściwym obszarem ekranu 1080p.
Ale z niewłaściwą matematyką area = (x_right - x_left) * (y_bottom - y_top)
, otrzymaliśmy: (1919 - 0) * (1079 - 0)
= 1919 * 1079
= 2070601
piksele! To jest źle!
Dlatego musimy dodać +1
do każdego obliczenia, co daje nam następującą poprawioną matematykę: area = (x_right - x_left + 1) * (y_bottom - y_top + 1)
, dając nam: (1919 - 0 + 1) * (1079 - 0 + 1)
= 1920 * 1080
= 2073600
piksele ! I to rzeczywiście poprawna odpowiedź!
Najkrótsze możliwe podsumowanie jest: zakresy współrzędnych pikseli są inclusive:inclusive
, więc musimy dodać + 1
do każdej osi, jeśli chcemy prawdziwej powierzchni zakresu współrzędnych pikseli.
Za kilka szczegółowych informacji na temat tego, dlaczego +1
jest potrzebna, zobacz odpowiedź Jindil: https://stackoverflow.com/a/51730512 / 8874388.
Jak również ten artykuł Pyimagagesearch: HTTPS: //www.pyImagesearch. COM / 2016/11 / 07 / Wykrywanie przecięcia-over-union-IOU
I ten github komentuje: https://github.com/alexeyab/darknet/issues/3995#issuecomment-535697357 \ t.
Ponieważ stała matematyka nie została zatwierdzona, każdy, kto kopiuje kod z najwyższej odpowiedzi, miejmy nadzieję, że widzi tę odpowiedź, i będzie w stanie sam się poprawić, po prostu skopiując twierdzenia błędów i linie obliczeniowe poniżej, które były Naprawiono zakresy współrzędnych inclusive:inclusive
(Pixel):
assert bb1['x1'] <= bb1['x2']
assert bb1['y1'] <= bb1['y2']
assert bb2['x1'] <= bb2['x2']
assert bb2['y1'] <= bb2['y2']
................................................
# The intersection of two axis-aligned bounding boxes is always an
# axis-aligned bounding box.
# NOTE: We MUST ALWAYS add +1 to calculate area when working in
# screen coordinates, since 0,0 is the top left pixel, and w-1,h-1
# is the bottom right pixel. If we DON'T add +1, the result is wrong.
intersection_area = (x_right - x_left + 1) * (y_bottom - y_top + 1)
# compute the area of both AABBs
bb1_area = (bb1['x2'] - bb1['x1'] + 1) * (bb1['y2'] - bb1['y1'] + 1)
bb2_area = (bb2['x2'] - bb2['x1'] + 1) * (bb2['y2'] - bb2['y1'] + 1)
Droga prosta
(Obraz nie jest rysowany do skali)
from shapely.geometry import Polygon
def calculate_iou(box_1, box_2):
poly_1 = Polygon(box_1)
poly_2 = Polygon(box_2)
iou = poly_1.intersection(poly_2).area / poly_1.union(poly_2).area
return iou
box_1 = [[511, 41], [577, 41], [577, 76], [511, 76]]
box_2 = [[544, 59], [610, 59], [610, 94], [544, 94]]
print(calculate_iou(box_1, box_2))
Wynik będzie 0.138211...
, co oznacza 13.82%
.
W przypadku odległości skrzyżowania nie powinniśmy dodawać +1, aby mieć
intersection_area = (x_right - x_left + 1) * (y_bottom - y_top + 1)
(tak samo dla AABB)
Jak na tym Pyimage Search Post
Zgadzam się (x_right - x_left) x (Y_BOTTOM - Y_TOP) pracuje w matematyce z współrzędnymi punktami, ale odkąd zajmujemy się pikselami, tak myślę.
Rozważ 1D Przykład:
- 2 punkty: x1 = 1 i x2 = 3 , odległość jest rzeczywiście x2-x1 = 2
- 2 pikseli indeksu: i1 = 1 i i2 = 3 , segment z pikseli I1 do I2 zawiera 3 piksele, czyli L = I2 - I1 + 1 ..
W poniższym fragmencie buduję wielokąt wzdłuż krawędzi pierwszego pudełka. Następnie użyj MATPOTLIB do klipu wielokąt do drugiego pola. Uzyskany wielokąt zawiera cztery wierzchołki, ale interesuje nas tylko górne rogi w lewo i dolne prawe rogi, więc biorę maksimum i minimalne współrzędne, aby uzyskać obwiedni, który jest zwracany do użytkownika.
import numpy as np
from matplotlib import path, transforms
def clip_boxes(box0, box1):
path_coords = np.array([[box0[0, 0], box0[0, 1]],
[box0[1, 0], box0[0, 1]],
[box0[1, 0], box0[1, 1]],
[box0[0, 0], box0[1, 1]]])
poly = path.Path(np.vstack((path_coords[:, 0],
path_coords[:, 1])).T, closed=True)
clip_rect = transforms.Bbox(box1)
poly_clipped = poly.clip_to_bbox(clip_rect).to_polygons()[0]
return np.array([np.min(poly_clipped, axis=0),
np.max(poly_clipped, axis=0)])
box0 = np.array([[0, 0], [1, 1]])
box1 = np.array([[0, 0], [0.5, 0.5]])
print clip_boxes(box0, box1)
Co powiesz na to podejście? Może zostać przedłużony na dowolną liczbę uzwiązanych kształtów
surface = np.zeros([1024,1024])
surface[1:1+10, 1:1+10] += 1
surface[100:100+500, 100:100+100] += 1
unionArea = (surface==2).sum()
print(unionArea)
W przypadku skrzynek ograniczających osi są stosunkowo proste. "Asy wyrównane" oznacza, że obwiedni nie jest obracany; lub innymi słowy, które linie pudełka są równoległe do osi. Oto jak obliczyć IOU o dwóch osłonowych skrzynkach.
def get_iou(bb1, bb2):
"""
Calculate the Intersection over Union (IoU) of two bounding boxes.
Parameters
----------
bb1 : dict
Keys: {'x1', 'x2', 'y1', 'y2'}
The (x1, y1) position is at the top left corner,
the (x2, y2) position is at the bottom right corner
bb2 : dict
Keys: {'x1', 'x2', 'y1', 'y2'}
The (x, y) position is at the top left corner,
the (x2, y2) position is at the bottom right corner
Returns
-------
float
in [0, 1]
"""
assert bb1['x1'] < bb1['x2']
assert bb1['y1'] < bb1['y2']
assert bb2['x1'] < bb2['x2']
assert bb2['y1'] < bb2['y2']
# determine the coordinates of the intersection rectangle
x_left = max(bb1['x1'], bb2['x1'])
y_top = max(bb1['y1'], bb2['y1'])
x_right = min(bb1['x2'], bb2['x2'])
y_bottom = min(bb1['y2'], bb2['y2'])
if x_right < x_left or y_bottom < y_top:
return 0.0
# The intersection of two axis-aligned bounding boxes is always an
# axis-aligned bounding box
intersection_area = (x_right - x_left) * (y_bottom - y_top)
# compute the area of both AABBs
bb1_area = (bb1['x2'] - bb1['x1']) * (bb1['y2'] - bb1['y1'])
bb2_area = (bb2['x2'] - bb2['x1']) * (bb2['y2'] - bb2['y1'])
# compute the intersection over union by taking the intersection
# area and dividing it by the sum of prediction + ground-truth
# areas - the interesection area
iou = intersection_area / float(bb1_area + bb2_area - intersection_area)
assert iou >= 0.0
assert iou <= 1.0
return iou
Wyjaśnienie
Obrazy są z Ta odpowiedź
Podobne pytania
Powiązane pytania
Nowe pytania
python
Python to wielozadaniowy, wielozadaniowy język programowania dynamicznie typowany. Został zaprojektowany tak, aby był szybki do nauczenia się, zrozumienia i użycia oraz wymuszania czystej i jednolitej składni. Należy pamiętać, że Python 2 oficjalnie nie jest obsługiwany od 01-01-2020. Mimo to, w przypadku pytań Pythona specyficznych dla wersji, dodaj znacznik [python-2.7] lub [python-3.x]. Korzystając z wariantu Pythona (np. Jython, PyPy) lub biblioteki (np. Pandas i NumPy), należy umieścić go w tagach.