ControlNet Pre (+Model/ControlNet): MLSD
MLSD — straight-line detection for architecture and interiors
- image
- model
- clip
- vae
- control_net
- control_image
- model
- clip
- vae
- control_net
MLSD (Mobile Line Segment Detection) does one thing Canny doesn't: it only picks up straight lines, and ignores curves and texture entirely. That narrower focus is exactly why it's useful - for architecture, interior layouts, product boxes, anything dominated by hard geometric edges, MLSD gives you a cleaner, less cluttered conditioning map than a general edge detector would. It's not a niche or dying condition either - it's in the standard preprocessor list on every major union ControlNet, from SDXL's xinsir union through the current Z-Image and Flux 2 unions, so a checkpoint that actually understands MLSD maps is easy to find on whichever base you're running.
Two completely different backends, one node
The single most important thing about this node is the backend choice, because it changes everything about what you need installed. opencv_lsd runs OpenCV's built-in Line Segment Detector - a classical computer-vision algorithm, no external model file, no download, works the moment the pack is installed. onnx_mlsd runs the actual neural MLSD model, which is generally sharper and more consistent on cluttered scenes, but depends on a separate .onnx weight file the pack does not ship and does not document where to get. auto most likely tries the neural model first and falls back to OpenCV if the weight file isn't found, though that fallback behavior isn't documented anywhere and is worth verifying by just watching what happens on your machine rather than assuming.
That undocumented weight file is the practical landmine here: weights_dir defaults to weights/mlsd and onnx_model defaults to mlsd_large_512_fp32.onnx, but the README gives zero pointer to a download link, and there's no bundled copy. If you don't want to go hunting for that specific ONNX file, set backend to opencv_lsd and skip the whole problem - for most straight-line ControlNet work the classical LSD algorithm is genuinely good enough, and it's the path of least resistance for a first-time user.
The rest of the knobs
line_thickness and render_style (white_on_black/black_on_white/grayscale) control the rendered output - match the polarity to what your ControlNet checkpoint expects. detect_resolution sets the working resolution the detector runs at, independent of your final image size - the standard pattern across ControlNet preprocessors generally. min_line_length and merge_distance filter and consolidate short or nearby segments so you don't end up with a hundred tiny fragmented lines. mlsd_score_threshold and mlsd_dist_threshold are onnx_mlsd-specific tuning knobs for the neural model's confidence and distance filtering - they won't do anything meaningful if you're running the OpenCV backend instead.
Inputs and outputs
Required: image, backend, line_thickness, render_style, detect_resolution, min_line_length, merge_distance, mlsd_score_threshold, mlsd_dist_threshold, weights_dir, onnx_model. Like the rest of the pack's Loaders nodes, optional model/clip/vae/control_net inputs pass straight through to matching outputs if you want to route your model bundle through this node - otherwise ignore them. The output that matters is control_image (IMAGE), which feeds your ControlNet Apply node.
Installing it
Search ComfyUI-CN-Pre in ComfyUI Manager, or cd ComfyUI/custom_nodes && git clone https://github.com/OKIE5/ComfyUI-CN-Pre and restart. Straight talk on the docs situation: this pack's README is a single mismatched stub line, there's no community discussion of it anywhere, and the model-weight gap described above is a real, unaddressed hole in the pack's documentation rather than something you're missing.
Where people get burned
The failure mode to expect: setting backend to onnx_mlsd without having the weight file in place. Depending on how the node handles a missing file, that's either a clear load error in the console log or a silent fallback you won't notice unless you compare output against the OpenCV path. Either way, if MLSD isn't producing anything, check backend first - it's the single variable that determines whether this node needs an external file at all.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| backend | COMBO | 3 options: auto, onnx_mlsd, opencv_lsd | |
| line_thickness | INT | 11–9 | — |
| render_style | COMBO | 3 options: white_on_black, black_on_white, grayscale | |
| detect_resolution | INT | 768256–2048 | — |
| min_line_length | FLOAT | 10.000–1000 | — |
| merge_distance | FLOAT | 0.000–50 | — |
| mlsd_score_threshold | FLOAT | 0.100.01–1 | — |
| mlsd_dist_threshold | FLOAT | 0.100.01–1 | — |
| weights_dir | STRING | weights/mlsd | — |
| onnx_model | STRING | mlsd_large_512_fp32.onnx | — |
| modelopt | MODEL | — | |
| clipopt | CLIP | — | |
| vaeopt | VAE | — | |
| control_netopt | CONTROL_NET | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| control_image | IMAGE | — |
| model | MODEL | — |
| clip | CLIP | — |
| vae | VAE | — |
| control_net | CONTROL_NET | — |