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(list(range(4)), minRect)])
rect = minrect[topLeft:] + minrect[:topLeft]
Finding rotated rectangle from contour