2015-07-27 15 views
6

Próbuję użyć OpenCV, aby zidentyfikować i wyodrębnić dość oczywisty region z obrazu. Do tej pory, stosując próg i serię rozszerzeń i erozji, mogę z powodzeniem znaleźć kontur dla wymaganego obszaru.Znajdowanie obróconego prostokąta od konturu

Jednak moje próby użycia minAreaRect jako prekursora obrotu i przycinania nie generują prostokąta zawierającego kontur wejściowy.

contours, hierarchy = cv2.findContours(morph.copy() ,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 
contour = contours[0] 

draw = cv2.cvtColor(morph, cv2.COLOR_GRAY2BGR) 
cv2.drawContours(draw, [contour], 0, (0,255,0), 2) 

rotrect = cv2.minAreaRect(contour) 
box = cv2.cv.BoxPoints(rotrect) 
box = numpy.int0(box) 
cv2.drawContours(draw, [box], 0, (0,0,255), 2) 

cv2.imshow('image', draw); cv2.waitKey(0) 

Oto i przykład wyjścia:

Output

Gdzie czerwony skok jest rect a zielona jest contour. Spodziewałbym się, że czerwony obrys będzie obejmował zielony obrys.

Niestety, nie mogę podać obrazu wejściowego.

+0

W końcu napisałem własną implementację metody obracających się suwaków do znajdowania minimalnego prostokąta ograniczającego. Nadal chciałbym wiedzieć, jak znaleźć wynik za pomocą 'minAreaRect()' jednak. – thomasfedb

+0

Nie mogę powiedzieć wiele o Pythonie, ale w C++ działa zgodnie z oczekiwaniami. Tylko kilka czeków, jeśli już tego nie zrobiłeś. 1) Nie sądzę, że problem dotyczy 'minAreaRect'. Możesz to sprawdzić, rysując okrąg w lewym górnym rogu 'rotrect' i sprawdź, czy jest to uzasadnione. 2) Spróbuj także użyć 'box = cv2.boxPoints (rect)', a nie 'cv2.cv.BoxPoints (...)'. Przepraszam, ale to wszystko, co mam. – Miki

+0

'cv2.boxPoints (rect)' nie jest dostępne w wersji OpenCV, do której mam dostęp. Rysując punkt środkowy z 'rotrect' ustaliłem, że' minAreaRect() 'w rzeczywistości daje zły wynik. – thomasfedb

Odpowiedz

1

Skończyłem rozwiązywanie tego problemu, wdrażając własną procedurę obracania zacisków, aby znaleźć minimalny prostokąt. Wykorzystuje wypukły kadłub do określenia rotacji kandydatów.

def p2abs(point): 
    return math.sqrt(point[0] ** 2 + point[1] ** 2) 

def rotatePoint(point, angle): 
    s, c = math.sin(angle), math.cos(angle) 
    return (p[0] * c - p[1] * s, p[0] * s + p[1] * c) 

def rotatePoints(points, angle): 
    return [rotatePoint(point, angle) for point in points] 

points = map(lambda x: tuple(x[0]), contour) 
convexHull = map(lambda x: points[x], scipy.spatial.ConvexHull(numpy.array(points)).vertices) 

minArea = float("inf") 
minRect = None 

for i in range(len(hull)): 
    a, b = convexHull[i], convexHull[i - 1] 
    ang = math.atan2(b[0] - a[0], b[1] - a[1]) 

    rotatedHull = rotatePoints(convexHull, ang) 

    minX = min(map(lambda p: p[0], rotatedHull)) 
    maxX = max(map(lambda p: p[0], rotatedHull)) 
    minY = min(map(lambda p: p[1], rotatedHull)) 
    maxY = max(map(lambda p: p[1], rotatedHull)) 

    area = (maxX - minX) * (maxY - minY) 

    if area < minArea: 
     minArea = area 

     rotatedRect = [(minX, minY), (minX, maxY), (maxX, maxY), (maxX, minY)] 
     minRect = rotatePoints(rotatedRect, -ang) 

_, topLeft = min([(p2abs(p), i) for p, i in zip(range(4), minRect)]) 
rect = minrect[topLeft:] + minrect[:topLeft] 
Powiązane problemy