Distance between two Aruco Markers in Python? - python

I am trying to calculate the distance between two Aruco markers in Python. I have code that can calculate the pose of one marker but I am not sure how to move from there. Is there anyone that has done something similar or can point me in the right direction?
Thank you!

You can find the distance between the markers by calculating the distance between the corners of the detected markers.
The following will give you the corners and the co-ordinates of that corner.
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, aruco_dict, parameters=arucoParameters)
x1 = int (corners[0][0][0][0])
y1 = int (corners[0][0][0][1])
Similarly you can find the co-ordinates of the corner of the other marker (x2,y2).
import math
def calculateDistance(x1,y1,x2,y2):
dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
return dist
print calculateDistance(x1, y1, x2, y2)
This code will give the distance between the two corners

Related

Determine if points are within ellipse (Python and Pillow)

Using PIL, I've drawn an ellipse using the square coordinates around the circle (ie, the X and Y coordinates of the shape if it were a square).
I want to determine if coordinates I pass in are within the range of the coordinates of the ellipse. If this were a square, I imagine this would be relatively easy, as I could simply ask the script to determine if the coordinates (x and y) are between the range of x and y coordinates of the square.
However, because it's an ellipse, I do not know the coordinates of the lines produced by the arc. For this reason, I believe I need a PIL solution to give me the range of the ellipse line first. Does this exist natively in PIL?
Full handwork solution incoming
Since an ellipse is just a "stuffed circle", one could resize the ellipse to be a circle and move on from there.
You have the coordinates, so the first step is to resize.
x_diff = abs(x_max - x_min)
x = (x - x_min ) / x_diff
y_diff = abs(y_max - y_min)
y = (y - y_min ) / y_diff
This resizes the ellipse to a circle with radius .5.
Using Pythagora's theorem, the distance to (0, 0) should be lower than the distances to the x and y axis, each squared. So a² + b² = c² becomes c <= sqrt(a² + b²). And since we have scaled the ellipse to a circle with radius 0.5, we can assume, that c has to be smaller or equal to 0.5.
import math
c = math.sqrt(x**2 + y**2)
if c <= .5:
print("Coordinate lies within ellipse!")
else:
print("Try again :(")

How can I retrieve the center of a rotated ellipse from a pyqtgraph EllipseROI?

I would like to find the center of an ellipse created using the pyqtgraph EllipseROI, generated using the following command:
import pyqtgraph as pg
...
ellipse = pg.EllipseROI(pos = [200, 200], size=125, pen='r', movable=True)
Once a user moves and rotates the ellipse, some information can be retrieved from the handles to determine the new position:
x0=ellipse.pos().x()
y0=ellipse.pos().y()
width=ellipse.size()[0]
height=ellipse.size()[1]
angle=ellipse.angle()
It looks like the width and height values correspond to the rectangular region surrounding the non-rotated ellipse:
In the above images, the black pixels represent the following points (from lower left, proceeding counter-clockwise):
[x0, y0]
[x0+width, y0]
[x0+width, y0+height]
[x0, y0+height]
The center for the ellipse with angle=0 is simply [x0+width/2, y0+height/2]. For a rotated ellipse, I can find the center by rotating the center of the ellipse corresponding to angle=0 about the point [x0, y0]:
import numpy as np
...
center_x0 = x0+width/2.0
center_y0 = y0+height/2.0
center_x = x0 + np.cos(np.radians(angle)) * (center_x0 - x0) - np.sin(np.radians(angle)) * (x0 - center_x0)
center_y = y0 + np.sin(np.radians(angle)) * (center_x0 - x0) + np.cos(np.radians(angle)) * (center_y - y0)
Am I missing a simple solution to quickly retrieve the center position from the EllipseROI (or any pyqtgraph ROI) that does not first require retrieving the bounding box points of an non-rotated ROI and then rotating their center? I would like to minimize the delay between when the user adjusts the ROI and subsequent displays in the viewbox (that rely on the center point), and the method I am currently using seems like an inefficient way to calculate the center.

Draw precise circle through two points

