HybridNets: End-to-End Perception Network

Overview

HybridNets: End2End Perception Network

logo
HybridNets Network Architecture.

Generic badge PyTorch - Version Python - Version

HybridNets: End-to-End Perception Network

by Dat Vu, Bao Ngo, Hung Phan 📧 FPT University

( 📧 ) corresponding author.

arXiv technical report (arXiv 2203.09035)

PWC PWC

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Training Tips
  5. Results
  6. License
  7. Acknowledgements
  8. Citation

About The Project

HybridNets is an end2end perception network for multi-tasks. Our work focused on traffic object detection, drivable area segmentation and lane detection. HybridNets can run real-time on embedded systems, and obtains SOTA Object Detection, Lane Detection on BDD100K Dataset. intro

Project Structure

HybridNets
│   backbone.py                   # Model configuration
│   hubconf.py                    # Pytorch Hub entrypoint
│   hybridnets_test.py            # Image inference
│   hybridnets_test_videos.py     # Video inference
│   train.py                      # Train script
│   val.py                        # Validate script
│
├───encoders                      # https://github.com/qubvel/segmentation_models.pytorch/tree/master/segmentation_models_pytorch/encoders
│       ...
│
├───hybridnets
│       autoanchor.py             # Generate new anchors by k-means
│       dataset.py                # BDD100K dataset
│       loss.py                   # Focal, tversky (dice)
│       model.py                  # Model blocks
│
├───projects
│       bdd100k.yml               # Project configuration
│
└───utils
    │   plot.py                   # Draw bounding box
    │   smp_metrics.py            # https://github.com/qubvel/segmentation_models.pytorch/blob/master/segmentation_models_pytorch/metrics/functional.py
    │   utils.py                  # Various helper functions (preprocess, postprocess, eval...)
    │
    └───sync_batchnorm            # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch/tree/master/sync_batchnorm 
            ...

Getting Started Open In Colab

Installation

The project was developed with Python>=3.7 and Pytorch>=1.10.

git clone https://github.com/datvuthanh/HybridNets
cd HybridNets
pip install -r requirements.txt

Demo

# Download end-to-end weights
mkdir weights
curl -L -o weights/hybridnets.pth https://github.com/datvuthanh/HybridNets/releases/download/v1.0/hybridnets.pth

# Image inference
python hybridnets_test.py -w weights/hybridnets.pth --source demo/image --output demo_result --imshow False --imwrite True

# Video inference
python hybridnets_test_videos.py -w weights/hybridnets.pth --source demo/video --output demo_result

# Result is saved in a new folder called demo_result

Usage

Data Preparation

Recommended dataset structure:

HybridNets
└───datasets
    ├───imgs
    │   ├───train
    │   └───val
    ├───det_annot
    │   ├───train
    │   └───val
    ├───da_seg_annot
    │   ├───train
    │   └───val
    └───ll_seg_annot
        ├───train
        └───val

Update your dataset paths in projects/your_project_name.yml.

For BDD100K: imgs, det_annot, da_seg_annot, ll_seg_annot

Training

1) Edit or create a new project configuration, using bdd100k.yml as a template

# mean and std of dataset in RGB order
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]

# bdd100k anchors
anchors_scales: '[2**0, 2**0.70, 2**1.32]'
anchors_ratios: '[(0.62, 1.58), (1.0, 1.0), (1.58, 0.62)]'

# BDD100K officially supports 10 classes
# obj_list: ['person', 'rider', 'car', 'truck', 'bus', 'train', 'motorcycle', 'bicycle', 'traffic light', 'traffic sign']
obj_list: ['car']
obj_combine: ['car', 'bus', 'truck', 'train']  # if single class, combine these classes into 1 single class in obj_list
                                               # leave as empty list ([]) to not combine classes

seg_list: ['road',
          'lane']

dataset:
  color_rgb: false
  dataroot: path/to/imgs
  labelroot: path/to/det_annot
  laneroot: path/to/ll_seg_annot
  maskroot: path/to/da_seg_annot
...

2) Train

