2015-03-18 12 views
10

Czy istnieje coś takiego jak cv::Mat::contains(cv::Rect) w Opencv?Jak sprawdzić, czy rect znajduje się wewnątrz cv :: Mat w OpenCV?

Tło: Po wykryciu obiektów jak kontury i próbuje ROI dostępu za pomocą cv :: boundingRect moja aplikacja zawieszała. OK, to dlatego, że ograniczające prostokąty obiektu blisko granicy obrazu mogą nie znajdować się w całości w obrazie.

Teraz pominąć obiekty niezupełnie w obrazie o tej kontroli:

if(
    cellRect.x>0 && 
    cellRect.y>0 && 
    cellRect.x + cellRect.width < m.cols && 
    cellRect.x + cellRect.width < m.rows) ... 

gdzie cellRect jest obwiedni rect obiektu i m jest obraz. Mam nadzieję, że jest dedykowana do tego funkcja opencv.

Odpowiedz

17

Prostym sposobem jest użycie operatora I (tj &).

Załóżmy, że chcesz sprawdzić, czy cv::Rect rect jest wewnątrz cv::Mat mat:

bool is_inside = (rect & cv::Rect(0, 0, mat.cols, mat.rows)) == rect; 
+0

Prawdopodobnie nie jest to szybkie rozwiązanie, ale interesujące. '(rect i rect_mat)' utworzyłoby nowy obiekt Mat i = = porównałoby wszystkie komórki. Będzie to na pewno wolniejsze, niż uzyskanie i skompilowanie 4 liczb x, y, w, h. –

+2

@ValentinHeinitz Nie nowy "Mat", nowy "Rect" faktycznie, który jest w zasadzie tylko 4 liczb '(x, y, szerokość, wysokość)'. Powinno to być relatywnie szybkie. : P – herohuyongtao

+1

OK, rozumiem! Teraz wygląda naprawdę elegancko! –

4

Możesz utworzyć prostokąt "reprezentujący" (x, y = 0, szerokość i wysokość równą szerokości i wysokości obrazu) i sprawdzić, czy zawiera prostokątne krawędzie konturów. Aby to osiągnąć, musisz użyć prostego przecięcia - w OpenCV jest to bardzo proste, wystarczy użyć rect1 & rect2. Nadzieję, że kod wyraźnie:

cv::Rect imgRect = cv::Rect(cv::Point(0,0), img.size()); 
cv::Rect objectBoundingRect = ....; 
cv::Rect rectsIntersecion = imgRect & objectBoundingRect; 
if (rectsIntersecion.area() == 0) 
    //object is completely outside image 
else if (rectsIntersecion.area() == objectBoundingRect.area()) 
    //whole object is inside image 
else 
    //((double)rectsIntersecion.area())/((double)objectBoundingRect.area()) * 100.0 % of object is inside image 
+0

Interesujące! Nigdy intuicyjnie nie zrozumiałem, że & oznacza skrzyżowanie w OpenCV. Dobrze wiedzieć! Wygląda więc na to, że nie ma wbudowanej funkcji, takiej jak Rect :: contains (Rect)? Czemu? wydaje mi się, że jest to bardzo powszechna i użyteczna funkcja. –

+3

Myślę, że nie ma takiej funkcji, ponieważ jeden rect może zawierać inne rect w 100%, wcale (0%) lub w dowolnej części między 0-100%. Jeśli chcesz sprawdzić, czy rect1 zawiera rect2, po prostu użyj tego kodu 'bool zawiera = (rect1 i rect2) .area() == rect2.area()'. Zwróć uwagę, że ten kod zwróci true, jeśli rect2.area() będzie miało wartość 0 (więc szerokość lub wysokość będzie równa 0), jeśli tego nie chcesz, użyj tego kodu: 'bool zawiera = rect2.area() i& (rect1 i rect2) .area() == rect2.area() '. Mam nadzieję, że to jest to, czego potrzebujesz :) – cyriel

+0

OK, to było dobre wytłumaczenie. –

-1

Oto sposób ocenić, czy prostokąt zawiera inny prostokąt. możesz uzyskać informacje o rozmiarze od cv::Mat first, a następnie użyj poniższej metody:

public bool rectContainsRect(Rectangle containerRect, Rectangle subRect) 
{ 
    if(containerRect.Contains(new Point(subRect.Left, subRect.Top)) 
     && containerRect.Contains(new Point(subRect.Right, subRect.Top)) 
     && containerRect.Contains(new Point(subRect.Left, subRect.Bottom)) 
     && containerRect.Contains(new Point(subRect.Right, subRect.Bottom))) 
    { 
     return true; 
    } 
    return false; 
}