I am programming an application for high precision measurements. Now I have a problem.
User can select a segment on axis X that would represent diameter of a circle.
How do I draw the circle in question through two selected end points if the selected diameter has even pixel length
In this case origin of the circle would be between two pixels, which would make me choose one of them, thus shifting the circle one pixel left or right.
It is true, the look wouldn't change because one pixel will be included and another added on the other side of selected segment, but what if I need to draw a square based on the segment's length around the area first.
Then circle and square would touch in wrong places.
What is usually done in this circumstances?
ImageDraw.Draw.ellipse takes a bounding box as a parameter. It doesn't care where the center of the circle goes.
The circle outline includes all 4 edges of the bounding box in the tests I performed. I suggest you do your own tests too.
Calculating the bounding box from two arbitrary points is easy, once you have the diameter and center of the circle.
diameter = ((x2 - x1)**2 + (y2 - y1)**2) ** 0.5
radius = diameter / 2
xC, yC = (x1 + x2) / 2.0, (y1 + y2) / 2.0
bbox = [round(xC - radius), round(yC - radius), round(xC + radius), round(yC + radius)]

OpenCV - Creating an Ellipse shaped mask in python

I've extracted a Circle shaped mask from an image in OpenCV. I used the following code for the same:
H, W = img.shape
x, y = np.meshgrid(np.arange(W), np.arange(H))**
d2 = (x - xc)**2 + (y - yc)**2**
mask = d2 < r **2**
And, used the mask value to find the average color outside the circle.
outside = np.ma.masked_where(mask, img)**
average_color = outside.mean()**
I want to extract an Ellipse from an image in the same above process in OpenCV Python.
Thank You.
Drawing Ellipse
To draw the ellipse, we need to pass several arguments. One argument is the center location (x,y). Next argument is axes lengths (major axis length, minor axis length). angle is the angle of rotation of ellipse in anti-clockwise direction. startAngle and endAngle denotes the starting and ending of ellipse arc measured in clockwise direction from major axis. i.e. giving values 0 and 360 gives the full ellipse. For more details, check the documentation of cv2.ellipse(). Below example draws a half ellipse at the center of the image.
cv2.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
Taken from Miki's Link in the Question Comments

Python angle calculation for image rotation

I am working on an application which first needs to rotate an image slightly in order to deskew it.
I have detected a vertical line down the image between two points (x1, y1) and (x2,y2). The vertical line is not entirely vertical - the second x coordinate is slightly less or slightly more than the top x and therefore the line has a slope.
I am trying to calculate the angle of the slope of the line so that I can rotate the image and then re-detect the line so that it is perfectly vertical. I am using OpenCV in Python for this.
Unfortunately I am having problems calculating the slope of the line and the rotation of the image is therefore inaccurate.
My function to detect the slope of the vertical line in the image is as follows:
def find_vert_angles(vertical_line_candidates, vertical_line_candidates2, roi_x_coordinates, roi_x_coordinates2):
line_angles_radians = []
for line_x, line_x2 in itertools.izip(vertical_line_candidates, vertical_line_candidates2):
x_diff = line_x2 - line_x
y_diff = roi_x_coordinates[1][1] - roi_x_coordinates[0][1]
if x_diff != 0:
slope = y_diff / x_diff
angle_in_radians = atan(slope)
line_angles_radians.append(angle_in_radians)
else:
line_angles_radians.append(0)
return line_angles_radians
My code to rotate the image so that the line can be vertical is as follows:
skew_angle = degrees(vert_angle[1])
print "Detected skew angle is " + str(skew_angle) + " degrees"
warp = cv2.getRotationMatrix2D((img_width/2,img_height/2),skew_angle,1)
image = cv2.warpAffine(image,warp,(img_width,img_height))
But the angles of rotation are coming out as 249 degrees, 89 degrees etc. when they should just be a few degrees each way.
If anyone can help me find a solution to this problem so that I can correct the skew of the image correctly, that would be much appreciated.
I believe you're finding the angle that's complementary to the one you want.
A nearly vertical line will have a very small angle with respect to the y-axis, but a near 90-degree angle with respect to the x-axis.
Consider your line segment to be the hypotenuse of a right triangle. The angle it forms with respect to the x-axis is atan((y2-y1)/(x2-x1)). The angle with respect to the y-axis, which I think is what you want to rotate should be atan((x2-x1)/(y2-y1))

Categories