Documentation
¶
Overview ¶
Package registration provides experimental FFT-based image registration through phase correlation.
NewCorrelator creates the package's only long-lived public resource. With no options it prefers the direct Vulkan implementation and falls back to the CPU reference implementation. WithBackend can require either backend, while WithDevice borrows an existing root Device without closing it. A Correlator owns the resources it creates; callers must close it when it is no longer needed.
PhaseCorrelate accepts two equal-sized images and blocks until registration finishes. It estimates the rotation, scale, and translation that map image A to image B. The operation converts non-RGBA inputs internally and does not mutate either source image. A Correlator is not safe for concurrent method calls.
The CPU path is the portability and correctness reference. The direct Vulkan path is cgo-free and has runtime evidence on Linux. The registration API and numerical behavior remain experimental.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrLowConfidence = errors.New("registration: phase-correlation match confidence is too low")
ErrLowConfidence indicates that at least one phase-correlation peak did not meet the validity threshold described by Reddy and Chatterji.
Functions ¶
This section is empty.
Types ¶
type Correlator ¶
type Correlator struct {
// contains filtered or unexported fields
}
Correlator performs log-polar phase correlation on a GPU or CPU backend.
func NewCorrelator ¶
func NewCorrelator(maxW, maxH int, options ...Option) (*Correlator, error)
NewCorrelator creates a correlator. With no options it prefers direct Vulkan and falls back to CPU if Vulkan initialization or resource creation fails.
Example ¶
package main
import (
"image"
"github.com/srlehn/vulki/registration"
)
func main() {
correlator, err := registration.NewCorrelator(1024, 1024)
if err != nil {
return
}
defer correlator.Close()
imageA := image.NewNRGBA(image.Rect(0, 0, 1024, 1024))
imageB := image.NewNRGBA(image.Rect(0, 0, 1024, 1024))
_, _ = correlator.PhaseCorrelate(imageA, imageB)
}
Output:
Example (BorrowedDevice) ¶
package main
import (
"github.com/srlehn/vulki"
"github.com/srlehn/vulki/registration"
)
func main() {
device, err := vulki.Open()
if err != nil {
return
}
defer device.Close()
correlator, err := registration.NewCorrelator(
1024,
1024,
registration.WithDevice(device),
)
if err != nil {
return
}
defer correlator.Close()
}
Output:
Example (Cpu) ¶
package main
import (
"github.com/srlehn/vulki/registration"
)
func main() {
correlator, err := registration.NewCorrelator(
1024,
1024,
registration.WithBackend(registration.BackendCPU),
)
if err != nil {
return
}
defer correlator.Close()
}
Output:
func (*Correlator) Backend ¶
func (c *Correlator) Backend() Backend
Backend reports the implementation selected for this correlator.
func (*Correlator) Close ¶
func (c *Correlator) Close() error
Close releases resources owned by the Correlator. Cleanup continues after an error, and repeated calls return nil. A borrowed Device is never closed.
func (*Correlator) FallbackReason ¶
func (c *Correlator) FallbackReason() error
FallbackReason reports why an automatic correlator selected the CPU. It is nil for explicit CPU correlators and correlators using the GPU.
func (*Correlator) PhaseCorrelate ¶
func (c *Correlator) PhaseCorrelate(imgA, imgB image.Image) (*Result, error)
PhaseCorrelate recovers the transform that maps image A to image B. Following Reddy & Chatterji (1996):
Phase 1: FFT → magnitude → highpass → log-polar → FFT → cross-power → IFFT → peak → angle/scale
Phase 2: transform image A by detected angle/scale, phase correlate with B for translation
Try both angle and angle+180° (magnitude spectrum has 180° symmetry), pick higher peak.
RGBA inputs are used directly. Other image implementations are converted to RGBA before processing. The Vulkan path stages packed pixels once per image, then submits both uploads, the entire GPU pipeline, and a 64-byte result readback as one queue operation.
Inputs must have equal dimensions, both dimensions must be at least two, and neither dimension may exceed the maximum passed to NewCorrelator. Processing uses a centered square crop based on the smaller dimension and pads it to the next power of two. Source images are not mutated.
Angle is counterclockwise in displayed image coordinates. Scale and rotation are applied around the image center before translation; positive Tx moves right and positive Ty moves down. Confidence values are normalized correlation peaks. A peak at or below 0.03 returns a nil Result and an error wrapping ErrLowConfidence.
type Option ¶
type Option func(*correlatorConfig) error
Option configures NewCorrelator. Options are applied before any CPU or Vulkan resources are allocated.
func WithBackend ¶
WithBackend selects automatic fallback, direct Vulkan, or CPU execution. It may be supplied at most once.
func WithDevice ¶
WithDevice uses an existing Vulkan device without taking ownership. It cannot be combined with WithBackend and may be supplied at most once.
type Result ¶
type Result struct {
// Angle is counterclockwise rotation in degrees, normalized to [-180, 180).
Angle float64
// Scale is the image-size multiplier and is greater than zero.
Scale float64
// Tx is horizontal translation in pixels; positive values move right.
Tx float64
// Ty is vertical translation in pixels; positive values move down.
Ty float64
// RotationConfidence is the normalized log-polar correlation peak.
RotationConfidence float64
// TranslationConfidence is the normalized translation correlation peak.
TranslationConfidence float64
}
Result describes the transform that maps image A to image B. Apply Scale and the counterclockwise Angle around the image center, then apply Tx and Ty.