a rotated ellipse
The problem I am working with is trying to find the angle of the semi major axis of an ellipse with x axis. For this, I will have to find the major axis of an ellipse, get the equation of the major axis and then just arc tan of the gradient.
The approach I used in python is:
I first load the image and convert it to grayscale. Then, I binarize the grayscale image using a threshold (pixels above the threshold become white, and pixels below become black). Then iterate through each pixel in the binarized image. If a pixel is black (value 0), I calculate the Euclidean distance between that pixel and the center of mass (centroid) of the ellipse. The max distance will be the major axis and the coordinate of the pixel and the centre will be the two coordinates I can work with to get an equation of the major axis and theta. The problem is that I made a picture in powerpoint, rotated it to approximately 25 degrees but the answer I am getting is around 30 degrees so I dont know where I am going wrong. Can someone please help me.
import cv2
import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt
import math
def euclidean_distance(a, row, col):
"""
Calculates the Euclidean distance between two points.
Args:
a (tuple): Center of mass (x, y).
row (int): Row index of the pixel.
col (int): Column index of the pixel.
Returns:
float: Euclidean distance.
"""
return np.sqrt((a[0] - col) ** 2 + (a[1] - row) ** 2)
def angle(a, row, col):
"""
Calculates the angle between the major axis and the x-axis.
Args:
a (tuple): Center of mass (x, y).
row (int): Row index of the pixel.
col (int): Column index of the pixel.
Returns:
float: Angle in degrees.
"""
slope = (a[0] - col) / (a[1] - row)
return math.atan(slope)
# Load the image
image_path = "/Users/yahya2/Desktop/xy1.png"
img = cv2.imread(image_path)
a = ndimage.center_of_mass(img)
# Convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Binarize the grayscale image
_, img_bin = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY)
# Get the dimensions of the image
rows, cols = img_bin.shape
max_length = 0
max_row, max_col = 0, 0
# Loop through each pixel in the image
for row in range(rows):
for col in range(cols):
# Check if the pixel is black (0)
if img_bin[row, col] == 0:
length = euclidean_distance(a, row, col)
if length > max_length:
max_length = length
max_row, max_col = row, col
# Calculate the angle
major_axis_angle = angle(a, max_row, max_col)
print(f"Major axis angle (degrees): {major_axis_angle:.2f}")
# Visualize the result
fig, ax = plt.subplots(figsize=(8, 8))
ax.imshow(img, cmap='gray')
plt.scatter(max_col, max_row, color='red', marker='x', s=100)
plt.show()
yahya ashraf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.