Polygon testing script added along with bug fixes to edge detection
This commit is contained in:
parent
eb2feb67d9
commit
6b5a6a65a4
|
|
@ -25,6 +25,17 @@ def find_polygon_centroid(centers):
|
||||||
centroid_y = np.mean([center[1] for center in centers], axis=0)
|
centroid_y = np.mean([center[1] for center in centers], axis=0)
|
||||||
return centroid_x, centroid_y
|
return centroid_x, centroid_y
|
||||||
|
|
||||||
|
def sort_points_clockwise(centers):
|
||||||
|
"""Sort the points in a clockwise order based on their angles relative to the centroid."""
|
||||||
|
if not centers:
|
||||||
|
return []
|
||||||
|
|
||||||
|
centroid = np.mean(centers, axis=0)
|
||||||
|
def angle_from_centroid(center):
|
||||||
|
return np.arctan2(center[1] - centroid[1], center[0] - centroid[0])
|
||||||
|
sorted_centers = sorted(centers, key=angle_from_centroid)
|
||||||
|
return sorted_centers
|
||||||
|
|
||||||
def image_callback(msg):
|
def image_callback(msg):
|
||||||
global pub, marker_pub
|
global pub, marker_pub
|
||||||
bridge = CvBridge()
|
bridge = CvBridge()
|
||||||
|
|
@ -33,9 +44,10 @@ def image_callback(msg):
|
||||||
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||||
corners, ids, rejected = aruco.detectMarkers(gray, arucoDict)
|
corners, ids, rejected = aruco.detectMarkers(gray, arucoDict)
|
||||||
|
|
||||||
if ids is not None and len(ids) == 4: # Ensure exactly four markers are detected
|
if ids is not None and len(ids) >= 4: # Adjust this condition based on your setup
|
||||||
marker_centers = calculate_marker_centers(corners)
|
marker_centers = calculate_marker_centers(corners)
|
||||||
centerX, centerY = find_polygon_centroid(marker_centers)
|
sorted_centers = sort_points_clockwise(marker_centers)
|
||||||
|
centerX, centerY = find_polygon_centroid(sorted_centers)
|
||||||
|
|
||||||
if centerX is not None and centerY is not None:
|
if centerX is not None and centerY is not None:
|
||||||
origin = Point()
|
origin = Point()
|
||||||
|
|
@ -46,27 +58,27 @@ def image_callback(msg):
|
||||||
|
|
||||||
# Publish the edges of the polygon
|
# Publish the edges of the polygon
|
||||||
marker = Marker()
|
marker = Marker()
|
||||||
marker.header.frame_id = "camera_link" # or your camera frame
|
marker.header.frame_id = "camera_link" # Adjust to your camera frame
|
||||||
marker.header.stamp = rospy.Time.now()
|
marker.header.stamp = rospy.Time.now()
|
||||||
marker.ns = "polygon_edges"
|
marker.ns = "polygon_edges"
|
||||||
marker.id = 0
|
marker.id = 0
|
||||||
marker.type = Marker.LINE_STRIP
|
marker.type = Marker.LINE_STRIP
|
||||||
marker.action = Marker.ADD
|
marker.action = Marker.ADD
|
||||||
marker.scale.x = 0.02 # Adjust the line width as needed
|
marker.scale.x = 0.02 # Line width
|
||||||
marker.color = ColorRGBA(1.0, 0.0, 0.0, 1.0) # Red line
|
marker.color = ColorRGBA(1.0, 0.0, 0.0, 1.0) # Red color
|
||||||
marker.lifetime = rospy.Duration()
|
marker.lifetime = rospy.Duration()
|
||||||
|
|
||||||
# Add points for each marker center
|
# Add points for each sorted marker center
|
||||||
for center in marker_centers:
|
for center in sorted_centers:
|
||||||
p = Point()
|
p = Point()
|
||||||
p.x, p.y = center
|
p.x, p.y = center
|
||||||
p.z = 0 # Assuming a flat surface
|
p.z = 0
|
||||||
marker.points.append(p)
|
marker.points.append(p)
|
||||||
|
|
||||||
# Close the polygon by adding the first point again
|
# Close the polygon by adding the first point again
|
||||||
if marker_centers:
|
if sorted_centers:
|
||||||
p = Point()
|
p = Point()
|
||||||
p.x, p.y = marker_centers[0]
|
p.x, p.y = sorted_centers[0]
|
||||||
p.z = 0
|
p.z = 0
|
||||||
marker.points.append(p)
|
marker.points.append(p)
|
||||||
|
|
||||||
|
|
@ -84,7 +96,7 @@ def main():
|
||||||
global pub, marker_pub, arucoDict
|
global pub, marker_pub, arucoDict
|
||||||
rospy.init_node('aruco_origin_publisher', anonymous=True)
|
rospy.init_node('aruco_origin_publisher', anonymous=True)
|
||||||
pub = rospy.Publisher('/aruco_origin', Point, queue_size=10)
|
pub = rospy.Publisher('/aruco_origin', Point, queue_size=10)
|
||||||
marker_pub = rospy.Publisher('/visualization_marker', Marker, queue_size=10)
|
marker_pub = rospy.Publisher('/polygon_edges', Marker, queue_size=10)
|
||||||
|
|
||||||
# Initialize the ArUco dictionary
|
# Initialize the ArUco dictionary
|
||||||
arucoDict = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)
|
arucoDict = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import rospy
|
||||||
|
from sensor_msgs.msg import Image
|
||||||
|
from geometry_msgs.msg import Point
|
||||||
|
from visualization_msgs.msg import Marker
|
||||||
|
from cv_bridge import CvBridge, CvBridgeError
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class ArucoVisualizer:
|
||||||
|
def __init__(self):
|
||||||
|
self.bridge = CvBridge()
|
||||||
|
self.image_sub = rospy.Subscriber('/camera_image', Image, self.image_callback)
|
||||||
|
self.origin_sub = rospy.Subscriber('/aruco_origin', Point, self.origin_callback)
|
||||||
|
self.edges_sub = rospy.Subscriber('/polygon_edges', Marker, self.edges_callback)
|
||||||
|
|
||||||
|
self.current_frame = None
|
||||||
|
self.origin_point = None
|
||||||
|
self.edge_points = []
|
||||||
|
|
||||||
|
def origin_callback(self, data):
|
||||||
|
"""Callback function for the origin point."""
|
||||||
|
self.origin_point = (int(data.x), int(data.y))
|
||||||
|
|
||||||
|
def edges_callback(self, data):
|
||||||
|
"""Callback function for the polygon edges."""
|
||||||
|
self.edge_points = []
|
||||||
|
if data.type == Marker.LINE_STRIP:
|
||||||
|
for p in data.points:
|
||||||
|
self.edge_points.append((int(p.x), int(p.y)))
|
||||||
|
|
||||||
|
def image_callback(self, data):
|
||||||
|
"""Callback function for camera image."""
|
||||||
|
try:
|
||||||
|
cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
|
||||||
|
self.current_frame = cv_image
|
||||||
|
self.draw_visuals()
|
||||||
|
except CvBridgeError as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
def draw_visuals(self):
|
||||||
|
"""Draw the origin point and polygon edges on the current frame."""
|
||||||
|
if self.current_frame is not None:
|
||||||
|
frame = self.current_frame.copy()
|
||||||
|
# Draw the origin
|
||||||
|
if self.origin_point is not None:
|
||||||
|
cv2.circle(frame, self.origin_point, 5, (0, 255, 0), -1)
|
||||||
|
|
||||||
|
# Draw the edges
|
||||||
|
if len(self.edge_points) > 1:
|
||||||
|
for i in range(len(self.edge_points) - 1):
|
||||||
|
cv2.line(frame, self.edge_points[i], self.edge_points[i + 1], (0, 0, 255), 2)
|
||||||
|
# Optionally, close the polygon
|
||||||
|
cv2.line(frame, self.edge_points[-1], self.edge_points[0], (0, 0, 255), 2)
|
||||||
|
|
||||||
|
# Display the frame
|
||||||
|
cv2.imshow('Aruco Visualizer', frame)
|
||||||
|
cv2.waitKey(1)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
rospy.init_node('aruco_visualizer', anonymous=True)
|
||||||
|
av = ArucoVisualizer()
|
||||||
|
try:
|
||||||
|
rospy.spin()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("Shutting down")
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
Loading…
Reference in New Issue