python train.py -p bdd100k        # your_project_name
                -c 3              # coefficient of effnet backbone, result from paper is 3
                -n 4              # num_workers
                -b 8              # batch_size per gpu
                -w path/to/weight # use 'last' to resume training from previous session
                --freeze_det      # freeze detection head, others: --freeze_backbone, --freeze_seg
                --lr 1e-5         # learning rate
                --optim adamw     # adamw | sgd
                --num_epochs 200

Please check python train.py --help for every available arguments.

3) Evaluate

python val.py -p bdd100k -c 3 -w checkpoints/weight.pth

Training Tips

Anchors

If your dataset is intrinsically different from COCO or BDD100K, or the metrics of detection after training are not as high as expected, you could try enabling autoanchor in project.yml:

...
model:
  image_size:
  - 640
  - 384
need_autoanchor: true  # set to true to run autoanchor
pin_memory: false
...

This automatically finds the best combination of anchor scales and anchor ratios for your dataset. Then you can manually edit them project.yml and disable autoanchor.

If you're feeling lucky, maybe mess around with base_anchor_scale in backbone.py:

class HybridNetsBackbone(nn.Module):
  ...
  self.pyramid_levels = [5, 5, 5, 5, 5, 5, 5, 5, 6]
  self.anchor_scale = [1.25,1.25,1.25,1.25,1.25,1.25,1.25,1.25,1.25,]
  self.aspect_ratios = kwargs.get('ratios', [(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)])
  ...

and model.py:

class Anchors(nn.Module):
  ...
  for scale, ratio in itertools.product(self.scales, self.ratios):
    base_anchor_size = self.anchor_scale * stride * scale
    anchor_size_x_2 = base_anchor_size * ratio[0] / 2.0
    anchor_size_y_2 = base_anchor_size * ratio[1] / 2.0
  ...

to get a grasp on how anchor boxes work.

And because a picture is worth a thousand words, you can visualize your anchor boxes in Anchor Computation Tool.

Training stages

We experimented with training stages and found that this settings achieved the best results:

  1. --freeze_seg True ~ 100 epochs
  2. --freeze_backbone True --freeze_det True ~ 50 epochs
  3. Train end-to-end ~ 50 epochs

The reason being detection head is harder to converge early on, so we basically skipped segmentation head to focus on detection first.

Results

Traffic Object Detection

Result Visualization
Model Recall (%) [email protected] (%)
MultiNet 81.3 60.2
DLT-Net 89.4 68.4
Faster R-CNN 77.2 55.6
YOLOv5s 86.8 77.2
YOLOP 89.2 76.5
HybridNets 92.8 77.3

Drivable Area Segmentation

Result Visualization
Model Drivable mIoU (%)
MultiNet 71.6
DLT-Net 71.3
PSPNet 89.6
YOLOP 91.5
HybridNets 90.5

Lane Line Detection

Result Visualization
Model Accuracy (%) Lane Line IoU (%)
Enet 34.12 14.64
SCNN 35.79 15.84
Enet-SAD 36.56 16.02
YOLOP 70.5 26.2
HybridNets 85.4 31.6

License

Distributed under the MIT License. See LICENSE for more information.

Acknowledgements

Our work would not be complete without the wonderful work of the following authors:

Citation

If you find our paper and code useful for your research, please consider giving a star and citation 📝 :

