microsoft / onnxruntime-extensions

onnxruntime-extensions: A specialized pre- and post- processing library for ONNX Runtime
MIT License
295 stars 80 forks source link

How to export preprocessing as its own model? #697

Closed darrenjkt closed 2 months ago

darrenjkt commented 2 months ago

Hi, I have the following preprocessing code that I would like to add to my model. However I would like to first run an image through it and inspect the final output

inputs = [create_named_value("input", onnx.TensorProto.UINT8, ["h", "w", 3])]
onnx_opset = 17
pipeline = PrePostProcessor(inputs, onnx_opset)
pipeline.add_pre_processing(
    [
        ChannelsLastToChannelsFirst(name="RGBImageCHW"),  # HWC to CHW
        Resize(1280, layout="CHW", name='resize', policy='not_smaller'),  # Uses BILINEAR currently 
        LetterBox(target_shape=(1280, 1280), fill_value=114, name='pad', layout='CHW'),
        ImageBytesToFloat(name='uint8_to_01'),  # Convert to float in range 0..1 by dividing uint8 values by 255
        Normalize([(123.675, 58.395), (116.28, 57.12), (103.53, 57.375)], name='normalize', layout="CHW"),  # (mean, stddev) for each channel 
        Unsqueeze([0], name='unsqueeze'),  # add batch, CHW --> 1CHW
    ]
)

How can I export this pipeline as an onnx model? Or just simply run a out = preproc(image) through this pipeline?

darrenjkt commented 2 months ago

Adding Debug() in between helped me to check the outputs.

pipeline.add_pre_processing(
    [
        Debug(),
        Resize((1280,1280), layout="HWC", name='resize', policy='not_larger'),  # Uses BILINEAR currently 
        Debug(),
        LetterBox(target_shape=(1280, 1280), fill_value=114, name='pad', layout='HWC'),
        Debug(),
        Normalize([(123.675, 58.395), (116.28, 57.12), (103.53, 57.375)], name='normalize', layout="HWC"),  # (mean, stddev) for each channel 
        Debug(),
        ChannelsLastToChannelsFirst(name="RGBImageCHW"),  # HWC to CHW
        Debug(),        
        Unsqueeze([0], name='unsqueeze'),  # add batch, CHW --> 1CHW
        Debug(),
    ]
)

I can then check the outputs with:

ort_inputs = {ort_session.get_inputs()[0].name: image}
out = ort_session.run(None, ort_inputs)
dets, labels, input_debug, resized_d, pad_d, norm_d, transposed_d, expand_d = out

where dets, labels are my original outputs.