CV Quasi-Dense Stereo
Stereo matching by SEED-AND-GROW (cv2.stereo.QuasiDenseStereo), the third answer next to 'Stereo Disparity (SGBM)' and '(BM)'. Those two search a disparity RANGE at every pixel independently; this one tracks a few hundred good-features-to-track seeds with Lucas-Kanade and then GROWS each match into its neighbourhood as long as the correlation and the local disparity gradient hold up. Consequences worth knowing: there is no num_disparities to get wrong (a seed can sit anywhere, so a wide baseline costs nothing), it answers only where the image has texture to propagate through - the output is quasi-dense, not dense - and it needs no rectification to run, though the disparity output only means anything on a RECTIFIED pair. The class is not reachable from the raw wrappers. Failure-tolerant: a pair with no trackable features (a blank frame) returns found=false and empty arrays instead of the OpenCV assertion the class raises.
- left
- right
- disparity
- valid
- displacement
- points_left
- points_right
- seeds_left
- seeds_right
- dense_count
- seed_count
- found
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| left | NPARRAY,IMAGE | Left frame (grayscaled internally). Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size. | |
| right | NPARRAY,IMAGE | Right frame; resized to left if the sizes differ - the class asserts on mismatched frames. Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size. | |
| max_seeds | INT | 50010–5000 | How many goodFeaturesToTrack seeds to start from (gftMaxNumFeatures). More seeds reach more regions - propagation cannot cross a texture-less gap, so an unseeded area stays empty however good the matching is. |
| seed_quality | FLOAT | 0.0100.0001–1 | Corner quality of a seed relative to the strongest corner (gftQualityThres). Lower accepts weaker corners, i.e. more seeds in flat regions. |
| seed_min_distance | INT | 101–200 | Minimum pixel distance between seeds (gftMinSeperationDist) - spreads them over the frame instead of clustering on one strong texture. |
| correlation_window | INT | 53–31 | Half-window of the correlation test used when growing a match (corrWinSizeX/Y). Larger is more reliable and blurs across depth discontinuities. |
| correlation_threshold | FLOAT | 0.500–1 | Minimum normalized correlation for a grown match to be kept. Raise it to trade coverage for correctness. |
| texture_threshold | FLOAT | 2000–10000 | Minimum local texture (sum of squared gradients) a pixel must have before propagation continues into it. This is what stops the growth from flooding a blank wall or the sky with an invented disparity. |
| disparity_gradient | INT | 10–10 | How much the disparity may change between neighbouring pixels. 1 keeps surfaces smooth; larger follows steep slopes and lets the growth leak across object edges. |
| neighborhood_sizeopt | INT | 53–21 | Size of the neighbourhood a confirmed match propagates into. |
| borderopt | INT | 150–100 | Image margin (borderX/borderY) excluded from matching, so a correlation window never runs off the frame. |
Outputs (10)
| Name | Type | Description |
|---|---|---|
| disparity | NPARRAY | HxW float32 SIGNED horizontal disparity in pixels (x_left - x_right), the same convention as 'Stereo Disparity (SGBM)' / '(BM)' - so it feeds 'CV Disparity Interpolate', cv2.reprojectImageTo3D and the WLS filter directly. Built from the match set, NOT from cv2's own getDisparity(), which returns the UNSIGNED euclidean displacement (see 'displacement'). 0 where unmatched - read 'valid', not zero. |
| valid | NPARRAY | uint8 0/255 mask of pixels that actually got a match (the quasi-dense support). |
| displacement | NPARRAY | HxW float32 of cv2's own getDisparity(): the EUCLIDEAN length of each match's displacement, sqrt(dx^2 + dy^2), unsigned and including vertical motion. On a rectified pair it is |disparity|; on an unrectified one the two differ by tens of pixels, which is why the disparity output above is not this. NaN (cv2's 'no match') is written as 0. |
| points_left | NPARRAY | Nx1x2 float32 left-image coordinates of every DENSE match - wire straight into 'Triangulate Points', 'Find Homography (RANSAC)' or 'Draw Points'. |
| points_right | NPARRAY | Nx1x2 float32 right-image coordinates, row-aligned with points_left. |
| seeds_left | NPARRAY | Nx1x2 float32 left-image coordinates of the SPARSE seed matches the propagation started from - a few hundred against the dense set's tens of thousands. |
| seeds_right | NPARRAY | Nx1x2 float32 right-image coordinates of the seeds. |
| dense_count | INT | Number of quasi-dense matches. |
| seed_count | INT | Number of seed matches. |
| found | BOOLEAN | False when the pair produced no dense match at all (blank or uncorrelated frames); the arrays are then empty and the disparity is all zero. |