У меня есть несколько приблизительных кругов примерной формы сетки, но есть искажения.
Как мне расположить центры слева направо, сверху вниз?
Я попробовал findCirclesGrid, но не думаю, что это сработает с искажениями.
Я не думаю, что обнаружение BLOB-объектов имеет порядок.
Этот вопрос похож на: Python: сортировка элементов сверху слева вниз справа с помощью OpenCV. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.
Вам следует проверить отличный ответ, который я предложил в качестве дубликата.
внешне похоже, но не совсем. ответ, который вы связали, объединяет точки в заданное пользователем количество строк, независимо от того, какая форма сетки лежит в основе точек. если бы сетку повернуть еще раз, она определенно просто перерезала бы строки и исказила бы структуру. связанный ответ довольно тривиален (get_rows
), если удалить вторичный код (извлечение объектов для получения очков).
другой ответ на связанный вопрос на самом деле показывает более глубокое понимание. он предполагает кластеризацию, чувствительную к данным, вместо того, чтобы требовать количество кластеров, указанное пользователем. «кластеризация» описывает результат. это не конкретный подход. здесь «кластеризация» была бы нетривиальной, поскольку сетка искривлена нелинейно: точки не лежат ни на одной прямой линии. и именно об этой проблеме я упомянул в своем первом комментарии. Я имею в виду подходы и играл с этой проблемой в прошлом. надежные решения далеко не тривиальны.
@VanushVee, возможно, вы захотите добавить к вопросу второе изображение, на котором показана более сильно искаженная сетка... если в вашем приложении есть такие экземпляры. нам не нужно усложнять проблему, чем она есть на самом деле, но полезно увидеть, насколько сложной может быть проблема.
findCirclesGrid
, необходимый для калибровки камеры, должен иметь возможность восстанавливать деформированные сетки. ИДК, сможет ли он справиться с этим шаблоном. некоторые результаты поиска предполагают, что так и должно быть. CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING
помог кому-то в какой-то момент. ваше изображение может быть более сложным, потому что круги «комковатые».
небольшое расследование: детектору BLOB-объектов необходимо отключить всю фильтрацию. тогда я найду BLOB-объекты: i.sstatic.net/itvRGS0j.png и findCirclesGrid
могу найти структуру: i.sstatic.net/Ddr0WXA4.png (для этого требуется отсутствие флага кластеризации; реализация кластеризации делает это неправильное присвоение баллов). все это требует от вас знания размера сетки и всех точек, которые будут видны. любые недостающие испортят это.
findCirclesGrid()
предназначен для калибровки камеры. Ожидается, что такие шаблоны будут иметь искажения, как и ваши. Это определенно должно работать с вашими данными.
Ему просто нужна небольшая помощь. Внутри он использует BlobDetector
, который инициализируется с некоторыми значениями по умолчанию, которые хорошо работают для обычных сеток кругов, которые показывают четко определенные круги.
Для вашей картинки вам понадобится BlobDetector
с пользовательскими параметрами. Чтобы найти все эти комковатые капли, вам нужно отключить всю фильтрацию, которую он обычно выполняет.
params = cv.SimpleBlobDetector_Params()
params.filterByArea = False
params.filterByCircularity = False
params.filterByColor = False
params.filterByConvexity = False
params.filterByInertia = False
blobdet = cv.SimpleBlobDetector_create(params)
Результат keypoints = blobdet.detect(im)
и cv.drawKeypoints()
:
Также нужно быть осторожным с флажками findCirclesGrid()
. CALIB_CB_CLUSTERING
потерпел неудачу в том, что он неправильно присвоил точки позициям сетки.
(rv, gridpts) = cv.findCirclesGrid(
im, (10, 7),
flags=cv.CALIB_CB_SYMMETRIC_GRID,
blobDetector=blobdet)
И это придаст вам gridpts
форму (70, 1, 2)
.
Немного визуализации:
im_with_grid = cv.cvtColor(cv.pyrUp(im >> 1), cv.COLOR_GRAY2BGR)
for k in range(1, len(gridpts)):
[p1] = gridpts[k-1]
[p2] = gridpts[k]
cv.line(im_with_grid, (p1 * 2.0).astype(int), (p2 * 2.0).astype(int), (0, 0, 255), 2)
for i,[pt] in enumerate(gridpts):
cv.circle(im_with_grid, (pt * 2.0).astype(int), 5, (0, 255, 0), -1)
cv.putText(
im_with_grid, f"{i}", (pt * 2.0).astype(int),
cv.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2, cv.LINE_AA )
Или, если вы укажете размер сетки как (7, 10)
, она будет перевернута по диагонали и будет выглядеть так:
findCirclesGrid
не получится, если в сетке есть дефекты, т. е. недостающие точки. Он не может обойти эти дефекты. Вам необходимо идеальное обнаружение всех точек сетки.
Я собирался поработать над каким-нибудь кодом, который надежно восстанавливает структуру сетки по набору точек... но это требует времени и мотивации.