Pure MoonBit fiducial marker detection, perspective normalization, ArUco/AprilTag grid decoding, error correction, and 3D pose estimation library.
moon add 2515050242/fiducial_marker
moon check --target all
moon test --target allmoon run cmd/marker_cli| Resolution | Dimensions | Frame Latency (ms) | Throughput (FPS) | Detection Rate |
| :--- | :--- | :--- | :--- | :--- |
| QVGA | 320x240 | 15.97 | 62 | 100% |
| VGA | 640x480 | 57.56 | 17 | 100% |core types and matrices
|
image + filtering + morphology
|
contours + corners + quadrilateral extraction
|
homography + perspective sampling + dictionary decoding
|
pose, calibration, board, tracking, optical flow, and I/O
|
cmd/marker_climoon fmt --check
moon check --target all
moon info
moon test --target all
moon run cmd/marker_clifn BenchmarkResult::new(resolution_name : String, width : Int, height : Int, iterations : Int, total_time_ms : Double, successful_iterations? : Int) -> BenchmarkResultpub(all) struct BundleAdjustmentProblem {
camera_intrinsics : CameraIntrinsics
camera_poses : Array[Pose3D]
points_3d : Array[Point3D]
observations : Array[BaObservation]
} derive(Eq, Debug)fn CalibrationFrame::new(object_points : Array[Point3D], image_points : Array[Point2D]) -> CalibrationFramepub(all) struct CameraCalibrator {
image_size : Size2D
frames : Array[CalibrationFrame]
} derive(Eq, Debug)fn CameraCalibrator::add_frame(self : CameraCalibrator, object_points : Array[Point3D], image_points : Array[Point2D]) -> Unitfn CameraIntrinsics::with_distortion(fx : Double, fy : Double, cx : Double, cy : Double, k1 : Double, k2 : Double, p1 : Double, p2 : Double, k3 : Double) -> CameraIntrinsicsfn CharucoBoard::new(squares_x : Int, squares_y : Int, square_length : Double, marker_length : Double, dictionary : MarkerDictionary) -> CharucoBoardfn ConnectedComponent::new(label : Int, area : Int, bounding_box : Rect2D, centroid : Point2D) -> ConnectedComponentfn DenseMatrix::submatrix(self : DenseMatrix, r0 : Int, c0 : Int, r1 : Int, c1 : Int) -> DenseMatrixfn DenseMatrix::svd(self : DenseMatrix, max_iterations? : Int, epsilon? : Double) -> (DenseMatrix, Array[Double], DenseMatrix)?pub(all) struct DetectorParameters {
adaptive_thresh_win_size_min : Int
adaptive_thresh_win_size_max : Int
adaptive_thresh_win_size_step : Int
adaptive_thresh_constant : Int
min_marker_perimeter_rate : Double
max_marker_perimeter_rate : Double
polygonal_approx_accuracy_rate : Double
min_corner_distance_rate : Double
min_distance_to_border : Int
min_marker_distance_rate : Double
corner_refinement_method : Int
corner_refinement_win_size : Int
corner_refinement_max_iterations : Int
corner_refinement_min_accuracy : Double
perspective_remove_pixel_per_cell : Int
perspective_remove_ignored_margin_per_cell : Double
max_erroneous_bits_in_border_rate : Double
min_otsu_std_dev : Double
error_correction_rate : Double
} derive(Eq, Debug)pub(all) struct ExtendedKalmanFilter6DOF {
state : Array[Double]
covariance : DenseMatrix
process_noise : DenseMatrix
measurement_noise : DenseMatrix
} derive(Eq, Debug)fn ExtendedKalmanFilter6DOF::new(initial_pose : Pose3D, pos_process_noise? : Double, rot_process_noise? : Double, pos_meas_noise? : Double, rot_meas_noise? : Double) -> ExtendedKalmanFilter6DOFfn ExtendedKalmanFilter6DOF::update(self : ExtendedKalmanFilter6DOF, measured_pose : Pose3D) -> Unitfn GridBoard::new(markers_x : Int, markers_y : Int, marker_length : Double, marker_separation : Double, dictionary : MarkerDictionary, first_marker_id? : Int) -> GridBoardpub(all) struct KalmanFilter3D {
state_dim : Int
state : Array[Double]
covariance : DenseMatrix
process_noise : DenseMatrix
measurement_noise : DenseMatrix
} derive(Eq, Debug)fn KalmanFilter3D::new_constant_velocity(initial_position : Point3D, process_noise_std? : Double, measurement_noise_std? : Double) -> KalmanFilter3Dfn LineSegment::new(p1 : Point2D, p2 : Point2D, width : Double, p_val : Double, nfa : Double) -> LineSegmentfn MarkerDictionary::find_best_match(self : MarkerDictionary, candidate_bits : Int64) -> (Int, Int, Int)?pub(all) struct MarkerTrack {
track_id : Int
marker_id : Int
state : TrackState
filter : ExtendedKalmanFilter6DOF
hits : Int
age : Int
lost_frames : Int
history : Array[Point3D]
} derive(Debug)pub(all) struct MultiMarkerTracker {
tracks : Array[MarkerTrack]
next_track_id : Int
max_lost_frames : Int
min_hits_to_confirm : Int
} derive(Debug)fn MultiMarkerTracker::new(max_lost_frames? : Int, min_hits_to_confirm? : Int) -> MultiMarkerTrackerfn MultiMarkerTracker::update(self : MultiMarkerTracker, detections : Array[MarkerDetection], dt? : Double) -> Array[MarkerTrack]fn OpticalFlowTracker::new(win_size? : Int, max_level? : Int, max_iterations? : Int, epsilon? : Double, min_eigen_threshold? : Double) -> OpticalFlowTrackerfn OpticalFlowTracker::track_points(self : OpticalFlowTracker, prev_img : Image, next_img : Image, prev_points : Array[Point2D]) -> (Array[Point2D], Array[Bool], Array[Double])fn PerformanceStats::new(fps : Double, frame_latency_ms : Double, threshold_time_ms : Double, contour_time_ms : Double, decode_time_ms : Double, pose_time_ms : Double, num_markers_detected : Int) -> PerformanceStatspub(all) struct StereoCameraRig {
left_camera : CameraIntrinsics
right_camera : CameraIntrinsics
baseline : Double
right_to_left_pose : Pose3D
} derive(Eq, Debug)fn StereoCameraRig::estimate_marker_pose_stereo(self : StereoCameraRig, left_quad : Quad, right_quad : Quad, marker_length : Double) -> Pose3D?fn StereoCameraRig::triangulate_point(self : StereoCameraRig, left_pixel : Point2D, right_pixel : Point2D) -> Point3D?pub(all) struct StructuringElement {
shape : MorphShape
radius : Int
width : Int
height : Int
data : Array[Bool]
} derive(Eq, Debug)pub(all) struct SyntheticDatasetGenerator {
camera : CameraIntrinsics
dictionary : MarkerDictionary
marker_length : Double
image_size : Size2D
} derive(Eq, Debug)fn SyntheticDatasetGenerator::generate_distance_sweep(self : SyntheticDatasetGenerator, marker_id : Int, min_dist : Double, max_dist : Double, num_steps : Int) -> Array[SyntheticEvaluationFrame]fn SyntheticDatasetGenerator::new(camera : CameraIntrinsics, dictionary : MarkerDictionary, marker_length? : Double, image_size? : Size2D) -> SyntheticDatasetGeneratorpub(all) struct SyntheticSceneConfig {
image_size : Size2D
camera : CameraIntrinsics
marker_id : Int
dictionary : MarkerDictionary
marker_length : Double
pose : Pose3D
noise_std : Double
lighting_ambient : Double
lighting_diffuse : Double
} derive(Eq, Debug)fn SyntheticSceneConfig::default(marker_id : Int, dictionary : MarkerDictionary) -> SyntheticSceneConfigpub(all) struct VideoStreamPipeline {
capacity : Int
frames : Array[VideoFrame]
detector_params : DetectorParameters
dictionary : MarkerDictionary
tracker : MultiMarkerTracker
camera : CameraIntrinsics?
marker_length : Double
} derive(Debug)fn VideoStreamPipeline::new(dictionary : MarkerDictionary, capacity? : Int, camera? : CameraIntrinsics?, marker_length? : Double) -> VideoStreamPipelinefn VideoStreamPipeline::process_frame(self : VideoStreamPipeline, frame : VideoFrame) -> Array[MarkerTrack]fn backproject_pixel_to_ray(pixel : Point2D, pose : Pose3D, camera : CameraIntrinsics) -> (Point3D, Point3D)fn compute_hamming_distance(val1 : Int64, val2 : Int64) -> Intfn compute_reprojection_metrics(object_points : Array[Point3D], image_points : Array[Point2D], pose : Pose3D, camera : CameraIntrinsics) -> ReprojectionMetricsfn connected_components(binary_img : Image, connectivity_8? : Bool) -> (Array[Int], Array[ConnectedComponent])fn detect_diamond_markers(detections : Array[MarkerDetection], square_length : Double, marker_length : Double, camera? : CameraIntrinsics) -> Array[DiamondDetection]fn detect_harris_corners(img : Image, k_param? : Double, threshold? : Double, nms_radius? : Int) -> Array[CornerPoint]fn detect_line_segments(img : Image, min_length? : Double, gradient_threshold? : Double) -> Array[LineSegment]fn detect_markers_with_params(img : Image, dict : MarkerDictionary, params : DetectorParameters, camera_matrix? : CameraIntrinsics?, marker_length? : Double) -> Array[MarkerDetection]fn detect_shi_tomasi_corners(img : Image, threshold? : Double, nms_radius? : Int) -> Array[CornerPoint]fn estimate_board_pose(board : GridBoard, detections : Array[MarkerDetection], camera : CameraIntrinsics) -> Pose3D?fn find_homography_ransac(src_pts : Array[Point2D], dst_pts : Array[Point2D], max_iterations? : Int, inlier_threshold? : Double, _confidence? : Double, seed? : Int) -> RansacHomographyResult?fn generate_custom_dictionary(name : String, grid_size : Int, num_markers : Int, min_hamming_distance : Int, seed? : Int) -> MarkerDictionaryfn generate_synthetic_marker_image(id : Int, dict : MarkerDictionary, marker_pixel_size : Int, margin_pixels : Int) -> Image?fn interpolate_charuco_corners(img : Image, board : CharucoBoard, marker_detections : Array[MarkerDetection], camera? : CameraIntrinsics) -> CharucoCornersfn query_integral_sum(integral : Array[Int], w : Int, _h : Int, x0 : Int, y0 : Int, x1 : Int, y1 : Int) -> Intfn render_detection_svg(img : Image, detections : Array[MarkerDetection], camera : CameraIntrinsics?, axis_length : Double) -> Stringfn render_terminal_dashboard(stats : PerformanceStats, active_tracks : Array[MarkerTrack]) -> Stringfn rotate_apriltag_16h5_bits(bits : Int64) -> Int64fn rotate_bits_90(bits : Int64, grid_size : Int) -> Int64fn run_resolution_benchmark(res_name : String, width : Int, height : Int, iterations : Int) -> BenchmarkResultfn sample_cell_intensity_multisample(sampled_grid : Image, cell_r : Int, cell_c : Int, total_cells : Int, samples_per_dim? : Int) -> Doublefn sample_payload_bits(sampled_grid : Image, dict : MarkerDictionary, binary_threshold : Int) -> Int64fn shape_circularity(area : Double, perimeter : Double) -> Doublefn solve_pnp_ippe(object_points : Array[Point3D], image_points : Array[Point2D], camera : CameraIntrinsics) -> IppeResult?fn solve_pnp_ransac(object_points : Array[Point3D], image_points : Array[Point2D], camera : CameraIntrinsics, max_iterations? : Int, inlier_threshold? : Double, seed? : Int) -> RansacPnpResult?fn verify_quiet_zone(sampled_grid : Image, total_cells : Int, white_threshold? : Int, min_white_rate? : Double) -> Boolfn warp_perspective_color(src : ColorImage, h_mat : Matrix3x3, dst_width : Int, dst_height : Int) -> ColorImageInstall
Download zipPure MoonBit fiducial marker detection, perspective normalization, ArUco/AprilTag grid decoding, error correction, and 3D pose estimation library.