@misc{vu2022hybridnets,
      title={HybridNets: End-to-End Perception Network}, 
      author={Dat Vu and Bao Ngo and Hung Phan},
      year={2022},
      eprint={2203.09035},
      archivePrefix={arXiv},
      primaryClass={cs.CV}
}
Comments
  • Lane color and Lane type Segmentation

    Lane color and Lane type Segmentation

    In the traffic light and traffic sign detection issue, you've mentioned that we just have to change the obj_list in project.yml by adding the classes needed. Does that apply to seg_list as well?

    If I want to detect lane color and lane type, can I change seg_list as follows

    seg_list: ['road', 'double white', 'double yellow', 'single white', 'single yellow', 'solid', 'dashed']

    Actually, I need classes like double solid yellow, double solid white, single solid yellow, single solid white, single dashed yellow, single dashed white, double dashed yellow, double dashed white, but BDD100K already has labeled double white, double yellow, single white, single yellow classes under Lane Categories and solid, dashed classes under Lane Styles

    Will the change in seg_list as shown above work, if not, how to do it

    opened by nannapaneni4 9
  • dataset link in colab doesnt work

    dataset link in colab doesnt work

    Hi,

    This link is required access permission. Could you help with it? https://drive.google.com/drive/folders/1iW9Darrars4xc9uHq2ZnRsWoJolCcyzg?usp=sharing

    opened by zehranrgi 4
  • Issue with FPS mistake in the article

    Issue with FPS mistake in the article

    Hello. First of all,thank you for this work.

    I noted you mistake the code about the inf_time and fps.

    So I think maybe you calculation the inference time incorrectly in the article , your article show that YOLOP have 52ms the infercence time per frame(batch size 1), which mean 20fps? (although 41 fps show in the YOLOP's article).

    And sadly in the hybridnets_test.py , i try calculate the HYBRIDNET's inference time but only get 0.06s(only model(x) ) ,which means 17-20fps. (Tesla v100 )but get 0.021s(only model(x) ) in YOLOP, which means 48 fps(Tesla v100 )

    Sadly , it may not faster than YOLOP and not reach the real-time.

    question 
    opened by hankplease 3
  • Did anyone successfully export onnx?

    Did anyone successfully export onnx?

    code as follows, but export nothing:

    weight_path = 'weights/hybridnets.pth'
    device = 'cuda' if torch.cuda.is_available() else 'cpu'
    params = Params(os.path.join(Path(__file__).resolve().parent, "projects/bdd100k.yml"))
    model = HybridNetsBackbone(num_classes=len(params.obj_list), compound_coef=3,
                               ratios=eval(params.anchors_ratios), scales=eval(params.anchors_scales),
                               seg_classes=len(params.seg_list), backbone_name=None)
    model.load_state_dict(torch.load(weight_path, map_location=device))
    model.eval()
    inputs = torch.randn(1, 3, 384, 640)
    print("begin to convert onnx")
    torch.onnx.export(model, inputs, 'HybridNetsBackbone.onnx',
                      verbose=False, opset_version=12, input_names=['images'])
    print("done")
    

    shell log:

    HybridNets/utils/utils.py:673: TracerWarning: torch.from_numpy results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.
      anchor_boxes = torch.from_numpy(anchor_boxes.astype(dtype)).to(image.device)
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    Warning: Constant folding - Only steps=1 can be constant folded for opset >= 10 onnx::Slice op. Constant folding not applied.
    
    ...
    ONNX export failed: Couldn't export Python operator SwishImplementation
    
    question 
    opened by aimuch 3
  • Evaluation results not accurate?

    Evaluation results not accurate?

    Hi, I've been trying to recreate your results from the Hybridnets paper. I've run the eval code on the 100k dataset but the results I'm getting are nowhere close to the actual results you presented in the paper. I'm sure I'm missing something here, could you please tell me what could possibly be going wrong here. I think the root locations that I'm giving are inaccurate.

    data root - raw images from the 100k dataset label root - I saved separate json file for each image from the "bdd100k_labels_images_val.json" that I downloaded from the bdd100k dataset. So in total I saved 10,000 separate json (one for each image) into another folder named "val". Road labels in Seg_list - I used the drivable masks Lane labels in Seg_list - I used the lane masks

    The output that I got after evaluation of 100 images: Screenshot from 2022-06-21 16-27-00

    The iou values are inconsistent with the ones mentioned in the paper, they are nowhere near them. I was also wondering why the precision is so low, is there a specific reason as to why there are so many false positives. I hope you can help me out, thanks.

    question 
    opened by luceeleven 3
  • Problem in Training stage

    Problem in Training stage

    Hello, I tried to follow your suggestion to train the model. So accordingly, at first I freeze the segmentation and trained for some epoch.

    python train.py -p bdd100k -c 3 -n 4 -b 8 --freeze_seg True --lr 1e-5 --optim adamw --num_epochs 75 --val_interval 1 --log_path D:\HybridNets\rgb-clean --saved_path D:\HybridNets\rgb-clean --save_interval 500 --verbose True --num_gpus 1 --plots True
    
    

    After that I am freezing the backbone and detection head.

    python train.py -p bdd100k -c 3 -n 4 -b 8 --freeze_backbone True --freeze_det True --lr 1e-5 --optim adamw --num_epochs 12 --val_interval 1 --log_path D:\HybridNets\rgb_clean --saved_path D:\HybridNets\rgb_clean --save_interval 500 --verbose True --num_gpus 1 --plots True -w D:\HybridNets\rgb-clean\bdd100k\hybridnets-d3_74_129225_best.pth
    

    But I am getting the error

    image

    Can you please suggest how to solve this issue?

    Thank you in advance

    question 
    opened by dreamer-1996 2
  • AssertionError BUG

    AssertionError BUG

    if i just want to seg one class,such as seg_list only have ’road‘. Then i run train.py , in loss.py line 538, in soft_tversky_score assert output.size() == target.size() AssertionError

    then i debug code,find output.size() = torch.Size([2, 1, 245760]) target.size() = torch.Size([2, 1, 491520])

    How to fix that???

    opened by harrylee999 2
  • IndexError: boolean index did not match indexed array along dimension 0

    IndexError: boolean index did not match indexed array along dimension 0

    Hello , when i put a image of size 1920*1080 for test,there is the following error. Can you please help me resolve this issue? Thank you! "IndexError: boolean index did not match indexed array along dimension 0; dimension is 1080 but corresponding boolean dimension is 720"

    opened by liuliaocheng 2
  • [Discussion] Gradient flow

    [Discussion] Gradient flow

    Back when we were toying with mosaic, we removed the segmentation head completely from the model and dataloader. Now that we try to add mosaic augmentation officially, we have to make a decision of not using it for segmentation training.

    hybridnets/dataset.py

    if self.use_mosaic:
        # honestly, mosaic is not for road and lane segmentation anyway
        # you cant expect road and lane to be split up in 4 separate corners in an image, do you?
        # only use mosaic with freeze_seg :)
        img, labels, seg_label, lane_label, (h0, w0), (h, w), path = self.load_mosaic(idx)
    

    Only images and object annotations are mosaic, while segmentation annotations are kept intact, which produces incorrect segmentation loss but that doesn't matter because we froze segmentation head anyway, thinking that requires_grad=False makes the segmentation head disappear from backprop graph. But that is wrong, the backbone is still affected by segmentation loss.

    Check this colab for interactive stuffs.

    So we've been planning to just straight ahead set the losses to 0 when you --freeze_head like this:

    cls_loss, reg_loss, seg_loss, regression, classification, anchors, segmentation = model(imgs, annot, seg_annot, obj_list=params.obj_list)
    cls_loss = cls_loss.mean() if not opt.freeze_det else 0
    reg_loss = reg_loss.mean() if not opt.freeze_det else 0
    seg_loss = seg_loss.mean() if not opt.freeze_seg else 0
    

    Is this approach too naive? Are there any recommendation regarding this matter? Or should we also mosaic the segmentation labels?

    help wanted question 
    opened by xoiga123 2
  • Could not use Pytorch quantization for model

    Could not use Pytorch quantization for model

    model_to_quantize = copy.deepcopy(model)

    qconfig_dict = {"": torch.quantization.get_default_qconfig('qnnpack')}

    model_to_quantize.eval()

    # prepare model_prepared = quantize_fx.prepare_fx(model_to_quantize, qconfig_dict)

    # calibrate (not shown) # quantize model_quantized = quantize_fx.convert_fx(model_prepared)

    When using Pytorch quantization example for your model, I get this following error:

    ~/Documents/DL_course_project/HybridNets/backbone.py in forward(self, inputs) 100 101 # p1, p2, p3, p4, p5 = self.backbone_net(inputs) 102 --> p2, p3, p4, p5 = self.encoder(inputs)[-4:] # self.backbone_net(inputs) 103 104 features = (p3, p4, p5) NameError: module is not installed as a submodule

    How can I avoid this error?

    help wanted 
    opened by tiendatAI 2
  • Drivable and Lane Type training

    Drivable and Lane Type training

    @datvuthanh thanks for sharing the code based i have following queries

    1. since bdd100k has different types of lanes eg double yellow, single white lane , dashed, can we use current source code to train for different lane types? is so what are the modifications need to be made int he code based
    2. Can we similar train the current source code with the driveable area and alternate drivable area labels ? if so what are the changes to be made

    Please share your thoughts Thanks in advance

    opened by abhigoku10 2
  • How to generate drivable area and lane masks?

    How to generate drivable area and lane masks?

    I know you shared a drive link for bdd100k drivable area and lane masks for the dataloader but I want to replicate it for understanding what to do for my custom dataset. I looked for bdd repo and there is "to_mask.py" which has some scripts to do it. It passes its own tests but I cannot get similar results as you shared. Can you please explain how to generate those masks? Thanks in advance.

    opened by eren-aydemir 0
  • Issue with FPS calculation code.

    Issue with FPS calculation code.

    Hello. First of all, great work.

    While running the hybridnets_test_videos.py I found some issues with the FPS calculation part. In the hybridnets_test_videos.py script, the FPS is calculated as: (t2-t1)/frame_count)

    But it seems that the above code will give the inference time per frame and not the FPS. Most probably it should be: 1/((t2-t1)/frame_count)) That is, we need to divide it by 1.

    Please let me know if any updates happen on this front.

    opened by sovit-123 1
  • The loss doesn't converge when training segmentation head only.

    The loss doesn't converge when training segmentation head only.

    I changed the backbone to Efficientnet-b0 and reduce the number of BiFPN layers from 6 to 1, in order to cut down the runtime of inference. After training 200 epochs with segmentation head frozen, I tried to train the model freezing backbone and detection head. But I found that the train loss of segmentation head dose not seem to converge. And the loss of valuation and mIOU are reducing at the same time, which doesn't make sense. Apart from that, I also found that when freezing segmentation head, the segmentation loss is not set to 0 in the code. which can affect the updating of weights in backbone, I suppose.

    bug help wanted 
    opened by bigsquirrel18 13
