From 059631f718786f935d8f5312790dcae5acd08909 Mon Sep 17 00:00:00 2001 From: Shivaansh Gusain Date: Tue, 16 Dec 2025 20:10:26 +0530 Subject: [PATCH 1/5] Fix PaddleOCR 2.9+ compatibility and safe-guard box sorting --- util/utils.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/util/utils.py b/util/utils.py index eb7c8b25..a36e70fb 100644 --- a/util/utils.py +++ b/util/utils.py @@ -22,13 +22,7 @@ reader = easyocr.Reader(['en']) paddle_ocr = PaddleOCR( lang='en', # other lang also available - use_angle_cls=False, - use_gpu=False, # using cuda will conflict with pytorch in the same process - show_log=False, - max_batch_size=1024, - use_dilation=True, # improves accuracy - det_db_score_mode='slow', # improves accuracy - rec_batch_num=1024) +) import time import base64 @@ -41,7 +35,7 @@ from torchvision.transforms import ToPILImage import supervision as sv import torchvision.transforms as T -from util.box_annotator import BoxAnnotator +from .box_annotator import BoxAnnotator def get_caption_model_processor(model_name, model_name_or_path="Salesforce/blip2-opt-2.7b", device=None): @@ -430,13 +424,24 @@ def get_som_labeled_img(image_source: Union[str, Image.Image], model=None, BOX_T else: print('no ocr bbox!!!') ocr_bbox = None - + if ocr_bbox is None: ocr_bbox = [] + if ocr_text is None: ocr_text = [] ocr_bbox_elem = [{'type': 'text', 'bbox':box, 'interactivity':False, 'content':txt, 'source': 'box_ocr_content_ocr'} for box, txt in zip(ocr_bbox, ocr_text) if int_box_area(box, w, h) > 0] xyxy_elem = [{'type': 'icon', 'bbox':box, 'interactivity':True, 'content':None} for box in xyxy.tolist() if int_box_area(box, w, h) > 0] filtered_boxes = remove_overlap_new(boxes=xyxy_elem, iou_threshold=iou_threshold, ocr_bbox=ocr_bbox_elem) # sort the filtered_boxes so that the one with 'content': None is at the end, and get the index of the first 'content': None - filtered_boxes_elem = sorted(filtered_boxes, key=lambda x: x['content'] is None) + # filtered_boxes_elem = sorted(filtered_boxes, key=lambda x: x['content'] is None) + safe_boxes = [] + for item in filtered_boxes: + # If the item is just a list of coordinates (the bug), wrap it in a dict + if isinstance(item, (list, tuple)): + safe_boxes.append({'type': 'icon', 'bbox': item, 'content': None}) + else: + safe_boxes.append(item) + + # Now sort the safe list + filtered_boxes_elem = sorted(safe_boxes, key=lambda x: x.get('content') is None) # get the index of the first 'content': None starting_idx = next((i for i, box in enumerate(filtered_boxes_elem) if box['content'] is None), -1) filtered_boxes = torch.tensor([box['bbox'] for box in filtered_boxes_elem]) @@ -474,17 +479,13 @@ def get_som_labeled_img(image_source: Union[str, Image.Image], model=None, BOX_T annotated_frame, label_coordinates = annotate(image_source=image_source, boxes=filtered_boxes, logits=logits, phrases=phrases, **draw_bbox_config) else: annotated_frame, label_coordinates = annotate(image_source=image_source, boxes=filtered_boxes, logits=logits, phrases=phrases, text_scale=text_scale, text_padding=text_padding) - + pil_img = Image.fromarray(annotated_frame) - buffered = io.BytesIO() - pil_img.save(buffered, format="PNG") - encoded_image = base64.b64encode(buffered.getvalue()).decode('ascii') if output_coord_in_ratio: label_coordinates = {k: [v[0]/w, v[1]/h, v[2]/w, v[3]/h] for k, v in label_coordinates.items()} assert w == annotated_frame.shape[1] and h == annotated_frame.shape[0] - - return encoded_image, label_coordinates, filtered_boxes_elem - + + return pil_img, label_coordinates, filtered_boxes_elem def get_xywh(input): x, y, w, h = input[0][0], input[0][1], input[2][0] - input[0][0], input[2][1] - input[0][1] From 13b776fa7ade8e651836f082bdd4bd610f82d71e Mon Sep 17 00:00:00 2001 From: Shivaansh Gusain <76487827+ShivaanshGusain@users.noreply.github.com> Date: Fri, 16 Jan 2026 14:33:19 +0530 Subject: [PATCH 2/5] Fixed Florence2 2 Inference Crash --- requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 901a27fa..669955ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ easyocr torchvision supervision==0.18.0 openai==1.3.5 -transformers +transformers==4.40.0 ultralytics==8.3.70 azure-identity numpy==1.26.4 @@ -29,4 +29,5 @@ google-auth<3,>=2 screeninfo uiautomation dashscope -groq \ No newline at end of file + +groq From 51f58105c1913499d7af19e9834bd8974b7d3ae8 Mon Sep 17 00:00:00 2001 From: Shivaansh Gusain <76487827+ShivaanshGusain@users.noreply.github.com> Date: Fri, 16 Jan 2026 14:49:58 +0530 Subject: [PATCH 3/5] Fixed opencv-python conflicts. --- requirements.txt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 669955ab..f95e9f1c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,18 +3,32 @@ easyocr torchvision supervision==0.18.0 openai==1.3.5 + +# Fix for Florence2 Crash transformers==4.40.0 + ultralytics==8.3.70 azure-identity numpy==1.26.4 -opencv-python + +# If you need an interactive, desktop-level GUI features, use 'opencv-python' and comment out opencv-python-headless, both of them contain the same core file. + +# Includes GUI dependencies (like Qt) +#opencv-python + +# Removes the GUI dependencies. This is smaller and designed for server environments. opencv-python-headless + gradio dill accelerate timm einops==0.8.0 + +# To use the model on a GPU, change paddlepaddle to: paddlepaddle-gpu paddlepaddle +# paddleocr won't be able to find the GPU since paddlepaddle is a CPU-only library. + paddleocr ruff==0.6.7 pre-commit==3.8.0 @@ -31,3 +45,4 @@ uiautomation dashscope groq + From 217a105a8a0aaecf15151d59c08ee0e53b6e44cb Mon Sep 17 00:00:00 2001 From: Shivaansh Gusain <76487827+ShivaanshGusain@users.noreply.github.com> Date: Tue, 28 Jul 2026 21:38:22 +0530 Subject: [PATCH 4/5] Fix box dictionary normalization and starting_idx default Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- util/utils.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/util/utils.py b/util/utils.py index 931a2b2e..5589e935 100644 --- a/util/utils.py +++ b/util/utils.py @@ -446,14 +446,17 @@ def get_som_labeled_img(image_source: Union[str, Image.Image], model=None, BOX_T for item in filtered_boxes: # If the item is just a list of coordinates (the bug), wrap it in a dict if isinstance(item, (list, tuple)): - safe_boxes.append({'type': 'icon', 'bbox': item, 'content': None}) + safe_boxes.append({'type': 'icon', 'bbox': list(item), 'interactivity': True, 'content': None, 'source': 'box_yolo_content_yolo'}) else: + # Ensure required keys exist so downstream code can safely index + if isinstance(item, dict): + item.setdefault('content', None) safe_boxes.append(item) - + # Now sort the safe list filtered_boxes_elem = sorted(safe_boxes, key=lambda x: x.get('content') is None) # get the index of the first 'content': None - starting_idx = next((i for i, box in enumerate(filtered_boxes_elem) if box['content'] is None), -1) + starting_idx = next((i for i, box in enumerate(filtered_boxes_elem) if box.get('content') is None), len(filtered_boxes_elem)) filtered_boxes = torch.tensor([box['bbox'] for box in filtered_boxes_elem]) print('len(filtered_boxes):', len(filtered_boxes), starting_idx) From 01a3e99727b7d4ab12eed723a0a60f120077a4b9 Mon Sep 17 00:00:00 2001 From: Shivaansh Gusain <76487827+ShivaanshGusain@users.noreply.github.com> Date: Tue, 28 Jul 2026 21:49:36 +0530 Subject: [PATCH 5/5] [fix] Restore base64 string return type in get_som_labeled_img --- util/utils.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/util/utils.py b/util/utils.py index 5589e935..38f14ac0 100644 --- a/util/utils.py +++ b/util/utils.py @@ -494,12 +494,16 @@ def get_som_labeled_img(image_source: Union[str, Image.Image], model=None, BOX_T annotated_frame, label_coordinates = annotate(image_source=image_source, boxes=filtered_boxes, logits=logits, phrases=phrases, text_scale=text_scale, text_padding=text_padding) pil_img = Image.fromarray(annotated_frame) + + buffered = io.BytesIO() + pil_img.save(buffered, format="PNG") + encoded_image = base64.b64encode(buffered.getvalue()).decode('ascii') + if output_coord_in_ratio: label_coordinates = {k: [v[0]/w, v[1]/h, v[2]/w, v[3]/h] for k, v in label_coordinates.items()} assert w == annotated_frame.shape[1] and h == annotated_frame.shape[0] - return pil_img, label_coordinates, filtered_boxes_elem - + return encoded_image, label_coordinates, filtered_boxes_elem def get_xywh(input): x, y, w, h = input[0][0], input[0][1], input[2][0] - input[0][0], input[2][1] - input[0][1] x, y, w, h = int(x), int(y), int(w), int(h) @@ -551,4 +555,4 @@ def check_ocr_box(image_source: Union[str, Image.Image], display_img = True, out bb = [get_xywh(item) for item in coord] elif output_bb_format == 'xyxy': bb = [get_xyxy(item) for item in coord] - return (text, bb), goal_filtering \ No newline at end of file + return (text, bb), goal_filtering