comfyui-dsocr-bbox
A small ComfyUI custom node that draws bounding boxes from DeepSeek OCR output, crops each bbox region, and can paste processed crops back to the original coordinates.
ComfyUI DeepSeek OCR BBox
A small ComfyUI custom node that draws bounding boxes from DeepSeek OCR output, crops each bbox region, and can paste processed crops back to the original coordinates.
DeepSeek OCR coordinates are usually normalized to 0-1000; keep coord_base=1000.
Set coord_base=0 only when your OCR coordinates are already pixel coordinates.
GLM Vision BBox nodes
Both new nodes are grouped under the ComfyUI category dsocr_bbox/GLM Vision BBox.
They use only Python's standard HTTP library, so this API integration adds no package dependency.
GLM Vision BBox Extractor
Sends exactly one ComfyUI IMAGE and an editable multiline prompt to a configurable
OpenAI-compatible vision chat-completions API. Defaults:
endpoint:https://open.bigmodel.cn/api/paas/v4/chat/completionsmodel:glm-4.6v-flashapi_key: entered on the node; no key is stored in this repository
The prompt can be entered directly on the node and controls the bbox coordinate base
and order. The extractor strips Markdown fences or surrounding prose, keeps only
desc, class, and bbox, and preserves the model's first four numeric bbox values in
their original sequence. It does not scale, swap, sort, clamp, or round coordinates, so
downstream nodes must be configured to match the prompt's coordinate rules:
[
{
"desc": "official flagship store",
"class": "store",
"bbox": [900, 800.25, 100, -3]
}
]
Malformed items are omitted, but zero-area, reversed, negative, fractional, and out-of-image coordinates are retained for downstream interpretation. The node rejects image batches larger than one because its API contract is one image per call.
GLM Vision BBox Dual Extractor
Accepts two independent pairs, image_1 + prompt_1 and image_2 + prompt_2. The
first request uses endpoint_1 + api_key_1, the second uses endpoint_2 + api_key_2,
and both share model. Both GLM requests run concurrently, and the node returns
bbox_json_1 and bbox_json_2 in input-slot order even if the second request finishes
first. Each image input must contain exactly one image, and both inputs are validated
before either request starts. If either request fails, the node raises the error and
returns no partial output.
Both outputs use the same cleaned, pretty-printed, coordinate-preserving JSON format as the single-image extractor. The concurrent requests may consume each endpoint's API capacity at the same time, and each endpoint independently uses the existing retry behavior.
GLM BBox JSON Protected Expand
Takes bbox_json_a as protected regions and bbox_json_b as regions to expand. Unlike
the older A-B OCR nodes, every A bbox is protected; the node does not subtract matching
B boxes from A. Each B bbox first expands left/right by horizontal_expand percent of
the image width and top/bottom by vertical_expand percent of the image height, clipped
to the image, then all A regions are removed from it. safety_margin additionally
protects that many pixels around every A bbox.
Existing B/A overlap is removed too. Consequently, one B record may split into several
rectangles, each inheriting the original B desc and class; a fully covered B record
disappears. Different B records are processed independently and do not block each other.
Bboxes are half-open: touching an A edge is allowed, but positive-area overlap is never
returned, including at diagonal corners.
Set the shared coord_base to the base used by both inputs: use 0 for pixels or a
positive normalization base such as 1000. coordinate_order_a and
coordinate_order_b independently select [x1,y1,x2,y2] or [y1,x1,y2,x2], so each
can match the prompt that produced its JSON, including two different Dual Extractor
prompts. The output is always canonical x-first pixel-coordinate JSON and can feed
GLM BBox JSON To Mask with that node's coord_base=0 and x-first order.
GLM BBox JSON To Mask
Consumes bbox_json plus the source image, and outputs a native ComfyUI MASK
(float32, [batch,height,width]). coordinate_order switches between the default
[x1,y1,x2,y2] format and [y1,x1,y2,x2]. coord_base controls the input coordinate
system: it defaults to 1000 for normalized coordinates; set it to 0 when the JSON
uses source-image pixels. When connecting an extractor directly, set coord_base and
coordinate_order to the coordinate rules requested by that extractor's prompt.
horizontal_expand and vertical_expand are image-size percentages independent of
coord_base. For example, horizontal_expand=10 expands the bbox by 10% of the image
width on both the left and right, while vertical_expand=5 expands it by 5% of the
image height on both the top and bottom. Decimal percentages are supported (the input
step is 0.1). All expanded boxes are clipped to the image boundary; set both values
to 0 for no expansion.
Typical workflow:
Load Image -> GLM Vision BBox Extractor -> GLM BBox JSON To Mask
| ^
+--------------------------------------+
Modular OCR business-mask pipeline
The business filtering and region expansion are split into independent nodes, so a text or multimodal LLM can be inserted without rerunning OCR:
IMAGE
-> RapidOCR Detect Text
-> OCR Business Rule Classifier
-> OCR Business LLM Review Prompt
-> your LLM node (optionally also give it IMAGE)
-> OCR Apply Business Decisions
-> OCR Business Regions To Mask
For deterministic rules only, skip the prompt/apply nodes and connect classified_json directly to OCR Business Regions To Mask.
The intermediate JSON uses stable detection IDs (b0_d0, b0_d1, ...). A decision has two independent dimensions:
action:remove,preserve,ignore, orreviewregion_policy:text,box,top_banner,bottom_banner,group_box,gift_object,explicit_box, ornone
This separation is intentional: deciding that text is promotional is a semantic decision, while deciding to reconstruct an entire banner or nearby gift object is a geometric decision.
RapidOCR Detect Text (PP-OCR)
Detection-only node. It outputs pixel-coordinate OCR JSON and does not make business or mask decisions. The default candidate confidence is 0.50, intentionally lower than the classifier threshold so a downstream rule/LLM stage can inspect faint text and watermarks. Every detection includes a stable ID, text, score, bbox, polygon, OCR scale, and preprocessing variant.
OCR Business Rule Classifier
Adds deterministic initial fields to every OCR detection:
actioncategoryreasonregion_policydecision_source=rules
Known brand/restricted/promotion terms are removed, product specifications and configured functional terms are preserved, and ambiguous content is marked review. It outputs both the complete classified_json and a smaller review_items_json.
OCR Business LLM Review Prompt
Builds a strict JSON-only prompt from classified detections and a configurable business goal. Connect its output to any LLM node. For better decisions about banners, logos, badges, or nearby gift objects, use a multimodal LLM and provide the original image to that LLM as well.
OCR Apply Business Decisions
llm_decisions is optional. With no LLM connected, the node passes the rule decisions through and still provides the separate remove/preserve JSON outputs; unresolved_action controls how review items fall back. When connected, it merges LLM JSON back by stable detection ID. The LLM may override actions and region policies, group multiple detections, or provide an exact pixel region:
{
"decisions": [
{
"id": "b0_d12",
"action": "remove",
"category": "gift",
"region_policy": "explicit_box",
"region": [557, 656, 707, 816],
"notes": "Remove the gift object next to the gift marker"
}
]
}
Markdown JSON fences and surrounding LLM prose are accepted. Items omitted by the LLM can retain their rule result or use a configurable fallback. A multimodal LLM may also return additional_regions for visible logos, badges, gifts, or banners that have no OCR anchor; these become synthetic removal decisions with explicit pixel boxes.
OCR Business Regions To Mask
Turns final decisions into four native ComfyUI masks:
mask: complete removal masklarge_block_mask: whole banners, grouped regions, gifts, and explicit regionsdetail_mask:mask - large_block_mask, suitable for a second local inpaint passpreserve_mask: approved OCR text regions, excluding anything covered by removal
It also outputs regions_json for auditing and an overlay preview. Region expansion is policy-based rather than hard-coded into semantic classification:
text: padded OCR polygon/rectanglebox: independently expanded bbox; optional LLMexpandcan be a number or{left,top,right,bottom}top_banner: union matching top items, expand, and snap to top/left edges when closebottom_banner: expand from the earliest matching item to the bottom across full widthgroup_box: union items sharinggroup, then expandgift_object: infer a nearby object region from a gift markerexplicit_box: use LLM-supplied pixelregionnone: do not draw a removal region
RapidOCR Text Mask (PP-OCR)
Runs local RapidOCR/PP-OCR directly on a ComfyUI IMAGE and outputs every detected text region as a native ComfyUI MASK (float32, shape [batch, height, width]). It also returns detections_json with recognized text, confidence, polygon, bbox, OCR variant, and active provider.
Inputs:
image: source IMAGE, including image batchesspeed_profile:fastruns original RGB once;balancedadds enhanced grayscale and optional 2x OCR;thoroughadditionally checks inverted grayscaleminimum_confidence: recognition confidence threshold, default0.72padding: outward mask padding in pixels, default8mask_shape:polygonpreserves rotated OCR boxes;rectangleuses enclosing boxesaccelerator:auto,cpu, orcuda;autochooses CUDA only when ONNX Runtime exposesCUDAExecutionProvidercpu_threads:0keeps ONNX Runtime defaults; a positive value sets CPU intra-op threadsinvert_mask: reverses selected and unselected areas
Outputs:
mask: native ComfyUI MASK; detected text is1(white/selected)detections_json: OCR metadata and the provider actually used
Install dependencies in ComfyUI's Python environment:
pip install -r custom_nodes/comfyui-dsocr-bbox/requirements.txt
For NVIDIA GPU inference, replace the CPU ONNX Runtime package with a CUDA-compatible onnxruntime-gpu build. Verify it before selecting cuda:
python -c "import onnxruntime as ort; print(ort.get_available_providers())"
The output must include CUDAExecutionProvider. GPU acceleration applies to the PP-OCR detection, classification, and recognition ONNX models; PIL preprocessing and mask rasterization remain on CPU. For small single images, transfer/session overhead can make CPU as fast as or faster than GPU.
DeepSeek OCR Draw BBox
Inputs:
image: source IMAGEocr_result: DeepSeek OCR text output, STRING socketcoord_base: coordinate base, default1000crop_expand: expand crop area outward by this many pixels on each side, default0(clipped to image bounds)
Outputs:
image: source image with bbox drawncrop_images: all bbox crops as an IMAGE batchcrop_info: JSON metadata containing crop pixel coordinates for every crop; whencrop_expand > 0,boxis the expanded crop area andoriginal_boxkeeps the unexpanded bbox
DeepSeek OCR Draw BBox (Paste Text)
Same as DeepSeek OCR Draw BBox, but ocr_result is a multiline textbox for manual paste/testing.
DeepSeek OCR Expand Subset BBox
Expand bboxes from OCR result B while treating boxes in OCR result A - B as protected regions. Expansion is side-wise: left/right/top/bottom all try to move outward up to max_expand, and only protected boxes on the corresponding side limit that side. Boxes inside B do not avoid each other. Image borders are allowed as final stopping edges: expanded boxes can touch the border but are clipped inside the image when image size is provided. The output keeps B's original OCR text/ref format and only replaces each <|det|>...</|det|> bbox with the expanded bbox.
Inputs:
ocr_result_a: full OCR result A, STRING socketocr_result_b: subset OCR result B, STRING socketimage_width,image_height: source image size; used to clip the expanded bbox to image bounds and forcoord_base=1000normalized-coordinate conversion. If both are0and optionalimageis connected, the node auto-reads the image size.coord_base: coordinate base, default1000; set to0when OCR coordinates are already pixelsmax_expand: maximum outward expansion in pixels, default100safety_margin: protected margin around boxes inA - B, default0ignore_empty_label: defaulttrue; removes unlabeled/empty OCR blocks from A before computing protected boxes, including blocks whose label text only contains whitespace/invisible Unicode characters, so blank image detections do not block expansionoutput_coord_base:-1keeps the same coordinate base as input;0forces pixel output; positive values output normalized coordinates with that base
Output:
ocr_result: B OCR result with expanded bbox coordinates
DeepSeek OCR BBox To Mask
Convert bbox information into a native ComfyUI MASK (float32, shape [batch, height, width]), compatible with the mask output of ComfyUI's built-in Load Image node and usable directly by inpainting workflows. The bbox interior is 1 (white / inpaint area), and all other pixels are 0 (black).
Inputs:
bbox_info: bbox/OCR information from a STRING socket. It accepts full DeepSeek OCR text,<|det|>blocks, plain lists such as[[x1, y1, x2, y2], ...], dictionaries such as{"bbox": [x1, y1, x2, y2]}, and polygonsimage_width,image_height: output mask dimensions. Leave both at0when optionalimageis connected to read its dimensions automaticallycoord_base: coordinate base, default1000; set to0for pixel coordinatesinvert_mask: defaultfalse; when enabled, reverses the mask so bbox regions are0(black) and regions outside all bboxes are1(white / inpaint area)- optional
image: supplies the mask dimensions and batch size; image content is not changed or returned
Output:
mask: standard ComfyUI MASK; white bbox regions are selected for inpainting
RapidOCR polygon JSON nodes
The polygon JSON workflow is separate from the DeepSeek OCR tag/bbox workflow. All nodes in this set use the RapidOCR name and the RapidOCR category. They accept a top-level detection list as well as nested RapidOCR output containing detections and batch metadata such as width and height.
Example input:
[
{"text": "智能四轮", "polygon": [[32.0, 82.0], [198.0, 82.0], [198.0, 123.0], [32.0, 123.0]]},
{"text": "2025新款", "polygon": [[24.0, 128.0], [216.0, 128.0], [216.0, 178.0], [24.0, 178.0]]}
]
RapidOCR JSON Polygon To Mask
Convert RapidOCR pixel-coordinate polygons into a native ComfyUI MASK.
Inputs:
json_data: strict JSON from a STRING socket; each detection needspolygon(compatiblepointsis also accepted)image_width,image_height: output dimensions; leave both at0when optionalimageis connected or the RapidOCR JSON containswidth/heightmetadatacoord_base: default0for RapidOCR pixel coordinatesinvert_mask: invert selected and unselected areas- optional
image: supplies dimensions and output batch size
Output:
mask: polygon interiors are1(white/selected), other pixels are0
RapidOCR JSON Polygon Extend
Expand every polygon independently by up to expand pixels on each side. The original polygon is mapped into its expanded enclosing rectangle, preserving rotated or skewed polygon geometry rather than replacing it with a rectangle. Existing box/bbox metadata is synchronized, while text, IDs, confidence scores, wrappers, and all other JSON fields are preserved.
Image bounds come from image_width/image_height, optional image, or RapidOCR wrapper width/height. Set clip_to_image=false to allow output coordinates outside the image. image_edge_margin (default 0) limits newly expanded polygon edges to remain this many pixels away from the image border. If an original polygon is already closer than the requested margin, it is not shrunk; that side simply remains unchanged. A positive margin requires known image dimensions.
RapidOCR JSON Polygon A-B Based Extend
Expand polygons in JSON B while treating polygons in A - B as protected obstacles. It follows the same independent, side-wise behavior as DeepSeek OCR Expand Subset BBox, but consumes and returns RapidOCR polygon JSON:
- B polygons do not block each other
- left/right/top/bottom expand independently up to
max_expand safety_margininflates protected A-B regionsimage_edge_marginkeeps newly expanded edges the requested pixel distance from image borders without shrinking an original polygon that is already closerignore_empty_text_in_aexcludes A detections with blanktextfrom obstacles- B's JSON structure and metadata are preserved
- image dimensions can be supplied manually, by optional
image, or bywidth/heightin the JSON wrapper
DeepSeek OCR Expand Subset BBox (Paste Text)
Same as DeepSeek OCR Expand Subset BBox, but both OCR inputs are multiline textboxes for manual paste/testing.
DeepSeek OCR Paste BBox Crops
Paste cropped/processed bbox images back onto the original image using crop_info.
Inputs:
original_image: original/source IMAGEcrop_images: crops IMAGE batch, usually fromcrop_imagesoutput of Draw BBox or processed by other nodescrop_info: JSON metadata from Draw BBoxcrop_infooutputstrip_padding: defaulttrue; removes padding added to make ComfyUI image batches same sizeresize_to_bbox: defaulttrue; resizes each crop to its original bbox size before pastingfeather_radius: default0; feather radius in pixels around the pasted crop edge,0disables featheringfeather_strength: default1.0; feather blend strength from0.0to1.0; higher values make the crop edge more transparent and softer
Output:
image: image after pasting crops to original bbox coordinates
Expected OCR format
<|ref|>已售6万+健腹轮<|/ref|><|det|>[[59, 72, 485, 124]]<|/det|>
<|ref|>更懂你的需求<|/ref|><|det|>[[59, 145, 415, 200]]<|/det|>
<|ref|>数据来源店铺健腹轮累计销量!<|/ref|><|det|>[[54, 217, 329, 240]]<|/det|>
The parser also remains compatible with the older layout where <|ref|> is a generic type such as text/title and the recognized text is placed on the following lines.
Supported detection shapes include rectangles like [[x1, y1, x2, y2]] and polygon points like
[[x1, y1], [x2, y2], [x3, y3], [x4, y4]].
For polygon detections, cropping uses the polygon's enclosing rectangle, while bbox drawing keeps the polygon outline.