2015-07-27 2 views
6

Я пытаюсь использовать OpenCV для идентификации и извлечения довольно очевидной области из изображения. До сих пор, используя порог и ряд расширений и эрозий, я могу успешно найти контур для области, в которой я нуждаюсь.Поиск вращающегося прямоугольника из контура

Однако мои попытки использовать minAreaRect в качестве предшественника вращения и обрезки не могут создать прямоугольник, содержащий входной контур.

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) 

Вот и пример вывода:

Output

Если красный инсульт является rect и зеленый является contour. Я бы ожидал, что красный удар охватит зеленый ход.

К сожалению, я не могу предоставить входное изображение.

+0

В конце я написал собственную реализацию метода вращающихся суппортов для нахождения минимального ограничивающего прямоугольника. Я все же хотел бы узнать, как найти результат с помощью функции 'minAreaRect()'. – thomasfedb

+0

Я не могу рассказать вам много о Python, но в C++ он работает так, как ожидалось. Всего несколько проверок, если вы уже этого не сделали. 1) Я не думаю, что проблема заключается в 'minAreaRect'. Вы можете убедиться, что, нарисуя круг в левом верхнем углу 'rotrect' и проверьте, разумно ли это. 2) Также попробуйте использовать 'box = cv2.boxPoints (rect)', а не 'cv2.cv.BoxPoints (...)'. Извините, но это все, что у меня есть. – Miki

+0

'cv2.boxPoints (rect)' недоступен в версии OpenCV, к которой у меня есть доступ. Выбрав центральную точку из 'rotrect', я установил, что' minAreaRect() 'на самом деле дает неправильный результат. – thomasfedb

ответ

1

Я решил это решить, выполнив мою собственную процедуру вращающихся суппортов, чтобы найти минимальный прямоугольник. Он использует выпуклый корпус для определения возможных вращений.

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] 
Смежные вопросы