From 9e726851d2fd907219f913d1844d41145a3eccb5 Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 09:18:35 +0800 Subject: [PATCH 01/10] Fix an error when exporting onnx The batch size of images is 32, while the batch size of orig_target_sizes is 1, violating the constraint and throwing a 'Ne(s31, 1) is inconsistent' error. --- tools/deployment/export_onnx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/deployment/export_onnx.py b/tools/deployment/export_onnx.py index 091865b..988d450 100644 --- a/tools/deployment/export_onnx.py +++ b/tools/deployment/export_onnx.py @@ -62,7 +62,7 @@ def forward(self, images, orig_target_sizes): model = Model() - data = torch.rand(32, 3, 640, 640) + data = torch.rand(1, 3, 640, 640) size = torch.tensor([[640, 640]]) _ = model(data, size) From 2ca6770672131b8991200aa7499144cb4e5be70c Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:33:23 +0800 Subject: [PATCH 02/10] Add eval_spatial_size parameter to configuration --- configs/linea/linea_hgnetv2_l.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/linea/linea_hgnetv2_l.py b/configs/linea/linea_hgnetv2_l.py index 15f968d..49a61ac 100644 --- a/configs/linea/linea_hgnetv2_l.py +++ b/configs/linea/linea_hgnetv2_l.py @@ -6,6 +6,8 @@ output_dir = 'output/linea_hgnetv2_l' +eval_spatial_size = (640, 640) + # backbone backbone = 'HGNetv2_B4' param_dict_type = backbone.lower() From 2dc9a1b5fa65251a31298877bc5e1607c1c7e4d2 Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:45:31 +0800 Subject: [PATCH 03/10] Remove eval_spatial_size from linea_hgnetv2_l.py Remove eval_spatial_size variable from configuration. --- configs/linea/linea_hgnetv2_l.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/configs/linea/linea_hgnetv2_l.py b/configs/linea/linea_hgnetv2_l.py index 49a61ac..15f968d 100644 --- a/configs/linea/linea_hgnetv2_l.py +++ b/configs/linea/linea_hgnetv2_l.py @@ -6,8 +6,6 @@ output_dir = 'output/linea_hgnetv2_l' -eval_spatial_size = (640, 640) - # backbone backbone = 'HGNetv2_B4' param_dict_type = backbone.lower() From aac58f891ca929888a4cc576d02b48772b11969a Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:56:21 +0800 Subject: [PATCH 04/10] Set evaluation spatial size to (640, 640) Added evaluation spatial size for model configuration. --- configs/linea/linea_hgnetv2_l.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/linea/linea_hgnetv2_l.py b/configs/linea/linea_hgnetv2_l.py index 15f968d..49a61ac 100644 --- a/configs/linea/linea_hgnetv2_l.py +++ b/configs/linea/linea_hgnetv2_l.py @@ -6,6 +6,8 @@ output_dir = 'output/linea_hgnetv2_l' +eval_spatial_size = (640, 640) + # backbone backbone = 'HGNetv2_B4' param_dict_type = backbone.lower() From 904382538fa44b5580a52678bc90fec2cbc7a2dc Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:59:10 +0800 Subject: [PATCH 05/10] Set evaluation spatial size to (640, 640) Added evaluation spatial size for model configuration. --- configs/linea/linea_hgnetv2_m.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/linea/linea_hgnetv2_m.py b/configs/linea/linea_hgnetv2_m.py index aa01bb3..67e4620 100644 --- a/configs/linea/linea_hgnetv2_m.py +++ b/configs/linea/linea_hgnetv2_m.py @@ -6,6 +6,8 @@ output_dir = 'output/linea_hgnetv2_m' +eval_spatial_size = (640, 640) + # backbone backbone = 'HGNetv2_B2' use_lab = True From 0e13a670d6d0c251e8569bb258f9c2bd94e214b9 Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:59:34 +0800 Subject: [PATCH 06/10] Add eval_spatial_size configuration --- configs/linea/linea_hgnetv2_n.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/linea/linea_hgnetv2_n.py b/configs/linea/linea_hgnetv2_n.py index 3e61fa8..d9b4e1c 100644 --- a/configs/linea/linea_hgnetv2_n.py +++ b/configs/linea/linea_hgnetv2_n.py @@ -6,6 +6,8 @@ output_dir = 'output/linea_hgnetv2_n' +eval_spatial_size = (640, 640) + # backbone backbone = 'HGNetv2_B0' use_lab = True From 1a5ca3921357e67f39136ea1e0ff35aec7416333 Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 14:00:07 +0800 Subject: [PATCH 07/10] Add eval_spatial_size configuration --- configs/linea/linea_hgnetv2_s.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/linea/linea_hgnetv2_s.py b/configs/linea/linea_hgnetv2_s.py index c52d7e2..4ae83d5 100644 --- a/configs/linea/linea_hgnetv2_s.py +++ b/configs/linea/linea_hgnetv2_s.py @@ -6,6 +6,8 @@ output_dir = 'output/linea_hgnetv2_s' +eval_spatial_size = (640, 640) + # backbone backbone = 'HGNetv2_B1' use_lab = True From d104c752330453624e14fafed42fa3e802dbeb00 Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 14:05:16 +0800 Subject: [PATCH 08/10] Refactor decoder.py for consistency and clarity --- models/linea/decoder.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/models/linea/decoder.py b/models/linea/decoder.py index baf9af5..79ff9bc 100644 --- a/models/linea/decoder.py +++ b/models/linea/decoder.py @@ -297,18 +297,18 @@ def forward(self, inter_ref_bbox = distance2bbox(ref_points_initial, self.integral(pred_corners, project), self.reg_scale) if self.training or layer_id == self.eval_idx: - scores = self.class_embed[layer_id](output) - scores = self.lqe_layers[layer_id](scores, pred_corners) - dec_out_logits.append(scores) - dec_out_bboxes.append(inter_ref_bbox) + scores = self.class_embed[layer_id](output) + scores = self.lqe_layers[layer_id](scores, pred_corners) + dec_out_logits.append(scores) + dec_out_bboxes.append(inter_ref_bbox) pred_corners_undetach = pred_corners if self.training: - ref_points_detach = inter_ref_bbox.detach() - output_detach = output.detach() + ref_points_detach = inter_ref_bbox.detach() + output_detach = output.detach() else: - ref_points_detach = inter_ref_bbox - output_detach = output + ref_points_detach = inter_ref_bbox + output_detach = output return torch.stack(dec_out_bboxes).permute(0, 2, 1, 3), torch.stack(dec_out_logits).permute(0, 2, 1, 3), @@ -428,6 +428,20 @@ def generate_anchors(self, spatial_shapes): return output_proposals, output_proposals_valid + def _load_from_state_dict(self, state_dict, prefix, local_metadata, strict, + missing_keys, unexpected_keys, error_msgs): + for key in ['output_proposals', 'output_proposals_mask']: + full_key = prefix + key + if full_key in state_dict: + tensor = state_dict[full_key] + buf = getattr(self, key, None) + if buf is None: + self.register_buffer(key, torch.empty_like(tensor)) + elif buf.shape != tensor.shape: + self._buffers[key] = torch.empty_like(tensor) + super()._load_from_state_dict(state_dict, prefix, local_metadata, strict, + missing_keys, unexpected_keys, error_msgs) + def forward(self, feats, targets): # flatten feature maps @@ -445,13 +459,9 @@ def forward(self, feats, targets): memory = torch.cat(memory, 1) # bs, \sum{hxw}, c # two-stage - if self.training: - output_proposals, output_proposals_valid = self.generate_anchors(spatial_shapes) - output_proposals = output_proposals.to(memory.device).repeat(bs, 1, 1) - output_memory = memory.masked_fill(~output_proposals_valid.to(memory.device), float(0)) - else: - output_proposals = self.output_proposals.repeat(bs, 1, 1) - output_memory = memory.masked_fill(self.output_proposals_mask, float(0)) + output_proposals, output_proposals_valid = self.generate_anchors(spatial_shapes) + output_proposals = output_proposals.to(memory.device).repeat(bs, 1, 1) + output_memory = memory.masked_fill(~output_proposals_valid.to(memory.device), float(0)) output_memory = self.enc_output_norm(self.enc_output(output_memory)) From c7b3c52ae21cf9532ebae2230e20727a4f4b1760 Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 14:07:06 +0800 Subject: [PATCH 09/10] Update input size handling and ONNX opset version --- tools/deployment/export_onnx.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/deployment/export_onnx.py b/tools/deployment/export_onnx.py index 988d450..5e0372e 100644 --- a/tools/deployment/export_onnx.py +++ b/tools/deployment/export_onnx.py @@ -62,8 +62,12 @@ def forward(self, images, orig_target_sizes): model = Model() - data = torch.rand(1, 3, 640, 640) - size = torch.tensor([[640, 640]]) + eval_spatial_size = getattr(cfg, 'eval_spatial_size', (640, 640)) + if eval_spatial_size is None: + eval_spatial_size = (640, 640) + input_h, input_w = eval_spatial_size + data = torch.rand(1, 3, input_h, input_w) + size = torch.tensor([[input_h, input_w]]) _ = model(data, size) dynamic_axes = { @@ -84,7 +88,7 @@ def forward(self, images, orig_target_sizes): input_names=['images', 'orig_target_sizes'], output_names=['lines', 'scores'], dynamic_axes=dynamic_axes, - opset_version=16, + opset_version=18, verbose=False, do_constant_folding=True, ) From 1ef0db061f557b50f16ec4a797cd8f7abb403639 Mon Sep 17 00:00:00 2001 From: Melt <60842553+NeKoooo233@users.noreply.github.com> Date: Mon, 26 Jan 2026 14:11:25 +0800 Subject: [PATCH 10/10] Add input size parameter to image and video processing --- tools/inference/onnx_inf.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tools/inference/onnx_inf.py b/tools/inference/onnx_inf.py index 5c8feef..792097e 100644 --- a/tools/inference/onnx_inf.py +++ b/tools/inference/onnx_inf.py @@ -2,6 +2,7 @@ Copyright (c) 2024 The D-FINE Authors. All Rights Reserved. """ import os +import sys import cv2 import glob import numpy as np @@ -10,6 +11,9 @@ import torchvision.transforms as T from PIL import Image, ImageDraw +sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '../..')) +from util.slconfig import SLConfig + def resize_with_aspect_ratio(image, size, interpolation=Image.BILINEAR): """Resizes an image while maintaining aspect ratio and pads it.""" @@ -44,13 +48,13 @@ def draw(images, lines, scores): return result_images -def process_image(sess, im_pil): +def process_image(sess, im_pil, input_size): w, h = im_pil.size orig_size = torch.tensor([w, h])[None] transforms = T.Compose( [ - T.Resize((640, 640)), + T.Resize((input_size[0], input_size[1])), T.ToTensor(), T.Normalize(mean=[0.538, 0.494, 0.453], std=[0.257, 0.263, 0.273]), ] @@ -69,7 +73,7 @@ def process_image(sess, im_pil): print(f"Image processing complete. Result saved as '{OUTPUT_NAME}.jpg'.") -def process_video(sess, video_path): +def process_video(sess, video_path, input_size): cap = cv2.VideoCapture(video_path) # Get video properties @@ -96,7 +100,7 @@ def process_video(sess, video_path): transforms = T.Compose( [ - T.Resize((640, 640)), + T.Resize((input_size[0], input_size[1])), T.ToTensor(), T.Normalize(mean=[0.538, 0.494, 0.453], std=[0.257, 0.263, 0.273]), ] @@ -128,15 +132,15 @@ def process_video(sess, video_path): out.release() print(f"Video processing complete. Result saved as '{OUTPUT_NAME}.mp4'.") -def process_file(sess, file_path): +def process_file(sess, file_path, input_size): # Check if the input file is an image or a video try: # Try to open the input as an image im_pil = Image.open(file_path).convert("RGB") - process_image(sess, im_pil) + process_image(sess, im_pil, input_size) except IOError: # Not an image, process as video - process_video(sess, file_path) + process_video(sess, file_path, input_size) def main(args): # Global variable @@ -147,6 +151,11 @@ def main(args): sess = ort.InferenceSession(args.onnx) print(f"Using device: {ort.get_device()}") + cfg = SLConfig.fromfile(args.config) + input_size = getattr(cfg, 'eval_spatial_size', (640, 640)) + if input_size is None: + input_size = (640, 640) + input_path = args.input thrh = 0.4 if args.thrh is None else args.thrh @@ -160,11 +169,11 @@ def main(args): paths = list(glob.iglob(f"{folder_dir}/*.*")) for file_path in paths: OUTPUT_NAME = file_path.replace(f'{folder_dir}/', f'{output_dir}/').split('.')[0] - process_file(sess, file_path) + process_file(sess, file_path, input_size) else: # Process a file OUTPUT_NAME = 'onxx_results' - process_file(sess, file_path) + process_file(sess, file_path, input_size) if __name__ == "__main__": import argparse