Lens Distortion Corrector
Fix the barrel distortion before you even think about face detection
- image
- image_rectified
Wide-angle portraits have a quiet problem: barrel distortion. A 24mm lens pulls the corners inward and the edges outward, so faces near the frame edge come out subtly wrong - and here's the part that bites ComfyUI users specifically: distortion throws off landmark detection. The pack's own docs say to drop this node in before face-detect or alignment, and that's the smartest framing for it. Fix the geometry first, and every downstream face tool gets cleaner input.
JHPixelProLensDistortion applies Brown-Conrady distortion correction (radial k1/k2/k3 plus tangential p1/p2) with two directions:
inverse(default): rectify a distorted source - the retouch use case.forward: simulate distortion on a clean image - the creative effect, i.e. fake fisheye.
The thing that makes it usable without a calibration rig is the preset dropdown. Pick canon_24mm_wide, sony_85mm_tele, or gopro_fisheye and it auto-fills the five coefficients with mid-range approximations; no_op_identity is the safe pass-through default. Choose custom and the k/p widgets take over verbatim.
The trade-off you should know about
The presets are approximations, not lens-specific calibration. They're tested on a 35mm-equivalent crop and they'll get you 80% of the way there - plenty for stabilizing a face pipeline or a stylized effect. But the README is upfront: for pro retouch, calibrate your actual lens with OpenCV's calibrateCamera (checkerboard) and paste the resulting (k1..p2) tuple into custom. That's the difference between "good enough to not break detection" and "actually correct."
There's also a GPU/CPU split worth knowing: the inverse path uses Kornia's undistort_image on GPU and falls back to cv2.remap on CPU; the forward path always uses Kornia. In practice this means results stay consistent across devices - you don't get a different correction depending on what you're running on.
Output is a single image_rectified, same shape as the input.
Install
ComfyUI Manager → search ComfyUI-JH-PixelPro, or:
cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt
Restart ComfyUI; it's under ComfyUI-JH-PixelPro/geometry. The pack needs ComfyUI ≥ 0.43.x, Python ≥ 3.10, plus kornia, mediapipe, opencv-python-headless, scipy.
My take: for most people this node earns its keep in the one-two punch with the face pipeline - rectify a wide shot, then run JHPixelProFaceDetect → JHPixelProFacialAligner, and the landmark quality on edge-of-frame faces improves dramatically. The fake-fisheye direction is a fun toy, but the real value is subtraction, not addition: taking distortion out so everything downstream sees a geometrically honest image. If you only ever shoot 50mm+ and never touch action cam footage, you may not need it - but it's the kind of node that saves you a whole workflow's worth of debugging when you do.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| preset | COMBO | no_op_identity | Lens preset — auto-fills k1..p2 with calibrated approximations. canon_24mm_wide: barrel correction for wide portrait lenses. sony_85mm_tele: mild pincushion correction for short-tele. gopro_fisheye: aggressive barrel removal for action cams. no_op_identity: pass-through (default, safe). Choose 'custom' to use the 5 widget values below verbatim. |
| direction | COMBO | inverse | inverse = rectify a distorted source (default; the retouch use case). forward = simulate distortion on a clean source (creative effect). |
| k1 | FLOAT | 0.000-1–1 | Radial coefficient k1 (Brown-Conrady). Used only when preset = custom. |
| k2 | FLOAT | 0.000-1–1 | Radial coefficient k2. Used only when preset = custom. |
| k3 | FLOAT | 0.000-1–1 | Radial coefficient k3. Used only when preset = custom. |
| p1 | FLOAT | 0.0000-0.1–0.1 | Tangential coefficient p1. Used only when preset = custom. |
| p2 | FLOAT | 0.0000-0.1–0.1 | Tangential coefficient p2. Used only when preset = custom. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image_rectified | IMAGE | — |