Как мне найти центр контуров, но не геометрический, а визуальный?
В качестве домашнего проекта и обучения OpenCV я пишу читалку этого 2d-кода, но есть проблема при поиске визуального центра контуров, как вы можете видеть на фото, сейчас точки находятся в местах геометрического центра, и это не проблема для небольших участков, но для больших участков точки выходят за пределы контура, и это не подходит для моих целей. (Я ищу центральные точки, чтобы затем находить только те контуры, центральные точки которых образуют круг). Может быть, у кого-то есть идеи, как это сделать, или даже мысли о том, как читать код в целом) Сейчас код выглядит следующим образом
import cv2
import numpy as np
# Загрузка изображения
img = cv2.imread("t5.png")
# Преобразование изображения в оттенки серого
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Размытие изображения для уменьшения шума
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# Пороговое значение изображения для binarization
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
# Нахождение контуров
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Вычисление площади всех контуров
areas = [cv2.contourArea(contour) for contour in contours]
# Нахождение контура с минимальной площадью
min_area = float("inf")
min_contour = None
for contour in contours:
area = cv2.contourArea(contour)
if area < min_area:
min_area = area
min_contour = contour
# Перебор всех контуров
for contour in contours:
# Аппроксимируем контур
epsilon = 0.01 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
# Преобразуем контур в полигон
contour_poly = cv2.convexHull(contour)
# Находим середины всех отрезков
segments = []
for i in range(len(contour_poly) - 1):
x1, y1 = contour_poly[i][0]
x2, y2 = contour_poly[i + 1][0]
mid_x = (x1 + x2) // 2
mid_y = (y1 + y2) // 2
segments.append((mid_x, mid_y))
# Находим точку по центру контура
center_x = sum(point[0] for point in segments) // len(segments)
center_y = sum(point[1] for point in segments) // len(segments)
# Рисуем точку по центру контура
cv2.circle(img, (center_x, center_y), 5, (0, 255, 0), -1) # Зеленая точка размером 5
# Отображение изображения
cv2.imshow("Contours with Divided Parts", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Ответы (2 шт):
Можно попробовать через центр массы.
Циклом с мелким шагом, например по пикселю
count=0
centerx,centery=(0,0)
for x in range(minx,maxx):
for y in range(miny, maxy):
if in_shape(x, y):
count+=1
centerx+=x
century+=y
centerx/=count
century/=count
Но у изогнутых фигур центр может не лежать на фигуре. Смотреться будет достовернее чем радиус описанной.
Решать декодироние этого кода нужно через полярные координаты, а не через визуальный центр
Тут надо использовать математическую морфологию, а именно операцию shrink.
В Matlab/Octave это делается одной командой im2=bwmorph(im, "shrink", Inf);
Т.е. сначала вам нужно найти остов (скелет) объектов, а затем в цикле используя look up table делать подстановку по правилам для shrink.