Releases(v1.0)
Owner
Thanh Dat Vu
Thanh Dat Vu
Photo2cartoon - 人像卡通化探索项目 (photo-to-cartoon translation project)

人像卡通化 (Photo to Cartoon) 中文版 | English Version 该项目为小视科技卡通肖像探索项目。您可使用微信扫描下方二维码或搜索“AI卡通秀”小程序体验卡通化效果。

Minivision_AI 3.5k Dec 30, 2022
Implementation of "Large Steps in Inverse Rendering of Geometry"

Large Steps in Inverse Rendering of Geometry ACM Transactions on Graphics (Proceedings of SIGGRAPH Asia), December 2021. Baptiste Nicolet · Alec Jacob

RGL: Realistic Graphics Lab 274 Jan 06, 2023
Finite-temperature variational Monte Carlo calculation of uniform electron gas using neural canonical transformation.

CoulombGas This code implements the neural canonical transformation approach to the thermodynamic properties of uniform electron gas. Building on JAX,

FermiFlow 9 Mar 03, 2022
A PyTorch port of the Neural 3D Mesh Renderer

Neural 3D Mesh Renderer (CVPR 2018) This repo contains a PyTorch implementation of the paper Neural 3D Mesh Renderer by Hiroharu Kato, Yoshitaka Ushik

