user6038900
user6038900

Reputation:

Finding the midpoint of the rotated rectangle

I would like to find the midpoint of a rotated rectangle. The rotated rectangle has got the following coordinate

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

I have got the following code to determine

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

Unfortunately, the center doesn't correspond to the actual center. How do I find the exact center of the above coordinates?

Upvotes: 1

Views: 3371

Answers (4)

gelonida
gelonida

Reputation: 5630

There are several issues.

1.) The points are not ordered correctly for your formula to work. I guess they should be ordered like: (points should be ordered such, that you have a line of the rectangle between two points that are adjacent in the list and the last and first entry in the list)

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

2.) There is a mistake in your formula. (I guess the formula should be the one, that finds the mid point of a line or in this case the midpoint of a diagonal between point 0 and point 2).

It should be

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

For a rectangle cx, cy will be identical regardless of whether you use idx1=0, idx2=2 or idx1=1, idx2=3

3.) This formula (midpoint of a diagonal) determines the centroid only for rectangles. What you have is a quadrangle, which is almost, but not exactly a rectangle, so the formula does not apply at all.

Try to calculate cx, cy with idx1, idx2 = 0, 2 and with idx1, idx2 = 1, 3 and you see, that you get different results. Thus you do not have a rectangle.

Either there is a typo in the coordinates, that you posted, or perhaps there is an error in the formula that calculated your rectangle or your question really meant to calculate the centroid of a quadrangle, which is different. In that case it might be advisable to adapt the title of the question

You can find the formula for a polygon here https://en.wikipedia.org/wiki/Centroid#Of_a_polygon

Upvotes: 0

Prune
Prune

Reputation: 77837

The centroid of a rectangle is the midpoint of either diagonal. You used different point pairs for your two coordinate computations. Also note that, for some reason, the points are not in the usual, adjacent order. The diagonals are points 1 & 2, 0 & 3. Use either pair, such as:

# 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

Better yet, research some simple shape modules. Most of these will have a straightforward midpoint method.

Upvotes: 2

stateMachine
stateMachine

Reputation: 5805

I’m not sure if I’m following you, man, but if you want to calculate the centroid of a rectangle shape, it goes like this. Suppose you have the following rectangle aligned to the origin. The centroid is shown in green.

enter image description here

The centroid is computed as:

Cx = 0.5 * w
Cy = 0.5 * h

You can then apply a linear transformation. In this example, a rotation matrix, which is given as:

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

The rectangle is now rotated from the original coordinate system. That’s the angle ϴ:

enter image description here

The centroid equations become:

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

Translating back to the coordinate original system, we’ve got:

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

The function should be something like this (in pseudo-code):

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 );
}

Upvotes: 0

nathancy
nathancy

Reputation: 46600

You can find the midpoint of a rotated rectangle (the centroid) with cv2.minAreaRect. The function returns the following information:

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

Here's a simple example. Input image:

enter image description here

Result with the centroid highlighted in green

enter image description here

Coordinates

(157.6988067626953, 132.07565307617188)

Code

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()

Upvotes: 0

Related Questions