So essentially my question was to find the angle of the semi major axis of an ellipse. to do this, i used the following method:
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.
This is the result I am getting which makes sense.
What does not make sense is the coordinates of the max point and the COM. the COM coordinates are around 500,500 whereas the max point coordinates are around 270,1000. But shouldnt the coordinates of the max point be greater than the COM coordinates? If we imagine a line joining the two crosses then the gradient of these two crosses should be positive but using these i am getting a negative answer. I feel the problem is because the y axis is starting from top left corner and x axis from bottom left corner. How do I fix this?
import cv2
import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt
import math
def euclidean_distance(a, row, col):
return ((a[1] - col) ** 2 + (a[0] - row) ** 2)
def angle(a, row, col):
slope = (a[0] - row) / (a[1] - col)
return math.atan(slope)
# Load the image
image_path = "/Users/yahya2/Desktop/Screenshot 2024-05-29 at 1.17.34 AM.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
print(a[1],a[0])
print(max_col,max_row)
# Calculate the angle
major_axis_angle = angle(a, max_row, max_col)
# 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.scatter(a[1], a[0], color='red', marker='x', s=100)
plt.show()
print(major_axis_angle)
yahya ashraf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.