cv2.ximgproc.RadonTransform
Find how far a scan is tilting, without guessing angles
- src
- nparray
You know the problem: a photo of a document, a page of text, a scanned form, a wall of tiles - and it's rotated by "some amount". Hough will find lines but makes you pick peaks and pair them up. The Radon transform answers the cruder version of the question directly: at which angle does the image project into the sharpest lines? Each output column is the sum of the whole image along one projection direction, so a page full of horizontal text lines turns into a single bright band at exactly the right angle. Read the peak's column, and you have the skew in degrees.
The author's own tooltip calls it "a robust way to measure global skew", which is exactly right - this is the primitive for deskewing pipelines.
How it works and what to set
- src - the image to project. Any image works, but a projection sums every pixel, so a bright background owns the result. If you're looking for structure, threshold or edge-detect first and project the sparse version; your peaks will be far cleaner.
- theta (1.0) - the angular step in degrees. This is your speed/resolution trade: 1° over the full range gives 180 columns, 0.1° gives 1800 and costs ten times as much. Start at 1, zoom in when you know roughly where the peak is.
- start_angle (0) / end_angle (180) - the projection range. For skew measurement you rarely need more than a ±10° window around zero, and narrowing it is the biggest single speed-up available here.
- crop (false) - crop the source to its inscribed circle first, so every angle integrates the same amount of image and the peaks are comparable. Turn it on when you intend to compare peak heights across the range; leave it off when you only care about one direction.
- norm (false) - normalise the output to 8-bit for display instead of leaving raw sums. With a long document page the raw sums run into the millions, which is fine as data and useless as a preview.
Output is a single NPARRAY - the sinogram. With norm on you can push it straight to CV Array → Image; with norm off, CV Array → Image will min-max normalise it for you (which is fine for looking, wrong for measuring). For measuring, get the array's shape and peak location with Inspect CV Data first.
Downstream, the angle you read out feeds a rotation: the generated cv2.warpAffine wrapper or the curated CV Transform (Rotate/Scale/Shift) node, which wants a rotation in degrees anyway.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
Restart ComfyUI, or install ComfyUI CV through ComfyUI Manager. Requires Python ≥3.12, a recent ComfyUI built on the V3 node API, and opencv-contrib-python-headless~=5.0.0.93 - the pinned version. Nothing to download. Contrib-only function: if a non-contrib opencv-python wheel is sitting on top of the contrib one in site-packages/cv2, all ximgproc nodes including this one disappear from the menu. tools/repair_opencv_contrib.py --check tells you; --apply fixes it.
Common issues
One giant bright band, no structure. You projected a photo. Peak structure comes from repeated lines and edges, so binarise or Canny first.
Peaks in the wrong place / all the same height. crop off means wide angles integrate more pixels than narrow ones - the shape of the sinogram is partly an artefact of geometry. Turn crop on before comparing.
It's slow. Cost scales with the number of angles times the pixel count. theta = 0.1 on a 4K frame is a long wait; narrow start_angle/end_angle first.
No peak finder included. This is a raw wrapper: you get the sinogram, not the answer. Squeeze the column axis and take the argmax with the pack's array maths nodes, or read it off visually with a heatmap after norm.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| src | NPARRAY,IMAGE,MASK | - - - 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. | |
| thetaopt | FLOAT | 1.0000-1e+38–1e+38 | - - - Preset to the OpenCV default (1.0). |
| start_angleopt | FLOAT | 0.0000-1e+38–1e+38 | - - - Preset to the OpenCV default (0.0). |
| end_angleopt | FLOAT | 180.0000-1e+38–1e+38 | - - - Preset to the OpenCV default (180.0). |
| cropopt | BOOLEAN | false | - - - Preset to the OpenCV default (False). |
| normopt | BOOLEAN | false | - - - Preset to the OpenCV default (False). |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |