Я следую этому вопросу:Python OpenCV сортировки контуры
How can I sort contours from left to right and top to bottom?
для сортировки контуров слева направо и сверху-вниз. Тем не менее, мои контуры найдены с помощью этого (OpenCV 3):
im2, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
и они отформатированы, как это:
array([[[ 1, 1]],
[[ 1, 36]],
[[63, 36]],
[[64, 35]],
[[88, 35]],
[[89, 34]],
[[94, 34]],
[[94, 1]]], dtype=int32)]
Когда я запускаю код
max_width = max(contours, key=lambda r: r[0] + r[2])[0]
max_height = max(contours, key=lambda r: r[3])[3]
nearest = max_height * 1.4
contours.sort(key=lambda r: (int(nearest * round(float(r[1])/nearest)) * max_width + r[0]))
я набираюсь ошибка
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
поэтому я изменил это так:
max_width = max(contours, key=lambda r: np.max(r[0] + r[2]))[0]
max_height = max(contours, key=lambda r: np.max(r[3]))[3]
nearest = max_height * 1.4
contours.sort(key=lambda r: (int(nearest * round(float(r[1])/nearest)) * max_width + r[0]))
, но теперь я получаю сообщение об ошибке:
TypeError: only length-1 arrays can be converted to Python scalars
EDIT:
После прочтения ответа ниже я изменил мой код:
EDIT 2
Это код, который я использую, чтобы "растянуть" персонажей и найти контуры
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(35,35))
# dilate the image to get text
# binaryContour is just the black and white image shown below
dilation = cv2.dilate(binaryContour,kernel,iterations = 2)
КОНЕЦ EDIT 2
im2, contours, hierarchy = cv2.findContours(dilation,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
myContours = []
# Process the raw contours to get bounding rectangles
for cnt in reversed(contours):
epsilon = 0.1*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
if len(approx == 4):
rectangle = cv2.boundingRect(cnt)
myContours.append(rectangle)
max_width = max(myContours, key=lambda r: r[0] + r[2])[0]
max_height = max(myContours, key=lambda r: r[3])[3]
nearest = max_height * 1.4
myContours.sort(key=lambda r: (int(nearest * round(float(r[1])/nearest)) * max_width + r[0]))
i=0
for x,y,w,h in myContours:
letter = binaryContour[y:y+h, x:x+w]
cv2.rectangle(binaryContour,(x,y),(x+w,y+h),(255,255,255),2)
cv2.imwrite("pictures/"+str(i)+'.png', letter) # save contour to file
i+=1
Контуры перед сортировкой:
[(1, 1, 94, 36), (460, 223, 914, 427), (888, 722, 739, 239), (35,723, 522, 228),
(889, 1027, 242, 417), (70, 1028, 693, 423), (1138, 1028, 567, 643),
(781, 1030, 98, 413), (497, 1527, 303, 132), (892, 1527, 168, 130),
(37, 1719, 592, 130), (676, 1721, 413, 129), (1181, 1723, 206, 128),
(30, 1925, 997, 236), (1038, 1929, 170, 129), (140, 2232, 1285, 436)]
Контуры после сортировки:
(ПРИМЕЧАНИЕ. Это не порядок, я хочу, чтобы контуры должны быть отсортированы в см изображения в нижней части)
[(1, 1, 94, 36), (460, 223, 914, 427), (35, 723, 522, 228), (70,1028, 693, 423),
(781, 1030, 98, 413), (888, 722, 739, 239), (889, 1027, 242, 417),
(1138, 1028, 567, 643), (30, 1925, 997, 236), (37, 1719, 592, 130),
(140, 2232, 1285, 436), (497, 1527, 303, 132), (676, 1721, 413, 129),
(892, 1527, 168, 130), (1038, 1929, 170, 129), (1181, 1723, 206, 128)]
Image Я работаю с
I хотите найти контуры в следующем порядке:
Dilation image используется для определения контуров
Можете ли вы объяснить вашу цель? Что вам нужно в финальном выпуске? На основании чего вы хотите найти контуры по площади, по месту происхождения или по каким-либо другим критериям? – ZdaR
Я загрузил другое изображение, чтобы описать, в каком порядке я хочу, чтобы контуры были отсортированы как. Мне просто нужно отсортировать контуры по положению и сохранить их в файл в этом порядке. –
Вы можете написать код для создания 'dilation' please? –