@AbdulF atir был готов к хорошему решению, но, как говорится в комментариях (@ Randika @epinal), это не совсем работало для меня, поэтому я немного изменил его, и, похоже, он работает для моего дела. вот изображение, которое я использую.
im, contours, hierarchy = cv2.findContours(open_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("num of contours: {}".format(len(contours)))
mult = 1.2 # I wanted to show an area slightly larger than my min rectangle set this to one if you don't
img_box = cv2.cvtColor(img.copy(), cv2.COLOR_GRAY2BGR)
for cnt in contours:
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img_box, [box], 0, (0,255,0), 2) # this was mostly for debugging you may omit
W = rect[1][0]
H = rect[1][1]
Xs = [i[0] for i in box]
Ys = [i[1] for i in box]
x1 = min(Xs)
x2 = max(Xs)
y1 = min(Ys)
y2 = max(Ys)
rotated = False
angle = rect[2]
if angle < -45:
angle+=90
rotated = True
center = (int((x1+x2)/2), int((y1+y2)/2))
size = (int(mult*(x2-x1)),int(mult*(y2-y1)))
cv2.circle(img_box, center, 10, (0,255,0), -1) #again this was mostly for debugging purposes
M = cv2.getRotationMatrix2D((size[0]/2, size[1]/2), angle, 1.0)
cropped = cv2.getRectSubPix(img_box, size, center)
cropped = cv2.warpAffine(cropped, M, size)
croppedW = W if not rotated else H
croppedH = H if not rotated else W
croppedRotated = cv2.getRectSubPix(cropped, (int(croppedW*mult), int(croppedH*mult)), (size[0]/2, size[1]/2))
plt.imshow(croppedRotated)
plt.show()
plt.imshow(img_box)
plt.show()
Это должно произвести серию изображений, как это:
И это также даст результат изображение вроде этого:
Вы можете: 1) создать маску для вращающегося прямоугольника (достаточно просто с 'fillConvexPoly' или' drawContours (... CV_FILLED) '). 2) Черные инициализируют матрицу того же размера, что и оригинал. 3) Скопируйте только содержимое маски в новое изображение ('new_image.setTo (old_image, mask)'), 4) Обрезайте новое изображение в ограничивающей рамке повернутого прямоугольника – Miki