Daniilidis Group University of Pennsylvania 1k Jan 09, 2023
Forecasting with Gradient Boosted Time Series Decomposition

ThymeBoost ThymeBoost combines time series decomposition with gradient boosting to provide a flexible mix-and-match time series framework for spicy fo

131 Jan 08, 2023
Unofficial implementation of Proxy Anchor Loss for Deep Metric Learning

Proxy Anchor Loss for Deep Metric Learning Unofficial pytorch, tensorflow and mxnet implementations of Proxy Anchor Loss for Deep Metric Learning. Not

Geonmo Gu 3 Jun 09, 2021
Efficient and Scalable Physics-Informed Deep Learning and Scientific Machine Learning on top of Tensorflow for multi-worker distributed computing

Notice: Support for Python 3.6 will be dropped in v.0.2.1, please plan accordingly! Efficient and Scalable Physics-Informed Deep Learning Collocation-

tensordiffeq 74 Dec 09, 2022
STBP is a way to train SNN with datasets by Backward propagation.

Spiking neural network (SNN), compared with depth neural network (DNN), has faster processing speed, lower energy consumption and more biological interpretability, which is expected to approach Stron

Ling Zhang 18 Dec 09, 2022
Creating a Linear Program Solver by Implementing the Simplex Method in Python with NumPy

