[KongchangAI]
· 3 min read· 1,789 words

AI Line Art Binarization Thresholds: Field Notes from Passing Stock Image QC

AI Line Art Binarization Thresholds: Field Notes from Passing Stock Image QC

Binarize AI line art with normalize-then-threshold-128 to clear stock QC every time.

A batch of 60 AI line art assets got 11 Adobe Stock rejections, all for visible gray pixels along stroke edges. Testing fixed thresholds of 100, 160, and 128 all leaked; the fix was normalizing first to compress the gray band, then binarizing at 128. Combined with proper morphology order, PNG-only exports, and automated gray-band checks, edge-related rejections dropped to zero across the next 300 assets.

A batch of 60 AI line art assets went to Adobe Stock review and came back within an afternoon — 11 rejections, all with the exact same reason: visible gray pixels along the stroke edges. Same prompts, same exporter, same threshold settings that had worked for weeks. It wasn't until I zoomed a rejected file to 800% that I could see it: every line was wrapped in a near-black fuzzy halo, and that's exactly what reviewers flag as "not clean vector-ready assets."

AI line art binarization threshold debugging screenshot

The cost of that afternoon was a week of rework, and it taught me one thing: binarization isn't a detail — it's the decisive step that determines whether your whole batch clears review. Here's the full breakdown, with concrete data.

Why AI Line Art Is Born "Dirty"

Diffusion models don't output lines — they output probability fields that look like lines. Rendered into a PNG, that's a stroke where the core sits around RGB 20–40 and the edge decays through 80, 120, 160 all the way down to the background. At 100% zoom it reads as clean black and white, but when a stock reviewer inspects it at high magnification, it becomes a low-contrast soft edge — something multiple platforms classify as a quality defect.

Adobe Stock's illustration review checks technical cleanliness: artifacts, noise, and edges that look machine-degraded. Vecteezy and Dreamstime run the same checks in their own review pipelines. Gray halos are the most common artifact in AI line art, and also the easiest to remove once you pick the right threshold.

What a Diffusion Model's Probability Field Actually Means

To understand the gray-edge problem, you first need to understand what a diffusion model actually outputs. During denoising, a model like Stable Diffusion predicts, at each step, "the probability that this pixel belongs to some content," and the final decoder weights and averages those probabilities into pixel values. So a "black line" inside the model isn't a sharp-edged binary mask — it's a continuous field that decays from the line center (where ownership probability approaches 1 and pixels approach pure black) outward to the background (where probability approaches 0 and pixels approach pure white). More sampling steps and lower CFG produce softer edge transitions; even line art that looks "hard" shows a several-pixel-wide gray transition band when magnified. This is the root cause of why the mid-range values (roughly 80–200) on the grayscale histogram aren't zero, and why no fixed threshold can slice through cleanly in one pass: a threshold essentially "cuts" this continuous field, and where you cut determines whether the gray edge stays inside the line or gets cut outside it.

Thresholds That Actually Work

I tested three fixed thresholds across 200 assets and recorded the rejection rate for each:

  • Threshold 100 (0–255 range): lines came out too thin, faint details disappeared. About 14% of batches lost small features like whisker lines and interior detail lines.
  • Threshold 160: gray halos survived. My 11 rejections came from here — halo pixels landed in the 120–155 range, and a threshold of 160 simply couldn't cut them out.
  • Threshold 128: the intuitive midpoint, performed better, but under soft rendering halos still leaked through in roughly one out of every ten files.

What actually works isn't some magic number — it's a two-step process:

  1. First apply auto-contrast or normalization to the grayscale image, pushing the background toward pure 255 and the line core toward 0.
  2. Then binarize at 128. After normalization the halo pixels compress into an extremely narrow band, and 128 slices cleanly through the middle.

All 11 rejected files passed after reprocessing; across the next 300 assets, edge-related rejections were zero.

Why Normalization "Flattens" the Gray Edge

Auto-contrast or normalization (e.g., OpenCV's normalize, PIL's ImageOps.autocontrast) linearly stretches the image's actual grayscale range to 0–255. In the original image the line core might only reach RGB 30 and the background only RGB 230, with a whole gray band sitting at 80–200 in between; after stretching, the core is pushed to 0 and the background to 255, and a transition band that was 120 gray levels wide gets compressed to just a dozen or so levels, concentrated right at the light-dark boundary. This means the threshold no longer needs to be "carefully chosen" — whether you pick 128 or 130, the resulting line width differs by only a pixel or two, removing any dependence on a "magic number." One thing to note: normalization applies a single linear transform to the whole image, so it does little for uneven local lighting (such as scans or backgrounds with gradients). In those cases, do background subtraction first and normalize afterward, otherwise gray edges in the shadowed corners will still remain.

Morphological Processing: Thresholding Alone Isn't Enough

Even with a clean threshold, two problems still show up in review: isolated stray pixels in the background (dust left behind by diffusion noise), and pinholes inside thick lines. I process in the following order:

  • First apply a median filter or "remove small blobs" to eliminate isolated background pixels.
  • Then despeckle the inverted image to close pinholes inside the lines.

