JeVois  1.22
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Loading...
Searching...
No Matches
Tips for running custom neural networks

Tips for JeVois YAML zoo files

  • keys supported in the YAML files: each one is documented in the classes that use them, in the JEVOIS_DECLARE_PARAMETER(...) directives at the beginning of each header file:
  • Or you can also run one of the built-in networks and inspect the available parameters in the GUI, under the Parameters** tab.
  • If you create a custom python pre-processor, network, or post-processor and define JeVois parameters in there, you can set those parameters in your YAML file too.
  • Order matters: when a component is instantiated (e.g., preproc: Blob will instantiate a jevois::dnn::PreProcessorBlob), its parameters are brought into existence, but they do not exist before. So, for example, since rgb is a pre-processor parameter, it should be specified in the YAML file after preproc has been set.
    This is especially true for Python pre/net/post:
    • first select that you will use Python, e.g., preproc: Python
    • this only exposes a new parameter pypre to select which python file to load
    • when you then set, e.g., pypre: "pydnn/pre/PyPreBlob.py" the selected python code is loaded and initialized
    • during initialization, the python code may create new JeVois parameters; here, scale and mean
    • thus, only now you can set scale: 0.0078125 or similar.
  • Parameters have default values specified in their definition (in jevois::dnn::PreProcessor, etc). You can remove lines in your YAML file that would set parameters to those default values (e.g., rgb: true could be removed because the default for rgb is true). This will make your YAML file more concise.

Tips for pre-processing

  • mean and stdev values should be in the same order as your model's input images (RGB or BGR, as specified by the rgb parameter).

Tips for post-processing

  • If your network produces outputs that are close to what the post-processor wants, but not quite, you can try to apply transforms to the outputs. Supported transforms are:

    • re-order tensors
    • transpose along any axis
    • change shape without changing data (e.g., from 1x1x10x20 to 1x200)
    • split one tensor into several
    • concatenate several tensors into one.

    Output transformes are specified in the YAML zoo file using outransforms: and a sequence of transforms; for example:

    outtransform: "split(*,1,80,64); order(1,0,3,2,5,4)"

    See Network.H and Network.C for the exact syntax.

  • classes is optional. If you just want to check how fast a model will run on your JeVois camera but don't have the class list handy, just remove the classes parameter from your YAML. JeVois will just display class numbers instead of class names.
  • for classoffset: likely you have a computer keyboard around, and those tend to be easily recognized by models trained on ImageNet. So just point your camera to the keyboard and play with classoffset in the JeVois GUI until you get "computer keyboard" as output.
  • Classification is the easiest case. Detection usually requires more work, as a suitable post-processor is needed to decode the network outputs into boxes than can be drawn on screen. JeVois provides standard post-processors for the YOLO series, SSD, FasterRCNN, etc and you can also write your own in Python.
  • YOLOv2 anchors may need to be multiplied by 8 to work with the JeVois PostProcessor. You can do this in a terminal as follows (here, just cutting and pasting the anchors from yolov2-voc.cfg):
    for x in 1.3221, 1.73145, 3.19275, 4.00944, 5.05587, 8.09892, 9.47112, 4.84053, 11.2364, 10.0071; do echo "scale=4; ${x/,/} * 8" | bc; echo ','; done | xargs
    Remove the last comma and place some semicolons to separate the YOLO scales if needed, and you are good to go. See https://medium.com/nerd-for-tech/yolo-v2-configuration-file-explained-879e2219191 for some details.

Tips for model conversion

  • When converting a model, we may have some questions: Is our model using NCHW or NHWC? What are the names of the inputs and output layers? We can answer those using Lutz Roeder's great Netron online model inspection tool:
    • Point your browser to https://netron.app/
    • click "Open Model..."
    • upload your model
    • click on the boxes for the input and output layers to see some info about them
  • With quantized models, we prefer to use split outputs as they will give better quantized accuracy, with one output tensor for each type and scale (stride) of outputs. Use Netron to find their names. For example, for YOLOv8 / YOLOv9 / YOLOv10 / YOLO11:

    • for detection: 3 pairs (for 3 strides) of 2 outputs (raw boxes before DFL, class scores)
    • for instance segmentation: 3 pairs of 3 outputs (raw boxes, class scores, mask coefficients), plus 1 mask prototype
    • for pose detection: 3 pairs of 3 outputs (raw boxes, class scores, skeleton keypoints)
    • for oriented bounding boxes: 3 pairs (for 3 strides) of 3 outputs (raw boxes, class scores, box angles)

    Check out the many models that ship with JeVois-Pro, and also our script jevoispro-npu-convert.sh

  • YOLOv8 post-processors have two versions: normal and transposed. This is so that we do not waste time at runtime trying to figure out which one to use. Usually, networks converted for NPU will use the normal version (YOLOv8, for detection, pose, OBB, etc), and networks converted for Hailo-8 will use the transposed version (VOLOv8t). If one does not work for your model, try the other. Also see the following files for exactly what tensor shapes a given postprocessor expects:

    Have a look at the models in JeVois-Pro Deep Neural Network Benchmarks for many examples of the kinds of outputs we extract from various models to work with our C++ or Python post-processors.

  • If you are having problems with unsupported operations, you can use ONNX to truncate your model. For example, in a python interpreter:
    import onnx
    ins=['images']
    outs=['/model.23/cv2.0/cv2.0.2/Conv_output_0', '/model.23/cv3.0/cv3.0.2/Conv_output_0', '/model.23/cv2.1/cv2.1.2/Conv_output_0', '/model.23/cv3.1/cv3.1.2/Conv_output_0', '/model.23/cv2.2/cv2.2.2/Conv_output_0', '/model.23/cv3.2/cv3.2.2/Conv_output_0']
    onnx.utils.extract_model('yolo11m.onnx', 'yolo11m-truncated.onnx', ins, outs)
  • ONNX can also presumably convert ir_version, but we have had no success in running this to try to convert from ir_version 9 to 8:

    import onnx
    from onnx import version_converter, helper
    model = onnx.load('yolo11m-truncated.onnx')
    converted = version_converter.convert_version(model, 8)

    We always get an error.