Nodes/PortraitUtils/Process Scanned Photo
ComfyUI Node

Process Scanned Photo

Straighten and crop your grandparents' scans without leaving ComfyUI

By heyburns·Created 11 months ago·Updated 4 months ago· 1
Process Scanned Photo
  • image
  • IMAGE
straightentrue
crop_modeInner Photo Frame
padding0
threshold0.80

The whole reason people get into ComfyUI photo restoration is the family-scan pile: crooked, bordered, dusty JPEGs of actual photographs. Feed those straight into an inpainting or upscaling graph and you're paying VRAM and prompt tokens on dead space and 2-degree rotation. ProcessScannedPhoto is the pack's answer - one node that finds the photo inside the scan, rotates it level, and crops off the scanner bed in a single pass. It's the node that makes the rest of PortraitUtils feel worth installing.

It's pure OpenCV, no model. Feed it an IMAGE, and if straighten is on (it is by default) it runs the scan through Canny edge detection, dilates the edges, merges them with a threshold mask, and picks the longest strong edge in the largest contour to estimate the rotation angle. Then it rotates the whole image level. After that, crop_mode decides what you keep:

  • Inner Photo Frame - finds the photo's inner edge and crops to it. This is the one you want for bordered prints.
  • Scanner Bed Only - crops to the visible bed but keeps whatever's inside, so it's gentler if the photo has a white border you want to keep.
  • None - just straighten, don't crop.

threshold (default 0.8, 0–1) controls how strict contour detection is - lower it if the scan is noisy or low-contrast and edges keep getting missed; raise it if it's chopping into the photo. padding lets you add or remove pixels around the detected frame, which is handy because the auto-detected edge is usually a hair too tight. A small negative value trims scanner dust, a small positive value stops the crop from biting into the photo.

Output is a single IMAGE, so it drops straight into your upscale/inpaint chain. Because it's OpenCV running on the CPU tensor, it's fast and costs zero VRAM - throw a whole folder through it before anything model-based touches a pixel.

Install

Same as every node in this pack: ComfyUI Manager → search "PortraitUtils" → install, or:

cd ComfyUI/custom_nodes
git clone https://github.com/heyburns/PortraitUtils

Then restart ComfyUI. The pack's requirements.txt pulls in opencv-python-headless>=4.5 - this is the node that actually needs it, so if you only use the math-only nodes you could in principle skip it, but the pack installs it for everyone anyway. No model files to download, no API keys, nothing hidden.

Common issues

  • It crops into the photo. The auto frame is computed on the merged edge mask and can read a busy background as photo content. Crank threshold up and give padding a small positive bump before you blame it.
  • Straightening looks fine but the crop is wrong - that's usually crop_mode doing more than you asked. If the photo has a genuine white border you want to preserve, switch to Scanner Bed Only or None and crop manually.
  • Nothing happens / image unchanged - check that straighten didn't get left on with crop_mode: None and a scan that's already level; you're getting an identity pass, which is correct but looks like a no-op.

The pack ships a docs/ProcessScannedPhoto.md guide and a debug string on most siblings if you want to see what it thinks it found. If you're digitizing a pile of old prints before restoration, run every scan through this first - it's the cheapest quality win in the whole suite.

CategoryPortraitUtils/Transform

Inputs (5)

NameTypeDefaultDescription
imageIMAGE
straightenBOOLEANtrue
crop_modeCOMBOInner Photo Frame3 options: Inner Photo Frame, Scanner Bed Only, None
paddingINT0-500–500
thresholdFLOAT0.800–1

Outputs (1)

NameTypeDescription
IMAGEIMAGE