Creating a Linear Program Solver by Implementing the Simplex Method in Python with NumPy Simplex Algorithm is a popular algorithm for linear programmi

Reda BELHAJ 2 Oct 12, 2022
Python library for science observations from the James Webb Space Telescope

JWST Calibration Pipeline JWST requires Python 3.7 or above and a C compiler for dependencies. Linux and MacOS platforms are tested and supported. Win

Space Telescope Science Institute 386 Dec 30, 2022
Labels4Free: Unsupervised Segmentation using StyleGAN

Labels4Free: Unsupervised Segmentation using StyleGAN ICCV 2021 Figure: Some segmentation masks predicted by Labels4Free Framework on real and synthet

70 Dec 23, 2022
Source code and notebooks to reproduce experiments and benchmarks on Bias Faces in the Wild (BFW).

Face Recognition: Too Bias, or Not Too Bias? Robinson, Joseph P., Gennady Livitz, Yann Henon, Can Qin, Yun Fu, and Samson Timoner. "Face recognition:

Joseph P. Robinson 41 Dec 12, 2022
An MQA (Studio, originalSampleRate) identifier for lossless flac files written in Python.

An MQA (Studio, originalSampleRate) identifier for "lossless" flac files written in Python.

Daniel 10 Oct 03, 2022
Official implement of "CAT: Cross Attention in Vision Transformer".

CAT: Cross Attention in Vision Transformer This is official implement of "CAT: Cross Attention in Vision Transformer". Abstract Since Transformer has

100 Dec 15, 2022
Malmo Collaborative AI Challenge - Team Pig Catcher

The Malmo Collaborative AI Challenge - Team Pig Catcher Approach The challenge involves 2 agents who can either cooperate or defect. The optimal polic

Kai Arulkumaran 66 Jun 29, 2022
Denoising Diffusion Probabilistic Models

Denoising Diffusion Probabilistic Models Jonathan Ho, Ajay Jain, Pieter Abbeel Paper: https://arxiv.org/abs/2006.11239 Website: https://hojonathanho.g

Jonathan Ho 1.5k Jan 08, 2023
QueryFuzz implements a metamorphic testing approach to test Datalog engines.

Datalog is a popular query language with applications in several domains. Like any complex piece of software, Datalog engines may contain bugs. The mo

34 Sep 10, 2022
A curated list of awesome game datasets, and tools to artificial intelligence in games

🎮 Awesome Game Datasets In computer science, Artificial Intelligence (AI) is intelligence demonstrated by machines. Its definition, AI research as th

Leonardo Mauro 454 Jan 03, 2023
Cweqgen - The CW Equation Generator

The CW Equation Generator The cweqgen (pronouced like "Queck-Jen") package provi

2 Jan 15, 2022
Code for "Long-tailed Distribution Adaptation"

Long-tailed Distribution Adaptation (Accepted in ACM MM2021) This project is built upon BBN. Installation pip install -r requirements.txt Usage Traini

Zhiliang Peng 10 May 18, 2022