Order matters. If you despeckle before dust removal, dust specks get welded onto nearby lines and form small clumps — worse than either problem on its own.

One more habit: inspect at low resolution, not high. Rendering a 4000px preview to hunt for halos wastes memory and is less effective than a 600px thumbnail — the latter makes residual gray bands show up as visible murk. On my 1 vCPU, 2GB RAM machine, dropping the inspection render from 300 dpi to 60 dpi cut peak memory dramatically and completely eliminated swap thrashing. I confirmed the memory ceiling with resource.getrusage(RUSAGE_SELF).ru_maxrss rather than guessing, and ran each file in a separate subprocess so heavy renders returned memory to the OS between assets.

JPEG Is a Trap for Binary Images

Even with a perfect threshold, saving as JPEG at default quality reintroduces ringing artifacts around every line, because JPEG encodes edges with block transforms. What the reviewer sees when zoomed in is the very same fuzzy halo you just removed — added back in by the export step.

The fix is boring: save line art as PNG; if a platform forces JPEG, save at quality 95 or above, and verify by zooming in before uploading. I lost another small batch to this — the threshold was fine, the exporter ruined it.

Why JPEG Ringing Artifacts Happen

JPEG uses 8x8 discrete cosine transform (DCT) blocks for encoding. When pure black and pure white appear in the same block (exactly what binary line art looks like), the DCT needs a large number of high-frequency coefficients to approximate that near-step edge; the quantization step discards some high-frequency information, and the reconstructed waveform after decoding oscillates on both sides of the edge — showing up as an extra ring of alternating light-dark fine lines at the black-white boundary, known as "ringing" or "mosquito noise." The lower the quality parameter, the more high frequencies get discarded and the more visible the ringing. For grayscale line art, this ring of fine lines falls exactly in the "stroke edge" region reviewers care about, looking as if the gray halo you just binarized away has come back. PNG uses lossless compression and preserves exact pixel values, making it the only safe choice for line art; if a platform forces JPEG, setting quality above 95 only reduces ringing rather than eliminating it, and you should still zoom in for spot checks before upload.

Put Inspection Into the Pipeline Instead of Relying on Your Eyes

Manual zoom inspection doesn't scale. The alternative is mechanical, millisecond-per-file checking:

  • After binarization, count pixels in the gray band (roughly 60 to 200). Clean files are near zero; anything above a small threshold gets flagged as a binarization failure and sent to a retry queue for reprocessing with a different threshold.
  • Verify the histogram is genuinely bimodal: one near-black peak and one near-white peak, with almost nothing in between.

This automated check lets me run overnight batches on a small server with confidence. The pipeline processes one process at a time, calls gc.collect() after each asset, and routes any file failing the gray-band check to a retry queue instead of the upload directory. An upload ledger ensures no duplicate submissions — double-posting is the fastest way to get an account flagged.

That rejected batch taught one more lesson: keep the original outputs. Every failed file is a data point about which prompts and settings produce clean lines. I now keep research notes and scrape logs in a fixed folder structure and never delete original batches. The directory layout that survived is simple: raw assets, pending-submission output, finished packages, and research material, each kept separate.

Tooling and Packaging

All of the above is baked into the toolchain I use daily. The Pipeline Starter Kit includes four scripts for this pipeline: a metadata builder that writes Adobe 5-column, Vecteezy 4-column, and Dreamstime 15-column CSV headers (these platforms will reject you for getting the headers wrong); an upload tracker that prevents duplicate submissions; a Markdown-to-PDF converter; and a packager that generates product zips with a 1280x720 cover and 600x600 thumbnail. Two dependencies total, with the metadata and tracking tools using only the standard library, all verified on 1 vCPU, 2GB RAM, and no GPU — packaged 39 products and 856MB of output before release.

If you're building a batch pipeline for line art or any digital asset, this is the packaging layer I wish I'd had on day one.

One-line Summary

Passing AI line art review comes down to binarization: normalize to crush the gray edge, then threshold at 128, paired with morphology and automated gray-band checks.

Paragraph Summary

A batch of 60 AI line art assets got 11 rejections from Adobe Stock, all for the same reason: visible gray pixels along stroke edges. Diffusion models output probability fields, not lines, so edges naturally carry gray transitions that look "dirty" at high magnification. The author tested fixed thresholds of 100, 160, and 128 — all leaked. What worked was a two-step method: apply auto-contrast or normalization to push the background toward pure 255 and the line core toward 0, compressing the gray edge band, then binarize at 128. All rejected files passed, and across the next 300 assets edge-related rejections dropped to zero. The article also emphasizes morphological processing order (remove stray pixels first, then pinholes), avoiding JPEG for binary images (it reintroduces ringing artifacts), and replacing manual zoom inspection with gray-band pixel counts and bimodal histogram verification — enabling stable overnight batches on a low-spec 1 vCPU, 2GB RAM server.

#AI line art binarization#stock image QC#Adobe Stock rejection#threshold 128#gray halo artifact#morphological processing#JPEG ringing artifacts#batch image pipeline
Share:

Related articles