estimate op• Data kinds: image2d × image2d → flow2d
• Call: import fullseye as fs; fs.ledger.piv_cross_correlate(a, b, window=32, overlap=0.5, peak='gauss3', window_func='hann', subtract_mean=True, shift=None, normalize='overlap', search_limit=0.25) (to call the implementation directly, import pivops; pivops.piv_cross_correlate(a, b, window=32, overlap=0.5, peak='gauss3', window_func='hann', subtract_mean=True, shift=None, normalize='overlap', search_limit=0.25); from the registry, opspiv.get("piv_cross_correlate"))
• Return value through the ledger: fullseye.ledger.piv_cross_correlate(...) returns only the declared out type flow2d (the underlying function also returns auxiliary values). When you need what was dropped, use fullseye.ledger.piv_cross_correlate.raw(...) or call pivops.piv_cross_correlate directly.
• Underlying return: (flow, info) -> flow2d
Computes the displacement field by per-window cross-correlation. Returns (flow, info).
For each window FFT is taken 2 times and the inverse transform of the conjugate product is taken (circular correlation); the position of the maximum gives the integer displacement, and the 3 points around it give the subpixel displacement.
Bias towards zero and its correction (measured): plain cross-correlation pulls the displacement towards zero. Shifting the window reduces the overlapping region, so the correlation value itself drops with the displacement; in measurement too the bias was proportional to the displacement (win=32, Hann, dx varied from 0.5 to 6 px, bias / (d/N) = 1.30, 1.29, 1.28, 1.28, 1.28 —— constant slope).
normalize="overlap" corrects this by dividing by the autocorrelation of the window function (the same as normalising by the overlap area). At the edges, however, the divisor approaches 0, so it is always paired with search_limit narrowing the search range to 1/4 of the window. Measured:
=============== ========== ========== ==========
dx [px] no corr. corr.+1/4 corr. only
=============== ========== ========== ==========
bias at 1.0 -0.0402 -0.0020 -0.2659
bias at 5.0 -0.2001 -0.0128 -0.9210
RMS at 5.0 0.2081 0.0301 4.8881
=============== ========== ========== ==========
The rightmost column is "normalisation only, without narrowing the search": the correction makes the error 23 times worse. The measured result that one must not be enabled without the other is used directly as the default.
Args:
a, b: image pair (H, W).
window: side of the window [px]. Even, 8 or more.
overlap: window overlap ratio [0, 1). 0.5 is customary.
peak: PEAK_MODES.
window_func: WINDOW_FUNCS.
subtract_mean: subtract the mean per window (prevents the DC component of the background from creating a huge
peak at the centre). Turning it off sticks to zero displacement.
shift: predicted displacement (2, h, w) (for multi-pass). The 2nd image's window is cut out shifted by this
integer amount, and the residual is measured.
normalize: "overlap" (default) or "none".
search_limit: upper limit of the searched displacement as a fraction of the window (default 0.25 = PIV's
"1/4 rule"). None means unlimited —— combined with normalize="overlap"
it gets worse, as in the table above.
Returns:
(flow (2, h, w), info). info is a dict with rows / cols (image coordinates of the
window centres), peak_ratio (1st peak / 2nd peak; the closer to 1, the less
trustworthy), window / overlap / peak.
• piv_displacement family guide
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• The canonical algorithm (author, year) and its uses are named in the family usage guide above.
• piv_field_analysis_tour — py -3.11 examples/piv_field_analysis_tour.py
• piv_flow_from_particles — py -3.11 examples/piv_flow_from_particles.py
• poc_beam_modal_video — py -3.11 examples/poc_beam_modal_video.py
• poc_change_detection_misreg — py -3.11 examples/poc_change_detection_misreg.py
• poc_dic_strain — py -3.11 examples/poc_dic_strain.py
• poc_print_registration — py -3.11 examples/poc_print_registration.py
• poc_river_surface_velocity — py -3.11 examples/poc_river_surface_velocity.py
• poc_strain_history — py -3.11 examples/poc_strain_history.py
• poc_superresolution_limits — py -3.11 examples/poc_superresolution_limits.py
• poc_tacsim_marker_shear — py -3.11 examples/poc_tacsim_marker_shear.py
flow2d as input)piv_deform_pass · piv_outlier_mask · piv_replace_outliers · piv_vorticity · piv_divergence · piv_flow_magnitude · piv_to_velocity · piv_velocity_gradient
estimate)piv_multipass · piv_deform_pass · piv_ensemble_correlate
*Provenance: pivops.py — PIV operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.