# Where is the rotated angle actually located in fitEllipse method?

Main task: I fit the ellipse using the fitEllipse() method and then I'd like to count the rotation angle between the horizontal axis and the major axis of the generated ellipse. I'm going to do this using the 3rd returned argument from the fitEllipse() method - $$\theta$$ (rotation angle).

Main issue: I can't find exact information about which axes this angle is located between.

Other: If I'm right the length of minor axis and the length of major axis in ellipse it's the same lengths as two sides in a rotated rectangle.

Sources:

1. From documentation here (section nb. 9) it seems that this angle is between horizontal axis and the first side how it's written in CvBox2D section. So, it means that the angle can be between the horizontal axis and minor or major axis. But:
2. In this article (section 3) the first example is good but in the 2nd example the angle should be between horizontal axis and height instead of width (referring to my aforementioned first point).
3. In this article it shows that the angle is between vertical axis and one side of rectangle.

So, where is the rotated angle located in fitEllipse() method?

Any hints how it works are welcome.

I've implemented the following simple code:

import cv2
import numpy as np

nr_im = 9876
font = cv2.FONT_HERSHEY_SIMPLEX
fontScale = 1
colorText = (0, 0, 255)
thickness = 2

img = cv2.imread('testing/' + str(nr_im) + '.jpg')
original = img.copy()
blured_img = cv2.GaussianBlur(img,(17,17),5)

image = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower = np.array([0, 0, 140], dtype="uint8")
upper = np.array([0, 0, 255], dtype="uint8")
mask = cv2.inRange(image, lower, upper)

# Morphological Closing: Get rid of the noise inside the object
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (25, 25)))

# Find contours
cnts, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

print(len(cnts))

cntsElps = []
for num_cnt, cnt in enumerate(cnts):
genElipse = cv2.fitEllipse(cnt)
cntsElps.append(genElipse)
cv2.ellipse(original,genElipse,(0,255,0),2)
cv2.putText(original, str(num_cnt+1), (int(genElipse[0][0]),int(genElipse[0][1])), font, fontScale, colorText, thickness, cv2.LINE_AA)
print("Ellipse nb: " + str(num_cnt+1) + " has angle: " + str(genElipse[2]) + "\n")

cv2.imwrite('testing/' + str(nr_im) + '_' + 'trash2' + '.png', original)

And I used this image as example:

I've got the following image result:

And the rotation angle for each ellipse was:

1. Ellipse nb: 1 has angle: 55.63788986206055
2. Ellipse nb: 2 has angle: 108.58539581298828
3. Ellipse nb: 3 has angle: 170.23861694335938
4. Ellipse nb: 4 has angle: 73.59089660644531

So, my conclusion is that an angle between horizontal axis and major side of rectangle(=major ellipse axis) is the rotation angle in fitEllipse() method.