cv2.xphoto.oilPainting (2/2)
The same brush, one fewer knob — here's when to pick it
- src
- result
If you've found this node by name you've probably already seen cv2.xphoto.oilPainting (1/2) and wondered which of the two you actually clicked. Short answer: this is the three-argument overload, oilPainting(src, size, dynRatio) - no colour-space combo. The two exist because OpenCV ships the function twice in C++ and the pack's ~470 wrappers are generated one-per-overload from the type stubs. Functionally, (2/2) is (1/2) with the colour space fixed.
Why you'd reach for it
Same use as its twin: quantise each neighbourhood to its most common colour and you get flat, painterly regions with wobbly edges, deterministically and on the CPU. Stylise a photo, flatten an image before contour or segment work, or build a repeatable "painted" pass you can apply identically to a whole batch. There is no generative step here at all - which is the appeal if you're in the part of a pipeline where a re-generation is unacceptable.
How it works
For every pixel, take the (2*size+1)² neighbourhood, divide intensities by dynRatio to bin them coarsely, count the bins, and write back the most common one. Bigger size means broader strokes and a much slower run; bigger dynRatio means fewer bins and flatter, poster-like output.
The one difference from (1/2) is which numbers "a colour" is measured in. (1/2) lets you pick - Lab by default, HSV, GRAY, YCrCb, HLS, LUV, XYZ, YUV - and bins the histogram on the first plane. This overload doesn't expose the choice at all, so the colour space is whatever the underlying C++ default resolves to. Which, in practice, means: if you're happy with the default look, use this node and skip a widget; the moment you want to argue about colour space, use (1/2). Everything else - the same neighbourhood, the same binning, the same speed - is identical.
The inputs that matter
src- three-channel or single-channel image (CV_8UC3/CV_8UC1),NPARRAY,IMAGEorMASK.size- neighbourhood half-size. Default 0, which is a 1×1 window and therefore no change to your image. Set 2–7. This is the reported "broken node" almost every time.dynRatio- the quantisation divisor. It divides intensity, so the shipped 0 isn't a usable value; keep it at 1 or above. 1 = subtle, 2–4 = coarse and poster-ish.
Output: result, the same format as src came in as. As with every low-level wrapper in this pack, an IMAGE input returns an NPARRAY, so you'll want CV Array → Image before it rejoins the normal graph.
Install
ComfyUI Manager → ComfyUI CV, or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
Restart afterwards. opencv-contrib-python-headless~=5.0.0.93 is the dependency that matters - xphoto lives in the contrib wheel only, and the pack's behaviour is curated against that pinned version. Python 3.12+ and a V3-API ComfyUI are both required; older builds can't import the pack at all.
Traps
- You will not get identical numbers to (1/2) at a non-default
code- obviously - but do check both on the same crop once. If the default space suits your image, going with the simpler node makes the graph easier to read later. size = 0no-ops,dynRatio = 0is a bad divisor. Both are stub defaults, both bite.- Batch behaviour is per image. Feed it a batch and frames are processed one at a time;
sizeat 6+ over fifty frames is a long lunch. - Don't chain it with its twin. Two passes of the same quantisation is strictly worse than one pass at a slightly larger
size- you just compound the flattening and the Lab round-trip error.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| src | COMFY_MATCHTYPE_V3 | Input three-channel or one channel image (either CV_8UC3 or CV_8UC1) The image output(s) echo this input's format. 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. | |
| size | INT | 0-2147483648–2147483647 | neighbouring size is 2-size+1 |
| dynRatio | INT | 0-2147483648–2147483647 | image is divided by dynRatio before histogram processing |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| result | COMFY_MATCHTYPE_V3 | Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY. |