Nodes/ComfyUI CV/CV Draw Epipolar Lines
ComfyUI Node

CV Draw Epipolar Lines

Seeing whether your fundamental matrix is actually right

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
CV Draw Epipolar Lines
  • source
  • lines
  • points
  • inlier_mask
  • image
◄max_draw40►
◄thickness1►

Why you'd reach for this

Two views of the same scene, and a point in one of them. Epipolar geometry says that point's match must lie on a specific line in the other view - a line you can compute from the fundamental matrix, without knowing the match. That line is the single most informative sanity check in two-view geometry, because if the computed line doesn't pass through the actual correspondence, something upstream is wrong: the matches, the matrix, or the calibration.

You can't check that with numbers. You check it by drawing the lines over the second image and looking at whether they converge on the right spot - a correct fundamental matrix gives you a family of lines meeting near a common epipole.

How it works

Input is Nx1x3 line coefficients from cv2.computeCorrespondEpilines, in ax + by + c = 0 form. For each line the node intersects it with the frame - clipped at left/right when the line is mostly horizontal, top/bottom when mostly vertical, whichever edge pair is numerically safer - and draws that segment anti-aliased. Degenerate all-zero lines, which is what a not-found fundamental matrix produces, are skipped rather than dividing by zero.

max_draw defaults to 40, not 0, and that's a sensible default: with a few hundred matches an unfiltered epiline render is a grey smear. Then inlier_mask (the Nx1 uint8 from CV Find Fundamental Matrix or a homography) slices both the lines and the optional points by the same mask, so what you see is the RANSAC-consistent subset. The tooltip's suggestion is worth stealing: set it to 0 (all) exactly once so you know what the clutter looks like, then leave it filtered.

The colouring is the clever part. Each line is coloured by its index through the pack's colour-vision-deficiency-safe categorical palette, and if you wire this image's matched points into points they're marked with a dot in the same colour, radius scaled by thickness. Run two of these nodes - one per view - with the same inlier mask, and a point in the left image shares its colour with its epipolar line in the right one. That's the correspondence made visible as a colour match, not a coordinate table.

Inputs and outputs that matter

  • lines - from CV Compute Correspond Epilines-style call, i.e. the Nx1x3 output. Feed it the other view's points, as the maths requires.
  • max_draw - default 40. Your main clutter control.
  • inlier_mask (optional) - must match the line count exactly, or the node raises with both numbers.
  • points (optional) - this image's matched points, dotted in their line's colour.
  • image - the only output, same format as the input (IMAGE or MASK). No count output on this one; if you need "how many inliers", that's what the mask arithmetic upstream gives you.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"

Python ≥ 3.12, ComfyUI on the V3 node API, or install the pack as ComfyUI CV from ComfyUI Manager.

Common issues

  • Lines everywhere and none near the points. Ambiguous matches. Everything is geometrically consistent with some wrong matrix when you feed it outliers - filter with a ratio test and re-fit before blaming this node.
  • Zero lines drawn. The fundamental matrix wasn't found. The pack's CV Find Fundamental Matrix reports a found flag for this; degenerate all-zero rows are skipped here by design, so a total absence of lines is the message.
  • Length mismatch error. inlier_mask or points has a different row count than lines. They all have to come from the same matched point set, in the same order.
  • Points and lines in different colours. You ran two nodes with different masks, or wired the wrong view's points in. Use one mask for both nodes.
  • Contrib trap. Needs the contrib OpenCV wheel; installing plain opencv-python over it silently empties the contrib submodules. tools/repair_opencv_contrib.py --check.
Categoryimage/CV/features

Inputs (6)

NameTypeDefaultDescription
sourceCOMFY_MATCHTYPE_V3Image or mask to draw the epilines on (a copy is made). 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.
linesNPARRAYNx1x3 line coefficients from cv2.computeCorrespondEpilines.
max_drawINT400–10000Draw at most this many lines (after inlier filtering). 0 = all - usually too cluttered.
thicknessINT11–16Line width in pixels (point dots scale with it).
pointsoptNPARRAYThis image's matched points (Nx1x2): each is marked with a dot in its line color.
inlier_maskoptNPARRAYNx1 uint8 mask from the fundamental-matrix node: only entries flagged 1 are drawn.

Outputs (1)

NameTypeDescription
imageCOMFY_MATCHTYPE_V3Same format as the image input.