Monty.Frameworks.Utils.EdgeDetection (ExTbpMonty.Core v0.1.0)

Copy Markdown View Source

Finding the edge in a patch of pixels, and saying which way it points.

Mirrors tbp/monty/frameworks/utils/edge_detection.py. The two functions here are the ones Monty keeps at module level; the detector itself is ...EdgeDetection.EdgeDetector, what it returns is ...EdgeDetection.EdgeFeatures, and the matrix it aggregates is ...EdgeDetection.StructureTensor.

What an edge is here

A structure tensor over a patch of Sobel gradients, weighted towards the centre of the patch and towards pixels where the gradient is strong. Two numbers come out of it: how strong the edge is, and how coherent — one clean direction against a wash of them. An edge is reported when both clear their thresholds, which is why a uniform patch reports nothing at all rather than reporting a weak edge in an arbitrary direction.

The 2-D frame an edge implies

A surface agent moves on a curved surface, so a direction in the image is not a direction on the object. angle_to_pose_2d/4 projects the image direction onto the local tangent plane and expresses it in that plane's frame, which is the basis the 2-D model is built in. TangentFrame carries that basis, and it is transported from step to step rather than recomputed, because a basis that jumped at every step would make the model's coordinates jump with it.

What this port supplies that Monty borrows

Monty reads pixels with OpenCV: cvtColor, Sobel, GaussianBlur. This port has no OpenCV, so ...EdgeDetection.ImageOps writes those three — the same filters, over the same reflection at the patch border, which is what makes the same patch give the same edge.

Summary

Functions

The 2-D pose an image-space edge angle implies, in the local tangent frame.

The identity 2-D frame: normal z, tangent x, and y across it.

Turns a gradient direction into an edge direction, wrapped to [0, 2π).

Functions

angle_to_pose_2d(angle, cam_to_world, surface_normal, tangent_frame)

The 2-D pose an image-space edge angle implies, in the local tangent frame.

The image's x axis and its y axis (pointing down the image) are turned into world directions by the camera's rotation, combined at angle, and projected onto the tangent plane at surface_normal. What comes back is the edge's direction in that plane as [normal, edge_tangent, edge_perpendicular] — the normal always [0, 0, 1], because this is the model's own 2-D frame, not a direction in space.

A world direction that vanishes when projected (an edge seen edge-on) is not a direction at all, so the frame's own first basis vector stands in.

default_surface_pose_vectors_2d()

@spec default_surface_pose_vectors_2d() :: Monty.Geometry.SurfacePoseVectors.t()

The identity 2-D frame: normal z, tangent x, and y across it.

gradient_to_tangent_angle(gradient_angle)

@spec gradient_to_tangent_angle(float()) :: float()

Turns a gradient direction into an edge direction, wrapped to [0, 2π).

An edge runs across its gradient, so a quarter turn. The wrap is what makes the answer an orientation rather than a heading: a gradient pointing slightly below the x-axis gives an edge just below 2π, not a negative angle.