Нахождение средней точки повернутого прямоугольника - PullRequest
1 голос
/ 07 марта 2020

Я бы хотел найти середину повернутого прямоугольника. Вращенный прямоугольник имеет следующую координату

[[317, 80], [183, 291], [479, 150], [378, 387]]

У меня есть следующий код для определения

cx = (coord[0][0] + coord[2][0])//2
cy = (coord[0][1] + coord[1][1])//2

К сожалению, центр не соответствует фактическому центру. Как мне найти точный центр вышеуказанных координат?

Ответы [ 4 ]

2 голосов
/ 07 марта 2020

Центроид прямоугольника - это середина любой диагонали. Вы использовали разные пары точек для двух ваших координатных вычислений. Также обратите внимание, что по какой-то причине точки не в обычном соседнем порядке. Диагонали - это точки 1 и 2, 0 и 3. Используйте любую пару, например:

# Variables to make the computations easier to read
pt1 = 1
pt2 = 2
x = 0
y = 1
cx = (coord[pt1][x] + coord[pt2][x])//2
cy = (coord[pt1][y] + coord[pt2][y])//2

Еще лучше, исследуйте несколько простых модулей формы. У большинства из них будет простой midpoint метод.

0 голосов
/ 07 марта 2020

Я не уверен, что слежу за тобой, чувак, но если ты хочешь вычислить центроид прямоугольной формы, все будет так. Предположим, у вас есть следующий прямоугольник, выровненный по началу координат. Центроид показан зеленым цветом.

enter image description here

Центроид вычисляется как:

Cx = 0.5 * w
Cy = 0.5 * h

Затем можно применить линейное преобразование , В этом примере матрица вращения, которая задается как:

R = [ cos ϴ, -sin ϴ
      sin ϴ,  cos ϴ ]

Прямоугольник теперь вращается из исходной системы координат. Это угол ϴ:

enter image description here

Уравнения центроида становятся:

Cx’ = cx cos ϴ - cy sin ϴ
Cy’ = cx sin ϴ + cy cos ϴ

Переводя обратно в исходную систему координат, мы Вы получили:

Cx’’ = x + cx cos ϴ - cy sin ϴ
Cy’’ = y + cx sin ϴ + cy cos ϴ

Функция должна быть примерно такой (в псевдокоде):

Tuple computeRotatedCentroid( x, y, width, height, theta ) {
    cx = 0.5 * width;
    cy = 0.5 * height;

    thetaRadians = degreesToRadians(theta);

    cosTheta = cos( thetaRadians );
    sinTheta = sin( thetaRadians );

    finalCx = x + cx * cosTheta - cy * sinTheta;
    finalCy = y + cx * sinTheta + cy * cosTheta;

    return makeTuple( finalCx, finalCy );
}
0 голосов
/ 07 марта 2020

Есть несколько проблем.

1.) Точки не упорядочены правильно для вашей формулы для работы. Я предполагаю, что они должны быть упорядочены следующим образом: (точки должны быть упорядочены так, чтобы у вас была линия прямоугольника между двумя точками, смежными в списке, и последней и первой записью в списке)

points = [[183, 291], [378, 387], [479, 150], [317, 80]]

2.) В вашей формуле есть ошибка. (Я предполагаю, что формула должна быть такой, которая находит среднюю точку линии или в этом случае среднюю точку диагонали между точкой 0 и точкой 2).

Это должно быть

cx = (coord[idx1][0] + coord[idx2][0]) / 2
cy = (coord[idx1][1] + coord[idx2][1]) / 2

where idx1, idx2 are either 0,2 or 1,3

Для прямоугольника cx cy будет одинаковым независимо от того, используете ли вы idx1 = 0, idx2 = 2 или idx1 = 1, idx2 = 3

3.) Эта формула (середина диагонали) определяет центроид только для прямоугольников. То, что у вас есть, это четырехугольник, который почти, но не совсем прямоугольник, поэтому формула не применяется вообще.

Попробуйте вычислить cx, cy с idx1, idx2 = 0, 2 и с idx1, idx2 = 1, 3, и вы увидите, что вы получаете разные результаты. Таким образом, у вас нет прямоугольника.

Либо есть опечатка в координатах, которую вы разместили, либо, возможно, ошибка в формуле, которая вычислила ваш прямоугольник, или ваш вопрос действительно предназначен для вычисления центроида четырехугольник, который отличается. В этом случае было бы целесообразно изменить название вопроса

Вы можете найти формулу для многоугольника здесь https://en.wikipedia.org/wiki/Centroid#Of_a_polygon

0 голосов
/ 07 марта 2020

Вы можете найти среднюю точку повернутого прямоугольника (центроид) с помощью cv2.minAreaRect. Функция возвращает следующую информацию:

(centroid, (width, height), angle) = cv2.minAreaRect(cnts)

Вот простой пример. Исходное изображение:

enter image description here

Результат с выделенным центроидом зеленым цветом

enter image description here

Координаты

(157.6988067626953, 132.07565307617188)

Код

import cv2
import numpy as np

# Load image, grayscale, Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours and find centroid information on rotated rectangle
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
centroid, dimensions, angle = cv2.minAreaRect(cnts[0])
cv2.circle(image, (int(centroid[0]), int(centroid[1])), 5, (36,255,12), -1)

print(centroid)

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()
...