2015-07-27 16 views
6

Tôi đang cố gắng sử dụng OpenCV để xác định và trích xuất một vùng khá rõ ràng từ một hình ảnh. Cho đến nay, bằng cách sử dụng một ngưỡng và một loạt các sự giãn nở và xói mòn, tôi có thể tìm đường viền cho khu vực mà tôi yêu cầu.Tìm hình chữ nhật được xoay từ đường viền

Tuy nhiên, nỗ lực của tôi để sử dụng minAreaRect làm tiền thân cho xoay vòng và cắt xén không tạo ra hình chữ nhật có chứa đường bao đầu vào.

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) 

Dưới đây là ví dụ về và kết quả:

Output

Trong trường hợp đột quỵ màu đỏ là rect và màu xanh lá cây là contour. Tôi đã có thể mong đợi đột quỵ màu đỏ để bao gồm các đột quỵ màu xanh lá cây.

Rất tiếc, tôi không thể cung cấp hình ảnh đầu vào.

+0

Cuối cùng, tôi đã tự thực hiện phương pháp quay của trình quay số để tìm hình chữ nhật giới hạn tối thiểu. Tôi vẫn muốn biết làm thế nào để tìm kết quả với 'minAreaRect()' tuy nhiên. – thomasfedb

+0

Tôi không thể nói nhiều về Python, nhưng trong C++ nó hoạt động như mong đợi. Chỉ cần một vài kiểm tra, nếu bạn đã không. 1) Tôi không nghĩ rằng vấn đề là trên 'minAreaRect'. Bạn có thể xác minh điều đó bằng cách vẽ một vòng tròn ở góc trên cùng bên trái của 'rotrect' và kiểm tra xem nó có hợp lý hay không. 2) Cũng thử sử dụng 'box = cv2.boxPoints (rect)', và không phải 'cv2.cv.BoxPoints (...)'. Xin lỗi, nhưng đó là tất cả những gì tôi có. – Miki

+0

'cv2.boxPoints (rect)' không có sẵn trong phiên bản OpenCV mà tôi có quyền truy cập. Bằng cách vẽ điểm trung tâm từ 'rotrect', tôi đã thiết lập rằng' minAreaRect() 'thực ra là đưa ra kết quả sai. – thomasfedb

Trả lời

1

Tôi đã kết thúc việc giải quyết điều này bằng cách thực hiện thủ tục quay số của trình quay của riêng tôi để tìm hình chữ nhật tối thiểu. Nó sử dụng thân lồi để xác định phép quay ứng cử viên.

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] 
Các vấn đề liên quan