Full Code of StanfordVL/JRMOT_ROS for AI

master ca1e87e51ecf cached
100 files
715.3 KB
190.5k tokens
839 symbols
1 requests
Download .txt
Showing preview only (750K chars total). Download the full file or copy to clipboard to get everything.
Repository: StanfordVL/JRMOT_ROS
Branch: master
Commit: ca1e87e51ecf
Files: 100
Total size: 715.3 KB

Directory structure:
gitextract_mbelvxqp/

├── CMakeLists.txt
├── LICENSE
├── README.md
├── calib/
│   ├── cameras.yaml
│   └── defaults.yaml
├── config/
│   └── featurepointnet.cfg
├── launch/
│   └── jpda_tracker.launch
├── msg/
│   ├── __init__.py
│   ├── detection2d_with_feature.msg
│   ├── detection2d_with_feature_array.msg
│   ├── detection3d_with_feature.msg
│   └── detection3d_with_feature_array.msg
├── package.xml
├── paper_experiments/
│   ├── models/
│   │   ├── __init__.py
│   │   ├── aligned_reid_model.py
│   │   ├── combination_model.py
│   │   ├── deep_sort_model.py
│   │   ├── featurepointnet_model.py
│   │   ├── pointnet_model.py
│   │   ├── resnet_reid_models.py
│   │   └── yolo_models.py
│   ├── requirements.txt
│   ├── track.py
│   └── utils/
│       ├── EKF.py
│       ├── JPDA_matching.py
│       ├── aligned_reid_utils.py
│       ├── assign_ids_detections.py
│       ├── calibration.py
│       ├── combine_and_process_detections.py
│       ├── dataset.py
│       ├── deep_sort_utils.py
│       ├── detection.py
│       ├── double_measurement_kf.py
│       ├── evaluate_detections.py
│       ├── featurepointnet_model_util.py
│       ├── featurepointnet_tf_util.py
│       ├── imm.py
│       ├── iou_matching.py
│       ├── kf_2d.py
│       ├── kf_3d.py
│       ├── linear_assignment.py
│       ├── logger.py
│       ├── mbest_ilp.py
│       ├── nn_matching.py
│       ├── pointnet_tf_util.py
│       ├── pointnet_transform_nets.py
│       ├── read_detections.py
│       ├── resnet_reid_utils.py
│       ├── test_jpda.py
│       ├── test_kf/
│       │   ├── .gitignore
│       │   ├── run_kf_test.py
│       │   ├── single_track_4state_test.p.val
│       │   ├── single_track_6state_test.p.val
│       │   ├── two_track_4state_test.p.val
│       │   └── write_kf_test.py
│       ├── track.py
│       ├── track_3d.py
│       ├── tracker.py
│       ├── tracker_3d.py
│       ├── tracking_utils.py
│       ├── visualise.py
│       └── yolo_utils/
│           ├── __init__.py
│           ├── datasets.py
│           ├── parse_config.py
│           └── utils.py
├── requirements.txt
└── src/
    ├── 3d_detector.py
    ├── EKF.py
    ├── JPDA_matching.py
    ├── __init__.py
    ├── aligned_reid_model.py
    ├── aligned_reid_utils.py
    ├── calibration.py
    ├── combination_model.py
    ├── deep_sort_utils.py
    ├── detection.py
    ├── distances.py
    ├── double_measurement_kf.py
    ├── evaluation/
    │   ├── __init__.py
    │   ├── distances 2.py
    │   └── distances.py
    ├── featurepointnet_model.py
    ├── featurepointnet_model_util.py
    ├── featurepointnet_tf_util.py
    ├── iou_matching.py
    ├── kf_2d.py
    ├── linear_assignment.py
    ├── mbest_ilp.py
    ├── nn_matching.py
    ├── pointnet_model.py
    ├── template 2.py
    ├── template.py
    ├── track_3d 2.py
    ├── track_3d.py
    ├── tracker_3d 2.py
    ├── tracker_3d.py
    ├── tracker_3d_node 2.py
    ├── tracker_3d_node.py
    ├── tracking_utils 2.py
    └── tracking_utils.py

================================================
FILE CONTENTS
================================================

================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 2.8.3)
project(jpda_rospack)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  vision_msgs
  message_generation
)

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
add_message_files(
   FILES
   detection2d_with_feature.msg
   detection2d_with_feature_array.msg
   detection3d_with_feature.msg
   detection3d_with_feature_array.msg
 )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
 generate_messages(
   DEPENDENCIES
   std_msgs
   vision_msgs
   jpda_rospack
  )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES jpda_rospack
  CATKIN_DEPENDS roscpp rospy std_msgs vision_msgs message_runtime
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/jpda_rospack.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/jpda_rospack_node.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables and/or libraries for installation
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_jpda_rospack.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Stanford Vision and Learning Group

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# JRMOT ROS package

The repository contains the code for the work "JRMOT: A Real-Time 3D Multi-Object Tracker and a New Large-Scale Dataset".

Note that due to the global pandemic, this repository is still a work in progress. Updates will be made as soon as possible.

## Introduction

JRMOT is a 3D multi object tracking system that:
- Is real-time
- Is online
- Fuses 2D and 3D information
- Achieves State of the Art performance on KITTI

We also release JRDB:
- A dataset with over 2 million annotated boxes and 3500 time consistent trajectories in 2D and 3D
- Captured in social, human-centric settings
- Captured by our social mobile-manipulator JackRabbot
- Contains 360 degree cylindrical images, stereo camera images, 3D pointclouds and more sensing modalties

All information, including download links for JRDB can be found [here](https://jrdb.stanford.edu).

## JRMOT
![system overview](https://github.com/StanfordVL/JRMOT_ROS/blob/master/assets/framework.png)

- Our system is built on top of state of the art 2D and 3D detectors (mask-RCNN and F-PointNet respectively). These detections are associated with predicted track locations at every time step. 
- Association is done via a novel feature fusion, as well as a cost selection procedure, followed by Kalman state gating and JPDA. 
- Given the JPDA output, we use both 2D and 3D detections in a novel multi-modal Kalman filter to update the track locations.


## Using the code

There are 3 nodes forming parts of the ROS package:
+ 3d_detector.py: Runs F-PointNet, which performs 3D detection and 3D feature extraction
+ template.py: Runs Aligned-Re-ID, which performs 2D feature extraction
+ tracker_3d_node.py: Performs tracking while taking both 2D detections + features and 3D detections + features as input

The launch file in the folder "launch" launches all 3 nodes.

## Dependencies

The following are dependencies of the code:

+ 2D detector: The 2D detector is not included in this package. To interface with your own 2D detector, please modify the file template.py to subscribe to the correct topic, and also to handle the conversion from ROS message to numpy array.
+ Spencer People Tracking messages: The final tracker output is in a Spencer People Tracking message. Please install this package and include these message types.
+ Various python packages: These can be found in [requirements.txt](./requirements.txt).. Please install all dependencies prior to running the code (including CUDA and cuDNN. Additionally, this code requires a solver called Gurobi. Instructions to install gurobipy can be found [here](https://www.gurobi.com/documentation/9.0/quickstart_mac/the_grb_python_interface_f.html).
+ Weight files: The trained weights, (trained on JRDB) for FPointNet and Aligne-ReID can be found [here](https://drive.google.com/open?id=1YQinMPVWEI44KezS9inXe0mvVnm4aL3s).

## Citation

If you find this work useful, please cite:
```
@INPROCEEDINGS{shenoi2020jrmot,
  author={A. {Shenoi} and M. {Patel} and J. {Gwak} and P. {Goebel} and A. {Sadeghian} and H. {Rezatofighi} and R. {Mart\'in-Mart\'in} and S. {Savarese}},
  booktitle={2020 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS)}, 
  title={JRMOT: A Real-Time 3D Multi-Object Tracker and a New Large-Scale Dataset}, 
  year={2020},
  volume={},
  number={},
  pages={10335-10342},
  doi={10.1109/IROS45743.2020.9341635}}
```

If you utilise our dataset, please also cite:

```
@article{martin2019jrdb,
  title={JRDB: A dataset and benchmark of egocentric visual perception for navigation in human environments},
  author={Mart{\'i}n-Mart{\'i}n, Roberto and Patel, Mihir and Rezatofighi, Hamid and Shenoi, Abhijeet and Gwak, JunYoung and Frankel, Eric and Sadeghian, Amir and Savarese, Silvio},
  journal={arXiv preprint arXiv:1910.11792},
  year={2019}
}
```
## 


================================================
FILE: calib/cameras.yaml
================================================
stitching:
  radius: 3360000
  rotation: 0
  scalewidth: 1831
  crop: 1
cameras:
  # camera order matters!
  sensor_0:
    width: 752
    height: 480
    D: -0.336591 0.159742 0.00012697 -7.22557e-05 -0.0461953
    # K = fx   0    cx
    #     0    fy   cy
    #     0    0    1
    K: >
      476.71 0 350.738
      0 479.505 209.532
      0 0 1
    R: >
      0.999994 0.000654539 0.00340293
      -0.000654519 1 -6.81963e-06
      -0.00340293 4.59231e-06 0.999994
    T: -0.0104242 -3.70974 -56.9177
  sensor_1:
    width: 752
    height: 480
    D: -0.335073 0.151959 -0.000232061 0.00032014 -0.0396825
    K: >
      483.254 0 365.33
      0 485.78 210.953
      0 0 1
    R: >
      0.305706 -0.00895443 -0.952084
      0.0110396 0.999922 -0.00585963
      0.952062 -0.0087193 0.305781
    T: 0.93957 -4.05131 -52.03
  sensor_2:
    width: 752
    height: 480
    D: -0.338469 0.156256 -0.000385467 0.000295485 -0.0401965
    K: >
      483.911 0 355.144
      0 486.466 223.026
      0 0 1
    R: >
      -0.806828 0.0136361 -0.590629
      0.00870468 0.999899 0.011194
      0.590723 0.00389039 -0.806865
    T: -0.25753 -6.54978 -47.7311
  sensor_3:
    width: 752
    height: 480
    D: -0.330848 0.14747 8.59247e-05 0.000262599 -0.0385311
    K: >
      475.807 0 339.53
      0 478.371 188.481
      0 0 1
    R: >
      -0.811334 0.0033829 0.584574
      0.00046071 0.999987 -0.00514746
      -0.584583 -0.00390699 -0.811324
    T: 2.72207 -6.82928 -45.9778
  sensor_4:
    width: 752
    height: 480
    D: -0.34064 0.168338 0.000147292 0.000229372 -0.0516133
    K: >
      485.046 0 368.864
      0 488.185 208.215
      0 0 1
    R: >
      0.310275 0.00160497 0.950645
      -0.00648686 0.999979 0.000428942
      -0.950625 -0.00629979 0.310279
    T: -0.333857 -5.12974 -56.0573
  sensor_5:
    width: 752
    height: 480
    D: -0.338422 0.163703 -0.000376267 7.73351e-06 -0.0479871
    K: >
      478.406 0 353.499
      0 481.322 190.225
      0 0 1
    R: >
      0.999995 0.00282205 0.00163291
      -0.00282345 0.999996 0.000852931
      -0.00163049 -0.000857537 0.999998
    T: -0.903588 -126.851 -56.6256
  sensor_6:
    width: 752
    height: 480
    D: -0.340676 0.165511 -0.00035978 0.000181532 -0.0493721
    K: >
      480.459 0 362.503
      0 482.924 197.949
      0 0 1
    R: >
      0.308288 -0.0110391 -0.951229
      -0.000933102 0.999929 -0.0119067
      0.951293 0.00455829 0.308256
    T: 1.74525 -127.214 -51.7722
  sensor_7:
    width: 752
    height: 480
    D: -0.344379 0.170343 -0.000137847 0.000141047 -0.0510536
    K: >
      486.491 0 361.559
      0 489.22 210.547
      0 0 1
    R: >
      -0.808201 0.0313998 -0.588068
      0.026057 0.999506 0.0175574
      0.588329 -0.00113337 -0.808621
    T: -2.56535 -129.191 -47.5803
  sensor_8:
    width: 752
    height: 480
    D: -0.331228 0.144696 0.000117553 0.000566449 -0.0343506
    K: >
      476.708 0 354.16
      0 479.424 209.383
      0 0 1
    R: >
      -0.807384 -0.00296577 0.590019
      -0.0122001 0.999857 -0.0116688
      -0.589901 -0.0166195 -0.807305
    T: 3.39727 -129.381 -45.2409
  sensor_9:
    width: 752
    height: 480
    D: -0.345189 0.180808 0.000276465 0.000131868 -0.062103
    K: >
      484.219 0 345.303
      0 487.312 192.371
      0 0 1
    R: >
      0.308505 0.00370159 0.951215
      -0.00403535 0.999988 -0.00258261
      -0.951214 -0.00304174 0.308517
    T: 0.354966 -128.218 -54.0617



================================================
FILE: calib/defaults.yaml
================================================
calibrated:
  # the lidar_to_rgb parameters allow tweaking of the transformation between lidar and rgb frames
  # the default transformation is taken from the TF Tree
  # NOTE: applied to the original (sensor/velodyne) frame [x forward, y left, z up]:
  lidar_upper_to_rgb:
    # in meters: [x,y,z]
    translation: [0, 0, -0.33529]
    # in radians: [x,y,z]
    rotation: [0, 0, 0.085]
 
  lidar_lower_to_rgb:

    translation: [0, 0, 0.13511]
    
    rotation: [0, 0, 0]
image:
  # all in pixels
  width: 3760
  height: 480
  # y-axis forward pixel offset (e.g. 3760/2 => 1880, b/c center of the cylindrical image is forward)
  #  TODO: move into calibrated params, when auto-calibration is possible
  stitched_image_offset: 1880

frames:
  # lookup for people transforms
  global: base_link
  # name of the rgb360 camera frame to which we wish to transform
  rgb360: occam


================================================
FILE: config/featurepointnet.cfg
================================================
[general]
num_point = 1024
model_path = /home/sibot/jr2_catkin_ws/src/jpda_rospack/src/fpointnet_jrdb/model.ckpt


================================================
FILE: launch/jpda_tracker.launch
================================================
<?xml version="1.0" encoding="utf-8"?>

<launch>
  <!-- Console launch prefix -->
  <arg name="output"        default="screen"/>

  <!-- Config and weights folder. -->
  <arg name="aligned_reid_model"         default="$(find jpda_rospack)/src/aligned_reid_JRDB_weights.pth"/>
  <arg name="fpointnet_config"           default="$(find jpda_rospack)/config/featurepointnet.cfg"/>
  <arg name="calib_3d"                   default="$(find jpda_rospack)/calib"/>
  <arg name="combination_depth_weight"   default="1"/>
  <arg name="combination_model_path"     default="0"/>


  <node pkg="jpda_rospack" type="template.py" name="jpda_aligned_reid" output="$(arg output)" respawn="false">
    <param name="aligned_reid_model"          value="$(arg aligned_reid_model)" />
  </node>

  <node pkg="jpda_rospack" type="3d_detector.py" name="jpda_3d_detector" output="$(arg output)" respawn="false">
    <param name="fpointnet_config"          value="$(arg fpointnet_config)" />
    <param name="calib_3d"                  value="$(arg calib_3d)" />
  </node>
  
  <node pkg="jpda_rospack" type="tracker_3d_node.py" name="jpda_tracker_3d" output="$(arg output)" respawn="false">
    <param name="combination_depth_weight"           value="$(arg combination_depth_weight)" />
    <param name="calib_3d"                           value="$(arg calib_3d)" />
    <param name="combination_model_path"             value="$(arg combination_model_path)" />
  </node>

</launch>


================================================
FILE: msg/__init__.py
================================================


================================================
FILE: msg/detection2d_with_feature.msg
================================================
# This message contains a 2D bounding box corresponding to the detection of a person
# Also contains the feature of this person used for re-ID

Header header #header timestamp is time of frame acquisition


uint64 x1 # x coordinate of the top left of the bounding box
uint64 y1 # y coordinate of the top left of the bounding box
uint64 x2 # x coordinate of the bottom right of the bounding box
uint64 y2 # y coordinate of the bottom right of the bounding box

float64[] feature # re-ID feature

uint8 frame_det_id #unique id of this detection within this frame (used for associating 2D and 3D detections)
bool valid # whether detection is valid (within the boundaries of the image and has minimum required size)

================================================
FILE: msg/detection2d_with_feature_array.msg
================================================
Header header
detection2d_with_feature[] detection2d_with_features

================================================
FILE: msg/detection3d_with_feature.msg
================================================
# This message contains a 3D bounding box corresponding to the detection of a person
# Also contains the feature of this person used for re-ID

Header header #header timestamp is time of frame acquisition


float32 x # x coordinate of the center of the bottom face of the bounding box
float32 y # y coordinate of the center of the bottom face of the bounding box
float32 z # x coordinate of the center of the bottom face of the bounding box
float32 l # size of bounding box along x dimension
float32 h # size of bounding box along y dimension
float32 w # size of bounding box along z dimension
float32 theta # rotation of bounding box with respect to the positive x axis


float64[] feature # re-ID feature

uint8 frame_det_id #unique id of this detection within this frame (used for associating 2D and 3D detections)
bool valid # whether detection is valid (enough lidar points)

================================================
FILE: msg/detection3d_with_feature_array.msg
================================================
Header header
detection3d_with_feature[] detection3d_with_features

================================================
FILE: package.xml
================================================
<?xml version="1.0"?>
<package format="2">
  <name>jpda_rospack</name>
  <version>0.0.1</version>
  <description>The jpda_rospack package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="ashenoi@cs.stanford.edu">ashenoi</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/jpda_rospack</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
    <build_depend>message_generation</build_depend>
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
    <exec_depend>message_runtime</exec_depend>
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>vision_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <build_export_depend>vision_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <exec_depend>vision_msgs</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>


================================================
FILE: paper_experiments/models/__init__.py
================================================


================================================
FILE: paper_experiments/models/aligned_reid_model.py
================================================
import torch
import torch.nn as nn
import torch.nn.init as init
import torch.nn.functional as F
import torch.utils.model_zoo as model_zoo
import os
import math


class Model(nn.Module):
  def __init__(self, local_conv_out_channels=128, num_classes=None):
    super(Model, self).__init__()
    self.base = resnet50(pretrained=True)
    planes = 2048
    self.local_conv = nn.Conv2d(planes, local_conv_out_channels, 1)
    self.local_bn = nn.BatchNorm2d(local_conv_out_channels)
    self.local_relu = nn.ReLU(inplace=True)

    if num_classes is not None:
      self.fc = nn.Linear(planes, num_classes)
      init.normal(self.fc.weight, std=0.001)
      init.constant(self.fc.bias, 0)

  def forward(self, x):
    """
    Returns:
      global_feat: shape [N, C]
      local_feat: shape [N, H, c]
    """
    # shape [N, C, H, W]
    feat = self.base(x)
    global_feat = F.avg_pool2d(feat, feat.size()[2:])
    # shape [N, C]
    global_feat = global_feat.view(global_feat.size(0), -1)
    # shape [N, C, H, 1]
    local_feat = torch.mean(feat, -1, keepdim=True)
    local_feat = self.local_relu(self.local_bn(self.local_conv(local_feat)))
    # shape [N, H, c]
    local_feat = local_feat.squeeze(-1).permute(0, 2, 1)

    if hasattr(self, 'fc'):
      logits = self.fc(global_feat)
      return global_feat, local_feat, logits

    return global_feat, local_feat


__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',
           'resnet152']

model_urls = {
  'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
  'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',
  'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
  'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',
  'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',
}
os.environ["TORCH_HOME"] = "./ResNet_Model"

def conv3x3(in_planes, out_planes, stride=1):
  """3x3 convolution with padding"""
  return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
                   padding=1, bias=False)


class BasicBlock(nn.Module):
  expansion = 1

  def __init__(self, inplanes, planes, stride=1, downsample=None):
    super(BasicBlock, self).__init__()
    self.conv1 = conv3x3(inplanes, planes, stride)
    self.bn1 = nn.BatchNorm2d(planes)
    self.relu = nn.ReLU(inplace=True)
    self.conv2 = conv3x3(planes, planes)
    self.bn2 = nn.BatchNorm2d(planes)
    self.downsample = downsample
    self.stride = stride

  def forward(self, x):
    residual = x

    out = self.conv1(x)
    out = self.bn1(out)
    out = self.relu(out)

    out = self.conv2(out)
    out = self.bn2(out)

    if self.downsample is not None:
      residual = self.downsample(x)

    out += residual
    out = self.relu(out)

    return out


class Bottleneck(nn.Module):
  expansion = 4

  def __init__(self, inplanes, planes, stride=1, downsample=None):
    super(Bottleneck, self).__init__()
    self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
    self.bn1 = nn.BatchNorm2d(planes)
    self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
                           padding=1, bias=False)
    self.bn2 = nn.BatchNorm2d(planes)
    self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
    self.bn3 = nn.BatchNorm2d(planes * 4)
    self.relu = nn.ReLU(inplace=True)
    self.downsample = downsample
    self.stride = stride

  def forward(self, x):
    residual = x

    out = self.conv1(x)
    out = self.bn1(out)
    out = self.relu(out)

    out = self.conv2(out)
    out = self.bn2(out)
    out = self.relu(out)

    out = self.conv3(out)
    out = self.bn3(out)

    if self.downsample is not None:
      residual = self.downsample(x)

    out += residual
    out = self.relu(out)

    return out


class ResNet(nn.Module):

  def __init__(self, block, layers):
    self.inplanes = 64
    super(ResNet, self).__init__()
    self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
                           bias=False)
    self.bn1 = nn.BatchNorm2d(64)
    self.relu = nn.ReLU(inplace=True)
    self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
    self.layer1 = self._make_layer(block, 64, layers[0])
    self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
    self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
    self.layer4 = self._make_layer(block, 512, layers[3], stride=2)

    for m in self.modules():
      if isinstance(m, nn.Conv2d):
        n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
        m.weight.data.normal_(0, math.sqrt(2. / n))
      elif isinstance(m, nn.BatchNorm2d):
        m.weight.data.fill_(1)
        m.bias.data.zero_()

  def _make_layer(self, block, planes, blocks, stride=1):
    downsample = None
    if stride != 1 or self.inplanes != planes * block.expansion:
      downsample = nn.Sequential(
        nn.Conv2d(self.inplanes, planes * block.expansion,
                  kernel_size=1, stride=stride, bias=False),
        nn.BatchNorm2d(planes * block.expansion),
      )

    layers = []
    layers.append(block(self.inplanes, planes, stride, downsample))
    self.inplanes = planes * block.expansion
    for i in range(1, blocks):
      layers.append(block(self.inplanes, planes))

    return nn.Sequential(*layers)

  def forward(self, x):
    x = self.conv1(x)
    x = self.bn1(x)
    x = self.relu(x)
    x = self.maxpool(x)

    x = self.layer1(x)
    x = self.layer2(x)
    x = self.layer3(x)
    x = self.layer4(x)

    return x


def remove_fc(state_dict):
  """Remove the fc layer parameters from state_dict."""
  new_state_dict = state_dict.copy()
  for key, value in state_dict.items():
    if key.startswith('fc.'):
      del new_state_dict[key]
  return new_state_dict


def resnet18(pretrained=False):
  """Constructs a ResNet-18 model.

  Args:
      pretrained (bool): If True, returns a model pre-trained on ImageNet
  """
  model = ResNet(BasicBlock, [2, 2, 2, 2])
  if pretrained:
    model.load_state_dict(remove_fc(model_zoo.load_url(model_urls['resnet18'])))
  return model


def resnet34(pretrained=False):
  """Constructs a ResNet-34 model.

  Args:
      pretrained (bool): If True, returns a model pre-trained on ImageNet
  """
  model = ResNet(BasicBlock, [3, 4, 6, 3])
  if pretrained:
    model.load_state_dict(remove_fc(model_zoo.load_url(model_urls['resnet34'])))
  return model


def resnet50(pretrained=False):
  """Constructs a ResNet-50 model.

  Args:
      pretrained (bool): If True, returns a model pre-trained on ImageNet
  """
  model = ResNet(Bottleneck, [3, 4, 6, 3])
  if pretrained:
    model.load_state_dict(remove_fc(model_zoo.load_url(model_urls['resnet50'], model_dir="./ResNet_Model")))### ADDED MODEL_DIR
  return model


def resnet101(pretrained=False):
  """Constructs a ResNet-101 model.

  Args:
      pretrained (bool): If True, returns a model pre-trained on ImageNet
  """
  model = ResNet(Bottleneck, [3, 4, 23, 3])
  if pretrained:
    model.load_state_dict(
      remove_fc(model_zoo.load_url(model_urls['resnet101'])))
  return model


def resnet152(pretrained=False):
  """Constructs a ResNet-152 model.

  Args:
      pretrained (bool): If True, returns a model pre-trained on ImageNet
  """
  model = ResNet(Bottleneck, [3, 8, 36, 3])
  if pretrained:
    model.load_state_dict(
      remove_fc(model_zoo.load_url(model_urls['resnet152'])))
  return model


================================================
FILE: paper_experiments/models/combination_model.py
================================================
import pdb

import numpy as np
import torch.nn as nn

class CombiNet(nn.Module):
	def __init__(self, in_dim = 2560, hidden_units = 512, out_dim = 2560):
		super().__init__()
		self.fc1 = nn.Linear(in_dim, 2*hidden_units)
		# self.bn1 = nn.BatchNorm1d(hidden_units)
		self.fc2 = nn.Linear(2*hidden_units, 2*hidden_units)
		# self.bn2 = nn.BatchNorm1d(2*hidden_units)
		self.fc3 = nn.Linear(2*hidden_units, out_dim)
		self.relu = nn.ReLU()
		self.apply(weight_init)
	def forward(self, x):
		# out = nn.functional.normalize(x)
		skip = x
		out = self.fc1(x)
		# out = self.bn1(out)
		out = self.relu(out)
		out = self.fc2(out)
		# out = self.bn2(out)
		out = self.relu(out)
		out = self.fc3(out)
		# out = nn.functional.normalize(out)
		out += skip
		return out

class CombiLSTM(nn.Module):
	def __init__(self, in_dim = 2560, hidden_units = 512, out_dim = 2560):
		super().__init__()
		self.in_linear1 = nn.Linear(in_dim, hidden_units)
		# self.bn1 = nn.BatchNorm1d(hidden_units)
		self.in_linear2 = nn.Linear(hidden_units, hidden_units)
		self.rnn = nn.LSTM(input_size = hidden_units, hidden_size = hidden_units, dropout = 0)
		self.out_linear1 = nn.Linear(hidden_units, hidden_units)
		# self.bn2 = nn.BatchNorm1d(hidden_units)
		self.out_linear2 = nn.Linear(hidden_units, out_dim)
		self.relu = nn.ReLU()
		self.apply(weight_init)

	def forward(self, x, hidden = None):
		out = nn.functional.normalize(x)
		skip = out
		out = self.in_linear1(out)
		# out = self.bn1(out)
		out = self.relu(out)
		out = self.in_linear2(out)
		out = out.unsqueeze(1) #Adding batch dimension
		if hidden is None:
			out, hidden = self.rnn(out)
		else:
			out, hidden = self.rnn(out, hidden)

		out = out.squeeze(1) #removing batch dimension
		out = self.out_linear1(out)
		# out = self.bn2(out)
		out = self.relu(out)
		out = self.out_linear2(out)
		out = nn.functional.normalize(out)
		out += skip
		return out, hidden

def weight_init(m):
	if type(m)==nn.Linear:
		nn.init.xavier_normal_(m.weight, gain=np.sqrt(2))
	elif type(m)==nn.LSTM:
		nn.init.xavier_normal_(m.weight_ih_l0)
		nn.init.xavier_normal_(m.weight_hh_l0)


================================================
FILE: paper_experiments/models/deep_sort_model.py
================================================
import tensorflow as tf
from skimage.transform import resize
import numpy as np

class ImageEncoder(object):

    def __init__(self, checkpoint_filename="weights/deep_sort_weights.pb", input_name="images",
                 output_name="features"):
        config = tf.ConfigProto()
        config.gpu_options.allow_growth = True
        self.session = tf.Session(config=config)
        with tf.gfile.GFile(checkpoint_filename, "rb") as file_handle:
            graph_def = tf.GraphDef()
            graph_def.ParseFromString(file_handle.read())
        tf.import_graph_def(graph_def, name="net")
        self.input_var = tf.get_default_graph().get_tensor_by_name(
            "net/%s:0" % input_name)
        self.output_var = tf.get_default_graph().get_tensor_by_name(
            "net/%s:0" % output_name)

        assert len(self.output_var.get_shape()) == 2
        assert len(self.input_var.get_shape()) == 4
        self.feature_dim = self.output_var.get_shape().as_list()[-1]
        self.image_shape = self.input_var.get_shape().as_list()[1:]

    def __call__(self, data_x):
        #Resize input to expected size for model
        data_x = resize(data_x[0], self.image_shape, anti_aliasing=True, mode='reflect')
        data_x = np.expand_dims(data_x, 0)
        out = self.session.run(self.output_var, feed_dict={self.input_var: data_x})
        return out

if __name__ == '__main__':
    encoder = ImageEncoder()

================================================
FILE: paper_experiments/models/featurepointnet_model.py
================================================
import os, pdb
import numpy as np
import tensorflow as tf
tf.logging.set_verbosity(tf.logging.ERROR)
import configparser

import utils.featurepointnet_tf_util as tf_util
import utils.featurepointnet_model_util as model_util
from utils.calibration import Calibration, OmniCalibration

batch_size = 45 #TODO: Update if needed?

class FPointNet():
    def __init__(self, config_path):
        parser = configparser.SafeConfigParser()
        parser.read(config_path)
        self.num_point = parser.getint('general', 'num_point')
        self.model_path = parser.get('general', 'model_path')

        with tf.device('/gpu:'+str('0')):
            pointclouds_pl, one_hot_vec_pl, labels_pl, centers_pl, \
            heading_class_label_pl, heading_residual_label_pl, \
            size_class_label_pl, size_residual_label_pl = model_util.placeholder_inputs(batch_size, self.num_point)
            is_training_pl = tf.placeholder(tf.bool, shape=())
            end_points, depth_feature = self.get_model(pointclouds_pl, one_hot_vec_pl, is_training_pl)
            self.object_pointcloud = tf.placeholder(tf.float32, shape=(None, None, 3))
            #depth_feature = self.get_depth_feature_op(is_training_pl)
            loss = model_util.get_loss(labels_pl, centers_pl, heading_class_label_pl, heading_residual_label_pl, size_class_label_pl, size_residual_label_pl, end_points)
            self.saver = tf.train.Saver()

        # Create a session
        config = tf.ConfigProto()
        config.gpu_options.allow_growth = True
        config.allow_soft_placement = True
        self.sess = tf.Session(config=config)

        #Initialize variables
        self.sess.run(tf.global_variables_initializer())
        # Restore variables from disk.
        self.saver.restore(self.sess, self.model_path)
        self.ops = {'pointclouds_pl': pointclouds_pl,
               'one_hot_vec_pl': one_hot_vec_pl,
               'labels_pl': labels_pl,
               'centers_pl': centers_pl,
               'heading_class_label_pl': heading_class_label_pl,
               'heading_residual_label_pl': heading_residual_label_pl,
               'size_class_label_pl': size_class_label_pl,
               'size_residual_label_pl': size_residual_label_pl,
               'is_training_pl': is_training_pl,
               'logits': end_points['mask_logits'],
               'center': end_points['center'],
               'end_points': end_points,
               'depth_feature':depth_feature,
               'loss': loss}

    # @profile
    def __call__(self, input_point_cloud, rot_angle, peds=False):
        '''
        one_hot_vec = np.zeros((batch_size, 3))
        feed_dict = {self.pointclouds_pl: input_point_cloud,
                     self.one_hot_vec_pl: one_hot_vec,
                     self.is_training_pl: False}
        features = self.sess.run(self.feature,feed_dict=feed_dict)
        return features '''

        ''' Run inference for frustum pointnets in batch mode '''
        
        one_hot_vec = np.zeros((batch_size,3))
        if peds:
            one_hot_vec[:, 1] = 1
        num_batches = input_point_cloud.shape[0]//batch_size + 1
        num_inputs = input_point_cloud.shape[0]
        if input_point_cloud.shape[0]%batch_size !=0:
            input_point_cloud = np.vstack([input_point_cloud, np.zeros((batch_size - input_point_cloud.shape[0]%batch_size, self.num_point, 4))])
        else:
            num_batches -= 1
        logits = np.zeros((input_point_cloud.shape[0], input_point_cloud.shape[1], 2))
        centers = np.zeros((input_point_cloud.shape[0], 3))
        heading_logits = np.zeros((input_point_cloud.shape[0], model_util.NUM_HEADING_BIN))
        heading_residuals = np.zeros((input_point_cloud.shape[0], model_util.NUM_HEADING_BIN))
        size_logits = np.zeros((input_point_cloud.shape[0], model_util.NUM_SIZE_CLUSTER))
        size_residuals = np.zeros((input_point_cloud.shape[0], model_util.NUM_SIZE_CLUSTER, 3))
        mask_mean_prob = np.zeros((input_point_cloud.shape[0],)) # Step scores
        heading_prob = np.zeros((input_point_cloud.shape[0],))
        size_prob = np.zeros((input_point_cloud.shape[0],))
        scores = np.zeros((input_point_cloud.shape[0],)) # 3D box score 
        features = np.zeros((input_point_cloud.shape[0], 512))
        
        for i in range(num_batches):    
            ep = self.ops['end_points'] 
            feed_dict = {\
                self.ops['pointclouds_pl']: input_point_cloud[i*batch_size: (i+1)*batch_size],
                self.ops['one_hot_vec_pl']: one_hot_vec,
                self.ops['is_training_pl']: False}

            batch_logits, batch_centers, \
            batch_heading_scores, batch_heading_residuals, \
            batch_size_scores, batch_size_residuals, batch_features = \
                self.sess.run([self.ops['logits'], self.ops['center'],
                    ep['heading_scores'], ep['heading_residuals'],
                    ep['size_scores'], ep['size_residuals'], self.ops['depth_feature']],
                    feed_dict=feed_dict)

            logits[i*batch_size: (i+1)*batch_size] = batch_logits
            centers[i*batch_size: (i+1)*batch_size] = batch_centers
            heading_logits[i*batch_size: (i+1)*batch_size] = batch_heading_scores
            heading_residuals[i*batch_size: (i+1)*batch_size] = batch_heading_residuals
            size_logits[i*batch_size: (i+1)*batch_size] = batch_size_scores
            size_residuals[i*batch_size: (i+1)*batch_size] = batch_size_residuals
            features[i*batch_size: (i+1)*batch_size] = batch_features[:,0,:]

        heading_cls = np.argmax(heading_logits, 1) # B
        size_cls = np.argmax(size_logits, 1) # B
        heading_res = np.vstack([heading_residuals[i, heading_cls[i]] for i in range(heading_cls.shape[0])])
        size_res = np.vstack([size_residuals[i, size_cls[i], :] for i in range(size_cls.shape[0])])

        #TODO: Make this accept batches if wanted
        boxes = []
        for i in range(num_inputs):
            box = np.array(model_util.from_prediction_to_label_format(centers[i], heading_cls[i], heading_res[i], size_cls[i], size_res[i], rot_angle[i]))
            box[6] = np.squeeze(box[6])
            swp = box[5]
            box[5] = box[4]
            box[4] = swp
            boxes.append(box)       
        boxes = np.vstack(boxes)
        return boxes, mask_mean_prob[:num_inputs], features[:num_inputs]


    def get_instance_seg_v1_net(self, point_cloud, one_hot_vec, is_training, bn_decay, end_points):
        ''' 3D instance segmentation PointNet v1 network.
        Input:
            point_cloud: TF tensor in shape (B,N,4)
                frustum point clouds with XYZ and intensity in point channels
                XYZs are in frustum coordinate
            one_hot_vec: TF tensor in shape (B,3)
                length-3 vectors indicating predicted object type
            is_training: TF boolean scalar
            bn_decay: TF float scalar
            end_points: dict
        Output:
            logits: TF tensor in shape (B,N,2), scores for bkg/clutter and object
            end_points: dict
        '''
        num_point = point_cloud.get_shape()[1].value

        net = tf.expand_dims(point_cloud, 2)

        net = tf_util.conv2d(net, 64, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv1', bn_decay=bn_decay)
        net = tf_util.conv2d(net, 64, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv2', bn_decay=bn_decay)
        point_feat = tf_util.conv2d(net, 64, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv3', bn_decay=bn_decay)
        net = tf_util.conv2d(point_feat, 128, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv4', bn_decay=bn_decay)
        net = tf_util.conv2d(net, 1024, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv5', bn_decay=bn_decay)

        global_feat = tf_util.max_pool2d(net, [num_point,1],
                                         padding='VALID', scope='maxpool')

        global_feat = tf.concat([global_feat, tf.expand_dims(tf.expand_dims(one_hot_vec, 1), 1)], axis=3)
        global_feat_expand = tf.tile(global_feat, [1, num_point, 1, 1])
        concat_feat = tf.concat(axis=3, values=[point_feat, global_feat_expand])

        net = tf_util.conv2d(concat_feat, 512, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv6', bn_decay=bn_decay)
        net = tf_util.conv2d(net, 256, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv7', bn_decay=bn_decay)
        net = tf_util.conv2d(net, 128, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv8', bn_decay=bn_decay)
        net = tf_util.conv2d(net, 128, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv9', bn_decay=bn_decay)
        net = tf_util.dropout(net, is_training, 'dp1', keep_prob=0.5)

        logits = tf_util.conv2d(net, 2, [1,1],
                             padding='VALID', stride=[1,1], activation_fn=None,
                             scope='conv10')
        logits = tf.squeeze(logits, [2]) # BxNxC
        return logits, end_points
     
    def get_3d_box_estimation_v1_net(self, object_point_cloud, one_hot_vec,is_training, bn_decay, end_points):
        ''' 3D Box Estimation PointNet v1 network.
        Input:
            object_point_cloud: TF tensor in shape (B,M,C)
                point clouds in object coordinate
            one_hot_vec: TF tensor in shape (B,3)
                length-3 vectors indicating predicted object type
        Output:
            output: TF tensor in shape (B,3+NUM_HEADING_BIN*2+NUM_SIZE_CLUSTER*4)
                including box centers, heading bin class scores and residuals,
                and size cluster scores and residuals
        ''' 
        num_point = object_point_cloud.get_shape()[1].value
        net = tf.expand_dims(object_point_cloud, 2)
        net = tf_util.conv2d(net, 128, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv-reg1', bn_decay=bn_decay)
        net = tf_util.conv2d(net, 128, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv-reg2', bn_decay=bn_decay)
        net = tf_util.conv2d(net, 256, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv-reg3', bn_decay=bn_decay)
        net = tf_util.conv2d(net, 512, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv-reg4', bn_decay=bn_decay)

        features = tf.reduce_max(net, axis = 1)

        net = tf_util.max_pool2d(net, [num_point,1],
            padding='VALID', scope='maxpool2')
        net = tf.squeeze(net, axis=[1,2])
        net = tf.concat([net, one_hot_vec], axis=1)
        net = tf_util.fully_connected(net, 512, scope='fc1', bn=True,
            is_training=is_training, bn_decay=bn_decay)
        net = tf_util.fully_connected(net, 256, scope='fc2', bn=True,
            is_training=is_training, bn_decay=bn_decay)

        # The first 3 numbers: box center coordinates (cx,cy,cz),
        # the next NUM_HEADING_BIN*2:  heading bin class scores and bin residuals
        # next NUM_SIZE_CLUSTER*4: box cluster scores and residuals
        output = tf_util.fully_connected(net,
            3+model_util.NUM_HEADING_BIN*2+model_util.NUM_SIZE_CLUSTER*4, activation_fn=None, scope='fc3')
        return output, end_points, features

    def get_model(self, point_cloud, one_hot_vec, is_training, bn_decay=None):
        ''' Frustum PointNets model. The model predict 3D object masks and
        amodel bounding boxes for objects in frustum point clouds.
        Input:
            point_cloud: TF tensor in shape (B,N,4)
                frustum point clouds with XYZ and intensity in point channels
                XYZs are in frustum coordinate
            one_hot_vec: TF tensor in shape (B,3)
                length-3 vectors indicating predicted object type
            is_training: TF boolean scalar
            bn_decay: TF float scalar
        Output:
            end_points: dict (map from name strings to TF tensors)
        '''
        end_points = {}
        
        # 3D Instance Segmentation PointNet
        logits, end_points = self.get_instance_seg_v1_net(\
            point_cloud, one_hot_vec,
            is_training, bn_decay, end_points)
        end_points['mask_logits'] = logits

        # Masking
        # select masked points and translate to masked points' centroid
        object_point_cloud_xyz, mask_xyz_mean, end_points = \
            model_util.point_cloud_masking(point_cloud, logits, end_points)

        # T-Net and coordinate translation
        center_delta, end_points = model_util.get_center_regression_net(\
            object_point_cloud_xyz, one_hot_vec,
            is_training, bn_decay, end_points)
        stage1_center = center_delta + mask_xyz_mean # Bx3
        end_points['stage1_center'] = stage1_center
        # Get object point cloud in object coordinate
        object_point_cloud_xyz_new = \
            object_point_cloud_xyz - tf.expand_dims(center_delta, 1)

        # Amodel Box Estimation PointNet
        output, end_points, features = self.get_3d_box_estimation_v1_net(\
            object_point_cloud_xyz_new, one_hot_vec,
            is_training, bn_decay, end_points)

        # Parse output to 3D box parameters
        end_points = model_util.parse_output_to_tensors(output, end_points)
        end_points['center'] = end_points['center_boxnet'] + stage1_center # Bx3

        return end_points, features
    
    def get_depth_feature_op(self, is_training):

        net = tf.expand_dims(self.object_pointcloud, 2)
        net = tf_util.conv2d(net, 128, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv-reg1', bn_decay=None)
        net = tf_util.conv2d(net, 128, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv-reg2', bn_decay=None)
        net = tf_util.conv2d(net, 256, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv-reg3', bn_decay=None)
        net = tf_util.conv2d(net, 512, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv-reg4', bn_decay=None)
        net = tf.reduce_max(net, axis = 1)
        
        return net

    def get_depth_feature(self, object_pointcloud):
        
        feed_dict = {self.object_pointcloud:object_pointcloud, self.ops['is_training_pl']:False}
        depth_feature = self.sess.run([self.ops['depth_feature']], feed_dict = feed_dict)
        return depth_feature

    def softmax(self, x):
        ''' Numpy function for softmax'''
        shape = x.shape
        probs = np.exp(x - np.max(x, axis=len(shape)-1, keepdims=True))
        probs /= np.sum(probs, axis=len(shape)-1, keepdims=True)
        return probs

def create_depth_model(model, config_path):
    #Note that folder path must be the folder containing the config.yaml file if omni_camera is True
    if model == 'FPointNet':
        return FPointNet(config_path)
    elif model == 'PointNet':
        return PointNet(config_path)

================================================
FILE: paper_experiments/models/pointnet_model.py
================================================
import os, pdb
import tensorflow as tf
tf.logging.set_verbosity(tf.logging.ERROR)
import configparser
from utils.pointnet_transform_nets import input_transform_net, feature_transform_net
import utils.pointnet_tf_util as pointnet_tf_util


class PointNet():
    def __init__(self, config_path):
        parser = configparser.SafeConfigParser()
        parser.read(config_path)
        num_points = parser.getint('general', 'num_point')
        depth_model_path = parser.get('general', 'depth_model_path')

        with tf.device('/gpu:'+str(0)):
            self.pointclouds_pl, _ = self.placeholder_inputs(1, num_points)
            self.is_training_pl = tf.placeholder(tf.bool, shape=())

            # simple model
            feature = self.get_model(self.pointclouds_pl, self.is_training_pl)
            self.feature = feature
            # Add ops to save and restore all the variables.
        
        self.saver = tf.train.Saver()
        #Create session
        config = tf.ConfigProto()
        config.gpu_options.allow_growth = True
        config.allow_soft_placement = True
        config.log_device_placement = False
        self.sess = tf.Session(config=config)
        #Initialize variables
        self.sess.run(tf.global_variables_initializer())
        #Restore model weights
        self.saver.restore(self.sess, depth_model_path)

    def __call__(self, input_point_cloud):
        feed_dict = {self.pointclouds_pl: input_point_cloud,
                     self.is_training_pl: False}
        features = self.sess.run(self.feature,feed_dict=feed_dict)
        return features

    def placeholder_inputs(self, batch_size, num_point):
        pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, None, 3))
        labels_pl = tf.placeholder(tf.int32, shape=(batch_size))
        return pointclouds_pl, labels_pl


    def get_model(self, point_cloud, is_training, bn_decay=None):
        """ Classification PointNet, input is BxNx3, output Bx40 """
        batch_size = point_cloud.get_shape()[0].value
        end_points = {}

        with tf.variable_scope('transform_net1', reuse=tf.AUTO_REUSE) as sc:
            transform = input_transform_net(point_cloud, is_training, bn_decay, K=3)
        point_cloud_transformed = tf.matmul(point_cloud, transform)
        input_image = tf.expand_dims(point_cloud_transformed, -1)

        net = pointnet_tf_util.conv2d(input_image, 64, [1,3],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv1', bn_decay=bn_decay)
        net = pointnet_tf_util.conv2d(net, 64, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv2', bn_decay=bn_decay)

        with tf.variable_scope('transform_net2', reuse=tf.AUTO_REUSE) as sc:
            transform = feature_transform_net(net, is_training, bn_decay, K=64)
        end_points['transform'] = transform
        net_transformed = tf.matmul(tf.squeeze(net, axis=[2]), transform)
        net_transformed = tf.expand_dims(net_transformed, [2])

        net = pointnet_tf_util.conv2d(net_transformed, 64, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv3', bn_decay=bn_decay)
        net = pointnet_tf_util.conv2d(net, 128, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv4', bn_decay=bn_decay)
        net = pointnet_tf_util.conv2d(net, 1024, [1,1],
                             padding='VALID', stride=[1,1],
                             bn=True, is_training=is_training,
                             scope='conv5', bn_decay=bn_decay)

        # Symmetric function: max pooling
        net = tf.reduce_max(net, axis = 1)

        net = tf.reshape(net, [batch_size, -1])
        feature = net

        return feature


    def get_loss(self, pred, label, end_points, reg_weight=0.001):
        """ pred: B*NUM_CLASSES,
            label: B, """
        loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=pred, labels=label)
        classify_loss = tf.reduce_mean(loss)
        tf.summary.scalar('classify loss', classify_loss)

        # Enforce the transformation as orthogonal matrix
        transform = end_points['transform'] # BxKxK
        K = transform.get_shape()[1].value
        mat_diff = tf.matmul(transform, tf.transpose(transform, perm=[0,2,1]))
        mat_diff = mat_diff - tf.constant(np.eye(K), dtype=tf.float32)
        mat_diff_loss = tf.nn.l2_loss(mat_diff) 
        tf.summary.scalar('mat loss', mat_diff_loss)

        return classify_loss + mat_diff_loss * reg_weight
    

================================================
FILE: paper_experiments/models/resnet_reid_models.py
================================================
import torch
import torch.nn as nn
from torch.autograd import Variable
import torchvision.models as models
from torchvision import transforms
import torch.nn.functional as F

class FeatureResNet(nn.Module):
    def __init__(self,n_layers=50,pretrained=True):
        super(FeatureResNet,self).__init__()
        if n_layers == 50:
            old_model= models.resnet50(pretrained=pretrained)
        elif n_layers == 34:
            old_model= models.resnet34(pretrained=pretrained)
        elif n_layers == 18:
            old_model= models.resnet18(pretrained=pretrained)
        else:
            raise NotImplementedError('resnet%s is not found'%(n_layers))

        for name,modules in old_model._modules.items():
            if name.find('fc') == -1:
                self.add_module(name,modules)
        self.output_dim = old_model.fc.in_features
        self.pretrained = pretrained
    def forward(self,x):
        for name,module in self._modules.items():
            x = nn.parallel.data_parallel(module, x)
        return x.view(x.size(0), -1)

class ResNet(nn.Module):
    def __init__(self,n_id,n_layers=50,pretrained=True):
        super(ResNet,self).__init__()
        if n_layers == 50:
            old_model= models.resnet50(pretrained=pretrained)
        elif n_layers == 34:
            old_model= models.resnet34(pretrained=pretrained)
        elif n_layers == 18:
            old_model= models.resnet18(pretrained=pretrained)
        else:
            raise NotImplementedError('resnet%s is not found'%(n_layers))

        for name,modules in old_model._modules.items():
            self.add_module(name,modules)
        self.fc = nn.Linear(self.fc.in_features,n_id)
        #########
        self.pretrained = pretrained
    def forward(self,x):
        for name,module in self._modules.items():
            if name != 'fc':
                x = module(x)
        out = self.fc(x.view(x.size(0),-1))
        return out, x.view(x.size(0), -1)

class NLayersFC(nn.Module):
    def __init__(self, in_dim, out_dim, hidden_dim=1, n_layers=0):
        super(NLayersFC, self).__init__()
        if n_layers == 0:
            model = [nn.Linear(in_dim, out_dim)]
        else:
            model = []
            model += [nn.Linear(in_dim, hidden_dim),
                      nn.ReLU(True)]
            for i in range(n_layers-1):
                model += [nn.Linear(hidden_dim, hidden_dim),
                          nn.ReLU(True)]
            model += [nn.Linear(hidden_dim, out_dim)]
        self.model = nn.Sequential(*model)

    def forward(self, x):
        return self.model(x)

class ICT_ResNet(nn.Module):
    def __init__(self,n_id,n_color,n_type,n_layers=50,pretrained=True):
        super(ICT_ResNet,self).__init__()
        if n_layers == 50:
            old_model= models.resnet50(pretrained=pretrained)
        elif n_layers == 34:
            old_model= models.resnet34(pretrained=pretrained)
        elif n_layers == 18:
            old_model= models.resnet18(pretrained=pretrained)
        else:
            raise NotImplementedError('resnet%s is not found'%(n_layers))

        for name,modules in old_model._modules.items():
            self.add_module(name,modules)
        self.fc = nn.Linear(self.fc.in_features,n_id)
        self.fc_c = nn.Linear(self.fc.in_features,n_color)
        self.fc_t = nn.Linear(self.fc.in_features,n_type)
        #########
        self.pretrained = pretrained
    def forward(self,x):
        for name,module in self._modules.items():
            if name.find('fc')==-1:
                x = module(x)
        x = x.view(x.size(0),-1)
        x_i = self.fc(x)
        x_c = self.fc_c(x)
        x_t = self.fc_t(x)
        return x_i,x_c,x_t

class TripletNet(nn.Module):
    def __init__(self, net):
        super(TripletNet, self).__init__()
        self.net = net

    def forward(self, x, y, z):
        pred_x, feat_x = self.net(x)
        pred_y, feat_y = self.net(y)
        pred_z, feat_z = self.net(z)
        dist_pos = F.pairwise_distance(feat_x, feat_y, 2)
        dist_neg = F.pairwise_distance(feat_x, feat_z, 2)
        return dist_pos, dist_neg, pred_x, pred_y, pred_z

if __name__ == '__main__':
    netM = ICT_ResNet(n_id=1000,n_color=7,n_type=7,n_layers=18,pretrained=True).cuda()

    print(netM)
    output = netM(Variable(torch.ones(1,3,224,224).cuda()/2.))
    print(output[0].size())
    print(output[1].size())
    print(output[2].size())


================================================
FILE: paper_experiments/models/yolo_models.py
================================================
from __future__ import division

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import numpy as np

from PIL import Image

from utils.yolo_utils.parse_config import *
from utils.yolo_utils.utils import build_targets
from collections import defaultdict

import matplotlib.pyplot as plt
import matplotlib.patches as patches


def create_modules(module_defs):
    """
    Constructs module list of layer blocks from module configuration in module_defs
    """
    hyperparams = module_defs.pop(0)
    output_filters = [int(hyperparams["channels"])]
    module_list = nn.ModuleList()
    for i, module_def in enumerate(module_defs):
        modules = nn.Sequential()

        if module_def["type"] == "convolutional":
            bn = int(module_def["batch_normalize"])
            filters = int(module_def["filters"])
            kernel_size = int(module_def["size"])
            pad = (kernel_size - 1) // 2 if int(module_def["pad"]) else 0
            modules.add_module(
                "conv_%d" % i,
                nn.Conv2d(
                    in_channels=output_filters[-1],
                    out_channels=filters,
                    kernel_size=kernel_size,
                    stride=int(module_def["stride"]),
                    padding=pad,
                    bias=not bn,
                ),
            )
            if bn:
                modules.add_module("batch_norm_%d" % i, nn.BatchNorm2d(filters))
            if module_def["activation"] == "leaky":
                modules.add_module("leaky_%d" % i, nn.LeakyReLU(0.1))

        elif module_def["type"] == "maxpool":
            kernel_size = int(module_def["size"])
            stride = int(module_def["stride"])
            if kernel_size == 2 and stride == 1:
                padding = nn.ZeroPad2d((0, 1, 0, 1))
                modules.add_module("_debug_padding_%d" % i, padding)
            maxpool = nn.MaxPool2d(
                kernel_size=int(module_def["size"]),
                stride=int(module_def["stride"]),
                padding=int((kernel_size - 1) // 2),
            )
            modules.add_module("maxpool_%d" % i, maxpool)

        elif module_def["type"] == "upsample":
            upsample = Interpolate(scale_factor=int(module_def["stride"]), mode="nearest")
            modules.add_module("upsample_%d" % i, upsample)

        elif module_def["type"] == "route":
            layers = [int(x) for x in module_def["layers"].split(",")]
            filters = sum([output_filters[layer_i] for layer_i in layers])
            modules.add_module("route_%d" % i, EmptyLayer())

        elif module_def["type"] == "shortcut":
            filters = output_filters[int(module_def["from"])]
            modules.add_module("shortcut_%d" % i, EmptyLayer())

        elif module_def["type"] == "yolo":
            anchor_idxs = [int(x) for x in module_def["mask"].split(",")]
            # Extract anchors
            anchors = [int(x) for x in module_def["anchors"].split(",")]
            anchors = [(anchors[i], anchors[i + 1]) for i in range(0, len(anchors), 2)]
            anchors = [anchors[i] for i in anchor_idxs]
            num_classes = int(module_def["classes"])
            img_height = int(hyperparams["height"])
            # Define detection layer
            yolo_layer = YOLOLayer(anchors, num_classes, img_height)
            modules.add_module("yolo_%d" % i, yolo_layer)
        # Register module list and number of output filters
        module_list.append(modules)
        output_filters.append(filters)

    return hyperparams, module_list


class EmptyLayer(nn.Module):
    """Placeholder for 'route' and 'shortcut' layers"""

    def __init__(self):
        super(EmptyLayer, self).__init__()

class Interpolate(nn.Module):
    def __init__(self, scale_factor, mode):
        super(Interpolate, self).__init__()
        self.interp = nn.functional.interpolate
        self.scale_factor = scale_factor
        self.mode = mode
        
    def forward(self, x):
        x = self.interp(x, scale_factor=self.scale_factor, mode=self.mode)
        return x

class YOLOLayer(nn.Module):
    """Detection layer"""

    def __init__(self, anchors, num_classes, img_dim):
        super(YOLOLayer, self).__init__()
        self.anchors = anchors
        self.num_anchors = len(anchors)
        self.num_classes = num_classes
        self.bbox_attrs = 5 + num_classes
        self.image_dim = img_dim
        self.ignore_thres = 0.5
        self.lambda_coord = 1

        self.mse_loss = nn.MSELoss(reduction = 'elementwise_mean')  # Coordinate loss
        self.bce_loss = nn.BCELoss(reduction = 'elementwise_mean')  # Confidence loss
        self.ce_loss = nn.CrossEntropyLoss()  # Class loss

    def forward(self, x, targets=None):
        nA = self.num_anchors
        nB = x.size(0)
        nG = x.size(2)
        stride = self.image_dim / nG

        # Tensors for cuda support
        FloatTensor = torch.cuda.FloatTensor if x.is_cuda else torch.FloatTensor
        LongTensor = torch.cuda.LongTensor if x.is_cuda else torch.LongTensor
        ByteTensor = torch.cuda.ByteTensor if x.is_cuda else torch.ByteTensor

        prediction = x.view(nB, nA, self.bbox_attrs, nG, nG).permute(0, 1, 3, 4, 2).contiguous()

        # Get outputs
        x = torch.sigmoid(prediction[..., 0])  # Center x
        y = torch.sigmoid(prediction[..., 1])  # Center y
        w = prediction[..., 2]  # Width
        h = prediction[..., 3]  # Height
        pred_conf = torch.sigmoid(prediction[..., 4])  # Conf
        pred_cls = torch.sigmoid(prediction[..., 5:])  # Cls pred.

        # Calculate offsets for each grid
        grid_x = torch.arange(nG).repeat(nG, 1).view([1, 1, nG, nG]).type(FloatTensor)
        grid_y = torch.arange(nG).repeat(nG, 1).t().view([1, 1, nG, nG]).type(FloatTensor)
        scaled_anchors = FloatTensor([(a_w / stride, a_h / stride) for a_w, a_h in self.anchors])
        anchor_w = scaled_anchors[:, 0:1].view((1, nA, 1, 1))
        anchor_h = scaled_anchors[:, 1:2].view((1, nA, 1, 1))

        # Add offset and scale with anchors
        pred_boxes = FloatTensor(prediction[..., :4].shape)
        pred_boxes[..., 0] = x.data + grid_x
        pred_boxes[..., 1] = y.data + grid_y
        pred_boxes[..., 2] = torch.exp(w.data) * anchor_w
        pred_boxes[..., 3] = torch.exp(h.data) * anchor_h

        # Training
        if targets is not None:

            if x.is_cuda:
                self.mse_loss = self.mse_loss.cuda()
                self.bce_loss = self.bce_loss.cuda()
                self.ce_loss = self.ce_loss.cuda()

            nGT, nCorrect, mask, conf_mask, tx, ty, tw, th, tconf, tcls = build_targets(
                pred_boxes=pred_boxes.cpu().data,
                pred_conf=pred_conf.cpu().data,
                pred_cls=pred_cls.cpu().data,
                target=targets.cpu().data,
                anchors=scaled_anchors.cpu().data,
                num_anchors=nA,
                num_classes=self.num_classes,
                grid_size=nG,
                ignore_thres=self.ignore_thres,
                img_dim=self.image_dim,
            )

            nProposals = int((pred_conf > 0.5).sum().item())
            recall = float(nCorrect / nGT) if nGT else 1
            precision = float(nCorrect / nProposals)

            # Handle masks
            mask = Variable(mask.type(ByteTensor))
            conf_mask = Variable(conf_mask.type(ByteTensor))

            # Handle target variables
            tx = Variable(tx.type(FloatTensor), requires_grad=False)
            ty = Variable(ty.type(FloatTensor), requires_grad=False)
            tw = Variable(tw.type(FloatTensor), requires_grad=False)
            th = Variable(th.type(FloatTensor), requires_grad=False)
            tconf = Variable(tconf.type(FloatTensor), requires_grad=False)
            tcls = Variable(tcls.type(LongTensor), requires_grad=False)

            # Get conf mask where gt and where there is no gt
            conf_mask_true = mask
            conf_mask_false = conf_mask - mask

            # Mask outputs to ignore non-existing objects
            loss_x = self.mse_loss(x[mask], tx[mask])
            loss_y = self.mse_loss(y[mask], ty[mask])
            loss_w = self.mse_loss(w[mask], tw[mask])
            loss_h = self.mse_loss(h[mask], th[mask])
            loss_conf = self.bce_loss(pred_conf[conf_mask_false], tconf[conf_mask_false]) + self.bce_loss(
                pred_conf[conf_mask_true], tconf[conf_mask_true]
            )
            loss_cls = (1 / nB) * self.ce_loss(pred_cls[mask], torch.argmax(tcls[mask], 1))
            loss = loss_x + loss_y + loss_w + loss_h + loss_conf + loss_cls

            return (
                loss,
                loss_x.item(),
                loss_y.item(),
                loss_w.item(),
                loss_h.item(),
                loss_conf.item(),
                loss_cls.item(),
                recall,
                precision,
            )

        else:
            # If not in training phase return predictions
            output = torch.cat(
                (
                    pred_boxes.view(nB, -1, 4) * stride,
                    pred_conf.view(nB, -1, 1),
                    pred_cls.view(nB, -1, self.num_classes),
                ),
                -1,
            )
            return output


class Darknet(nn.Module):
    """YOLOv3 object detection model"""

    def __init__(self, config_path):
        super(Darknet, self).__init__()
        self.module_defs = parse_model_config(config_path)
        self.hyperparams, self.module_list = create_modules(self.module_defs)
        self.seen = 0
        self.header_info = np.array([0, 0, 0, self.seen, 0])
        self.loss_names = ["x", "y", "w", "h", "conf", "cls", "recall", "precision"]
        self.load_weights(self.module_defs[-1]['path'])

    def forward(self, x, targets=None):
        is_training = targets is not None
        output = []
        self.losses = defaultdict(float)
        layer_outputs = []
        for i, (module_def, module) in enumerate(zip(self.module_defs, self.module_list)):
            if module_def["type"] in ["convolutional", "upsample", "maxpool"]:
                x = module(x)
            elif module_def["type"] == "route":
                layer_i = [int(x) for x in module_def["layers"].split(",")]
                x = torch.cat([layer_outputs[i] for i in layer_i], 1)
            elif module_def["type"] == "shortcut":
                layer_i = int(module_def["from"])
                x = layer_outputs[-1] + layer_outputs[layer_i]
            elif module_def["type"] == "yolo":
                # Train phase: get loss
                if is_training:
                    x, *losses = module[0](x, targets)
                    for name, loss in zip(self.loss_names, losses):
                        self.losses[name] += loss
                # Test phase: Get detections
                else:
                    x = module(x)
                output.append(x)
            layer_outputs.append(x)

        self.losses["recall"] /= 3
        self.losses["precision"] /= 3
        return sum(output) if is_training else torch.cat(output, 1)

    def load_weights(self, weights_path):
        """Parses and loads the weights stored in 'weights_path'"""

        # Open the weights file
        fp = open(weights_path, "rb")
        header = np.fromfile(fp, dtype=np.int32, count=5)  # First five are header values

        # Needed to write header when saving weights
        self.header_info = header

        self.seen = header[3]
        weights = np.fromfile(fp, dtype=np.float32)  # The rest are weights
        fp.close()

        ptr = 0
        for i, (module_def, module) in enumerate(zip(self.module_defs, self.module_list)):
            if module_def["type"] == "convolutional":
                conv_layer = module[0]
                if module_def["batch_normalize"]:
                    # Load BN bias, weights, running mean and running variance
                    bn_layer = module[1]
                    num_b = bn_layer.bias.numel()  # Number of biases
                    # Bias
                    bn_b = torch.from_numpy(weights[ptr : ptr + num_b]).view_as(bn_layer.bias)
                    bn_layer.bias.data.copy_(bn_b)
                    ptr += num_b
                    # Weight
                    bn_w = torch.from_numpy(weights[ptr : ptr + num_b]).view_as(bn_layer.weight)
                    bn_layer.weight.data.copy_(bn_w)
                    ptr += num_b
                    # Running Mean
                    bn_rm = torch.from_numpy(weights[ptr : ptr + num_b]).view_as(bn_layer.running_mean)
                    bn_layer.running_mean.data.copy_(bn_rm)
                    ptr += num_b
                    # Running Var
                    bn_rv = torch.from_numpy(weights[ptr : ptr + num_b]).view_as(bn_layer.running_var)
                    bn_layer.running_var.data.copy_(bn_rv)
                    ptr += num_b
                else:
                    # Load conv. bias
                    num_b = conv_layer.bias.numel()
                    conv_b = torch.from_numpy(weights[ptr : ptr + num_b]).view_as(conv_layer.bias)
                    conv_layer.bias.data.copy_(conv_b)
                    ptr += num_b
                # Load conv. weights
                num_w = conv_layer.weight.numel()
                conv_w = torch.from_numpy(weights[ptr : ptr + num_w]).view_as(conv_layer.weight)
                conv_layer.weight.data.copy_(conv_w)
                ptr += num_w

    """
        @:param path    - path of the new weights file
        @:param cutoff  - save layers between 0 and cutoff (cutoff = -1 -> all are saved)
    """

    def save_weights(self, path, cutoff=-1):

        fp = open(path, "wb")
        self.header_info[3] = self.seen
        self.header_info.tofile(fp)

        # Iterate through layers
        for i, (module_def, module) in enumerate(zip(self.module_defs[:cutoff], self.module_list[:cutoff])):
            if module_def["type"] == "convolutional":
                conv_layer = module[0]
                # If batch norm, load bn first
                if module_def["batch_normalize"]:
                    bn_layer = module[1]
                    bn_layer.bias.data.cpu().numpy().tofile(fp)
                    bn_layer.weight.data.cpu().numpy().tofile(fp)
                    bn_layer.running_mean.data.cpu().numpy().tofile(fp)
                    bn_layer.running_var.data.cpu().numpy().tofile(fp)
                # Load conv bias
                else:
                    conv_layer.bias.data.cpu().numpy().tofile(fp)
                # Load conv weights
                conv_layer.weight.data.cpu().numpy().tofile(fp)

        fp.close()


================================================
FILE: paper_experiments/requirements.txt
================================================
absl-py==0.7.0
astor==0.7.1
backcall==0.1.0
bleach==3.3.0
catkin-pkg==0.4.12
certifi==2018.11.29
chardet==3.0.4
cloudpickle==0.7.0
cupy==6.0.0
cycler==0.10.0
Cython==0.29.7
dask==2021.10.0
decorator==4.3.2
defusedxml==0.5.0
docutils==0.14
entrypoints==0.3
fastrlock==0.4
ffmpeg==1.4
gast==0.2.2
grpcio==1.18.0
gurobipy==8.1.0
html5lib==0.9999999
idna==2.8
imageio==2.5.0
imageio-ffmpeg==0.3.0
ipydatawidgets==4.0.0
ipykernel==5.1.0
ipympl==0.2.1
ipython==7.16.3
ipython-genutils==0.2.0
ipyvolume==0.5.1
ipywebrtc==0.4.3
ipywidgets==7.4.2
jedi==0.13.2
Jinja2==2.11.3
jsonschema==2.6.0
jupyter-client==5.2.4
jupyter-core==4.4.0
jupyterlab==1.2.21
jupyterlab-server==0.2.0
kiwisolver==1.0.1
lap==0.4.0
lapjv==1.3.1
line-profiler==2.1.1
llvmlite==0.28.0
Markdown==3.0.1
MarkupSafe==1.1.0
matplotlib==3.0.2
mistune==0.8.4
nbconvert==5.4.1
nbformat==4.4.0
networkx==2.2
notebook==6.4.1
numba==0.43.1
numpy==1.21.0
open3d-python==0.7.0.0
opencv-python==4.2.0.32
pandas==0.24.1
pandocfilters==1.4.2
parso==0.3.3
pexpect==4.6.0
pickleshare==0.7.5
Pillow==9.0.0
pptk==0.1.0
prometheus-client==0.5.0
prompt-toolkit==2.0.8
protobuf==3.6.1
ptyprocess==0.6.0
pycocotools==2.0.0
Pygments==2.7.4
pyparsing==2.3.1
pypcd==0.1.1
python-dateutil==2.8.0
python-lzf==0.2.4
pythreejs==2.0.2
pytz==2018.9
PyWavelets==1.0.1
PyYAML==5.4
pyzmq==17.1.2
requests==2.21.0
rospkg==1.1.9
scikit-image==0.14.2
scikit-learn==0.20.2
scipy==1.2.0
seaborn==0.9.0
Send2Trash==1.5.0
six==1.12.0
sklearn==0.0
tensorboard==1.8.0
tensorboardX==1.6
tensorflow-gpu==2.5.2
termcolor==1.1.0
terminado==0.8.1
testpath==0.4.2
toolz==0.9.0
torch==1.0.1
torchvision==0.2.1
tornado==5.1.1
tqdm==4.30.0
traitlets==4.3.2
traittypes==0.2.1
urllib3==1.26.5
wcwidth==0.1.7
Werkzeug==0.15.3
widgetsnbextension==3.4.2


================================================
FILE: paper_experiments/track.py
================================================
import open3d as o3d
import torch
import argparse
import os, pdb, sys, copy, pickle
import time
import random
import numpy as np
import tensorflow as tf
from torch.utils.data import DataLoader
from tqdm import tqdm

from models.aligned_reid_model import Model as aligned_reid_model
from utils.yolo_utils.utils import non_max_suppression, load_classes
from models.combination_model import CombiNet, CombiLSTM
from utils.dataset import SequenceDataset, STIPDataset, collate_fn
from models.deep_sort_model import ImageEncoder as deep_sort_model
from utils.tracker import Tracker
from utils.tracker_3d import Tracker_3d
from utils.deep_sort_utils import non_max_suppression as deepsort_nms
from utils.visualise import draw_track
from utils.read_detections import read_ground_truth_2d_detections, read_ground_truth_3d_detections
from utils.tracking_utils import create_detector, convert_detections, combine_features
from utils.tracking_utils import non_max_suppression_3D, non_max_suppression_3D_prime
from utils.aligned_reid_utils import generate_features, generate_features_batched, get_image_patches, create_appearance_model
from utils.featurepointnet_model_util import generate_detections_3d, convert_depth_features
from models.featurepointnet_model import create_depth_model

def parse_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument('--sequence_folder', type=str, default='data/KITTI/sequences/0001', help='path to image sequence')
    parser.add_argument('--output_folder', type=str, default='results', help='output folder')
    parser.add_argument('--aligned_reid_ckpt', type=str, default='weights/aligned_reid_market_weights.ckpt', help='path to model config file')
    parser.add_argument('--resnet_reid_ckpt', type=str, default='weights/resnet_reid.ckpt', help='path to model config file')
    parser.add_argument('--depth_model', type=str, default='FPointNet', help='type of depth model to use')
    parser.add_argument('--depth_config_path', type=str, default='config/featurepointnet.cfg', help='path to model config file')
    parser.add_argument('--appearance_model', type=str, default='resnet_reid', help='type of appearance model to use aligned_reid or deepsort or resnet_reid')
    parser.add_argument('--conf_thres', type=float, default=0.8, help='object confidence threshold')
    parser.add_argument('--depth_weight', type=float, default=1, help='weight of depth feature while concatenating')
    parser.add_argument('--nms_thresh', type=float, default=0.56, help='iou thresshold for non-maximum suppression')
    parser.add_argument('--n_cpu', type=int, default=4, help='number of cpu threads to use during batch generation')
    parser.add_argument('--use_cuda', type=bool, default=True, help='whether to use cuda if available')
    parser.add_argument('-p', '--point_cloud', action='store_false', help='Use to disable pointcloud')
    parser.add_argument('-o', '--optical_flow_initiation', action='store_false', help='Use to enable optical flow based velocity initiation')
    parser.add_argument('-q', '--perfect', action='store_true', help='whether to use perfect assignments')
    parser.add_argument('-g', '--ground_truth', action='store_true', help='whether to use ground truth detections')
    parser.add_argument('-r', '--reference', action='store_false', help='whether to use reference detections')
    parser.add_argument('-t', '--track_3d', action='store_true', help='whether to do 3d tracking')
    parser.add_argument('--ref_det', type = str, default = 'new_rrc_subcnn_car', help='lsvm, subcnn, regionlets, maskrcnn')
    parser.add_argument("--nn_budget", type=int, default=100, help="Maximum size of the appearance descriptors gallery. If None, no budget is enforced.")
    parser.add_argument("--dummy_node_cost_app", type=float, default=0.99, help="Dummy node appearance cost for JPDA (or maximum distnce when using deepsort)")
    parser.add_argument("--dummy_node_cost_iou", type=float, default=0.97, help="Dummy node iou cost for JPDA (or maximum distnce when using deepsort)")
    parser.add_argument("-c", "--combine_features", action = 'store_false', help="Whether to use trained MLP to combine features")
    parser.add_argument("-f", "--fpointnet", action = 'store_false', help="Whether to use F-PointNet for 3d detection")
    parser.add_argument("--combo_model", default = 'weights/resnet_reid_fpointnet_combo_car/mlp__1570759353.0113978/best_checkpoint.tar"', help="Trained MLP checkpoint to combine features")
    parser.add_argument("-j", "--JPDA", action = 'store_false', help="Whether to use JPDA for soft assignments")
    parser.add_argument("-l", "--LSTM", action = 'store_true', help="Whether to use LSTM for feature combination and update")
    parser.add_argument("--lstm_model", default = 'weights/aligned_reid_fpointnet_combo/lstm/best_checkpoint.tar', help="Trained LSTM checkpoint to combine features")
    parser.add_argument("-m","--m_best_sol", type=int, default=10, help="Number of solutions for JPDA")
    parser.add_argument("--log_data", action='store_true', help="Turn on full data logging")
    parser.add_argument("--max_age", type=int, default=2, help="Number of misses before termination")
    parser.add_argument("--n_init", type=int, default=2, help="Consecutive frames for tentative->confirmed")
    parser.add_argument("--assn_thresh", type=float, default=0.65, help="min prob for match")
    parser.add_argument("--matching_strategy", type=str, default="hungarian", help="matching strategy for JPDA (max_and_threshold, strict_max_pair, or hungarian)")
    parser.add_argument("--kf_appearance_feature", type=bool, default=False, help="Whether to use kf state for apperance features")
    parser.add_argument('-i', "--use_imm", action = 'store_true', help='Whether to use IMM')
    parser.add_argument('-v', "--verbose", action = 'store_true', help='Verbose')
    parser.add_argument('--kf_process', type=float, default=5.2, help='kf 2d process noise factor')
    parser.add_argument('--kf_2d_meas', type=float, default=3.2, help='kf 2d measurement noise factor')
    parser.add_argument('--kf_3d_meas', type=float, default=0.25, help='kf 3d measurement noise factor')
    parser.add_argument('--pos_weight_3d', type=float, default=1, help='Weight on position covariance process noise in KF')
    parser.add_argument('--pos_weight', type=float, default=0.006, help='Weight on position covariance process noise in KF')
    parser.add_argument('--vel_weight', type=float, default=0.008, help='Weight on velocity covariance process noise in KF')
    parser.add_argument('--theta_weight', type=float, default=0.02, help='Weight on velocity covariance process noise in KF')
    parser.add_argument('--gate_limit', type=float, default=600, help='Maximum covariance value of the gate')
    parser.add_argument('--initial_uncertainty', type=float, default=1, help='Uncertainty scaling for initial covariance of track')
    parser.add_argument('--uncertainty_limit', type=float, default=1.5, help='Uncertainty limit at which to terminate tracks')
    parser.add_argument("--gate_full_state", action='store_true', help="Whether to gate on full kalman state, default is only position")
    parser.add_argument("--near_online", action = 'store_true', help="Whether to do near online tracking")
    parser.add_argument("--omni", action = 'store_true', help="Omni directional camera (JRDB)")
    opt = parser.parse_args()
    opt.sequence_folder = opt.sequence_folder.rstrip(os.sep)
    opt.using_cuda = torch.cuda.is_available() and opt.use_cuda
    if not opt.point_cloud and opt.track_3d:
        raise("Must provide point cloud if doing 3D tracking!")
    if opt.verbose:
        print(opt)
    if not os.path.exists(opt.output_folder):
        os.makedirs(opt.output_folder)
    return opt

# @profile
def main(opt):

    if opt.verbose:
        print("------------------------")
        print("RUNNING SET UP")
        print("------------------------")
    tf.logging.set_verbosity(40)
    random.seed(0)
    Tensor = torch.cuda.FloatTensor if opt.using_cuda else torch.FloatTensor
    os.makedirs(opt.output_folder, exist_ok=True)
    if opt.LSTM:
        opt.max_cosine_distance = 1
        lstm = CombiLSTM()
        checkpoint = torch.load(opt.lstm_model)
        lstm.load_state_dict(checkpoint['state_dict'])
        if opt.using_cuda:
            lstm.cuda()
        lstm.eval()
    else:
        lstm = None
    if opt.combine_features:
        combination_model = CombiNet()
        checkpoint = torch.load(opt.combo_model)
        combination_model.load_state_dict(checkpoint['state_dict'])
        if opt.using_cuda:
            combination_model.cuda()
        combination_model.eval()
    else:
        combination_model = None
    
    dataset = SequenceDataset(opt.sequence_folder, point_cloud=opt.point_cloud, omni=opt.omni)
    dataloader = DataLoader(dataset, batch_size=1, shuffle=False, num_workers=opt.n_cpu, collate_fn = collate_fn)
    appearance_model = create_appearance_model(opt.appearance_model, opt.aligned_reid_ckpt, opt.resnet_reid_ckpt, opt.using_cuda)
    if opt.point_cloud:
        depth_model = create_depth_model(opt.depth_model, opt.depth_config_path)
    if opt.track_3d:
        tracker = Tracker_3d(appearance_model=appearance_model, cuda=opt.using_cuda, JPDA = opt.JPDA, m_best_sol=opt.m_best_sol,
                        max_age = opt.max_age, n_init=opt.n_init, assn_thresh=opt.assn_thresh,
                        matching_strategy=opt.matching_strategy,
                        gate_full_state=opt.gate_full_state,
                        kf_vel_params=(opt.pos_weight_3d, opt.pos_weight, opt.vel_weight, opt.theta_weight,
                                       opt.kf_process, opt.kf_2d_meas, opt.kf_3d_meas, opt.initial_uncertainty),
                        calib=dataset.calib,
                        dummy_node_cost_iou=opt.dummy_node_cost_iou,
                        dummy_node_cost_app=opt.dummy_node_cost_app,
                        nn_budget=opt.nn_budget,
                        use_imm=opt.use_imm,
                        uncertainty_limit=opt.uncertainty_limit,
                        gate_limit=opt.gate_limit,
                        omni=opt.omni)
    else:
        tracker = Tracker(appearance_model=appearance_model, cuda=opt.using_cuda, JPDA = opt.JPDA, m_best_sol=opt.m_best_sol,
                        max_age = opt.max_age, n_init=opt.n_init, assn_thresh=opt.assn_thresh,
                        matching_strategy=opt.matching_strategy,
                        kf_appearance_feature=opt.kf_appearance_feature,
                        gate_full_state=opt.gate_full_state,
                        kf_vel_params=(opt.pos_weight, opt.vel_weight, opt.kf_process, opt.kf_2d_meas, opt.initial_uncertainty),
                        kf_walk_params=(opt.pos_weight, opt.vel_weight, opt.kf_process, opt.kf_2d_meas, opt.initial_uncertainty),
                        calib=dataset.calib,
                        dummy_node_cost_iou=opt.dummy_node_cost_iou,
                        dummy_node_cost_app=opt.dummy_node_cost_app,
                        nn_budget=opt.nn_budget,
                        use_imm=opt.use_imm,
                        uncertainty_limit=opt.uncertainty_limit,
                        optical_flow=opt.optical_flow_initiation,
                        gate_limit=opt.gate_limit)

    results = []
    results_3d = []
    n_frames = len(dataloader)
    if opt.log_data:
        full_log = [{'tracks':[], 'detections':[], 'detections_3d':[]} for _ in range(n_frames)]
    det_matrix = None
    seq_name = os.path.split(opt.sequence_folder)[-1]

    frame_times = []
    if opt.verbose:
        print("------------------------")
        print("BEGINNING TRACKING OF SEQUENCE %s"%seq_name)
        print("------------------------")
    for frame_idx, img_path, input_img, point_cloud in tqdm(dataloader, ncols = 100, disable=not opt.verbose):
        # if frame_idx > 120:
        #     break
        # elif frame_idx < 98:
        #     continue

        if opt.log_data:
            full_log[frame_idx]['img_path'] = copy.copy(img_path)
        input_img = input_img.type(Tensor)
        if opt.reference:
            detections, object_ids, det_matrix = read_ground_truth_2d_detections(os.path.join(opt.sequence_folder,'det',opt.ref_det+'.txt'), frame_idx, det_matrix, threshold = 0, nms_threshold = opt.nms_thresh)
        elif opt.ground_truth:
            detections, object_ids, det_matrix = read_ground_truth_2d_detections(os.path.join(opt.sequence_folder,'gt','gt.txt'), frame_idx, det_matrix, nms_threshold = opt.nms_thresh)
        else:
            raise("Must specify ground truth or detections")

        # --- START OF TRACKING ---
        # start_time = time.time()
        if detections is None or len(detections)==0:
            tracker.predict()
            if opt.log_data:
                full_log[frame_idx]['predicted_tracks'] = copy.deepcopy(tracker.tracks)
            start_time = time.time()
            tracker.update(input_img, [])
        else:
            total_dets = len(detections)
            patches = get_image_patches(input_img, detections)
            appearance_features = generate_features_batched(appearance_model, patches, opt, object_ids)
            if opt.point_cloud:
                if not opt.omni:
                    point_cloud = point_cloud[point_cloud[:,2]>=0]
                if opt.fpointnet:
                    boxes_3d, valid_3d, _, scores_3d, depth_features = generate_detections_3d(depth_model, 
                                                                        detections, np.asarray(point_cloud), 
                                                                        dataset.calib, input_img.shape,
                                                                        peds='ped' in opt.ref_det or opt.omni)
                    depth_features = convert_depth_features(depth_features, valid_3d)
                else:
                    boxes_3d, valid_3d = read_ground_truth_3d_detections(os.path.join(opt.sequence_folder,'gt','3d_detections.txt'), frame_idx)        
                features, appearance_features = combine_features(appearance_features, depth_features, valid_3d, combination_model, depth_weight = opt.depth_weight)
                # boxes_3d = boxes_3d[valid_3d != -1] # Old and buggy way of handling missing box
                # detections = detections[valid_3d != -1]
                if np.any(valid_3d == -1):
                    compare_2d = True
                else:
                    compare_2d = False
                if len(boxes_3d) > 0:
                    detections_3d = []
                    for idx, box in enumerate(boxes_3d):
                        if valid_3d[idx] == -1:
                            detections_3d.append(None)
                        else:
                            detections_3d.append(np.array(box).astype(np.float32))
                else:
                    detections_3d = None
            else:
                appearance_features = [appearance_features[i] for i in range(total_dets)]
                features = [None]*len(appearance_features)
                compare_2d = True
                detections_3d = None
            detections = convert_detections(detections, features, appearance_features, detections_3d)
            tracker.predict()
            if opt.log_data:
                full_log[frame_idx]['predicted_tracks'] = copy.deepcopy(tracker.tracks)
            start_time = time.time()
            tracker.update(input_img, detections, compare_2d)

        # --- END OF TRACKING ---
        end_time = time.time()
        frame_times.append(end_time - start_time)


        if opt.log_data:
            full_tracks = copy.deepcopy(tracker.tracks)
            temp_tracks = []
            for track in full_tracks:
                bbox = track.to_tlwh(None)
                if not (bbox[0] < 0-10 or bbox[1] < 0-10 or bbox[0] + bbox[2] > input_img.shape[2]+10 or bbox[1] + bbox[3] > input_img.shape[1]+10):
                    temp_tracks.append(track)
            full_log[frame_idx]['tracks'] = temp_tracks
            full_log[frame_idx]['detections'] = copy.deepcopy(detections)

        for track in tracker.tracks:
            if opt.track_3d:
                bbox_3d = track.to_tlwh3d()
            else:
                bbox = track.to_tlwh(None)
            if bbox[0] < 0-10 or bbox[1] < 0-10 or bbox[0] + bbox[2] > input_img.shape[2]+10 or bbox[1] + bbox[3] > input_img.shape[1]+10:
                continue
            bbox[0] = max(0,bbox[0]) # Frame adjustments
            bbox[1] = max(0,bbox[1])
            bbox[2] = min(bbox[0]+bbox[2], input_img.shape[2])-bbox[0]
            bbox[3] = min(bbox[1]+bbox[3], input_img.shape[1])-bbox[1]

            track_status = 1
            if not track.is_confirmed(): # or track.time_since_update > 0:
                if opt.near_online:
                    if not track.is_confirmed():
                         track_status = 0
                    else:
                         track_status = 2
                         continue
                else:
                    continue
            if opt.near_online:
                if opt.track_3d:
                    results_3d.append([frame_idx, track.track_id, bbox_3d[0], bbox_3d[1], bbox_3d[2], bbox_3d[3], bbox_3d[4], bbox_3d[5], bbox_3d[6], track_status])
                else:
                    results.append([frame_idx, track.track_id, bbox[0], bbox[1], bbox[2], bbox[3], track_status])

                if track_status == 1: #updates 0s
                    for row_i in range(len(results)):
                        if results[row_i][1] == track.track_id:
                            results[row_i][6] = 1
                        if opt.point_cloud:
                            if results_3d[row_i][1] == track.track_id:
                                results_3d[row_i][7] = 1
            else:
                if opt.track_3d:
                    results_3d.append([frame_idx, track.track_id, bbox_3d[0], bbox_3d[1], bbox_3d[2], bbox_3d[3], bbox_3d[4], bbox_3d[5], bbox_3d[6]])
                else:
                    results.append([frame_idx, track.track_id, bbox[0], bbox[1], bbox[2], bbox[3]])
                # if opt.point_cloud:

    frame_times = np.asarray(frame_times)
    if opt.verbose:
        print("------------------------")
        print("COMPLETED TRACKING, SAVING RESULTS")
        print("------------------------")
        print('\n\n','Total Tracking Time:',np.sum(frame_times),'Average Time Per Frame:',np.mean(frame_times))

    if opt.track_3d:
        output_file_3d = os.path.join(opt.output_folder, seq_name+"_3d.txt")
        if len(results_3d) > 0:
            with open(output_file_3d, 'w+') as f:
                for row in results_3d:
                    if opt.near_online and row[9] != 1:
                        continue
                    print('%d,%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.4f,1,1,1,-1' % (
                        row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]), file=f)
    else:
        output_file = os.path.join(opt.output_folder, seq_name+".txt")
        if len(results) > 0:
            with open(output_file, 'w+') as f:
                for row in results:
                    if opt.near_online and row[6] != 1:
                        continue
                    print('%d,%d,%.2f,%.2f,%.2f,%.2f,1,1,1,-1' % (
                        row[0], row[1], row[2], row[3], row[4], row[5]), file=f)

    if opt.log_data:
        output_file = os.path.join(opt.output_folder, seq_name+".p")
        with open(output_file, 'wb') as f:
            pickle.dump(full_log, f)

if __name__=='__main__':
    opt = parse_arguments()
    main(opt)


================================================
FILE: paper_experiments/utils/EKF.py
================================================
# vim: expandtab:ts=4:sw=4
import numpy as np
import scipy.linalg
import pdb

"""
Table for the 0.95 quantile of the chi-square distribution with N degrees of
freedom (contains values for N=1, ..., 9). Taken from MATLAB/Octave's chi2inv
function and used as Mahalanobis gating threshold.
"""
chi2inv95 = {
    1: 3.8415,
    2: 5.9915,
    3: 7.8147,
    4: 9.4877,
    5: 11.070,
    6: 12.592,
    7: 14.067,
    8: 15.507,
    9: 16.919}

chi2inv90 = {
    1: 2.706,
    2: 4.605,
    3: 6.251,
    4: 7.779,
    5: 9.236,
    6: 10.645,
    7: 12.017,
    8: 13.363,
    9: 14.684}

chi2inv975 = {
    1: 5.025,
    2: 7.378,
    3: 9.348,
    4: 11.143,
    5: 12.833,
    6: 14.449,
    7: 16.013,
    8: 17.535,
    9: 19.023}

chi2inv10 = {
    1: .016,
    2: .221,
    3: .584,
    4: 1.064,
    5: 1.610,
    6: 2.204,
    7: 2.833,
    8: 3.490,
    9: 4.168}


chi2inv995 = {
    1: 0.0000393,
    2: 0.0100,
    3: .0717,
    4: .207,
    5: .412,
    6: .676,
    7: .989,
    8: 1.344,
    9: 1.735}


chi2inv75 = {
    1: 1.323,
    2: 2.773,
    3: 4.108,
    4: 5.385,
    5: 6.626,
    6: 7.841,
    7: 9.037,
    8: 10.22,
    9: 11.39}

def squared_mahalanobis_distance(mean, covariance, measurements):
    # cholesky factorization used to solve for 
    # z = d * inv(covariance)
    # so z is also the solution to 
    # covariance * z = d       
    d = measurements - mean

    # Note: The cholesky factorization is giving weird answers. This is marginally slower but correct
    return np.matmul(np.matmul(d, np.linalg.inv(covariance)), d.T).diagonal()

    # print("Measurements:", measurements)
    # print("Mean:", mean)
    # print("dshape:", d.shape, "d:", d)
    # print("d*inv(cov)", np.matmul(d, np.linalg.inv(covariance)))

    cholesky_factor = np.linalg.cholesky(covariance)
    z = scipy.linalg.solve_triangular(
        cholesky_factor, d.T, lower=True, check_finite=False,
        overwrite_b=True)

    squared_maha = np.sum(z * (measurements-mean).T, axis=0)
    # print("Squared maha dist:", squared_maha)
    # print("cov:", covariance)
    # print("z", z, '\n')
    return squared_maha


class EKF(object):
    """
    Generic extended kalman filter class

    """

    def __init__(self):
        pass

    def initiate(self, measurement):
        """Create track from unassociated measurement.

        Parameters
        ----------
        measurement : ndarray

        Returns
        -------
        (ndarray, ndarray)
            Returns the mean vector and covariance matrix of the new track. 
            Unobserved velocities are initialized to 0 mean.

        """
        pass


    def predict_mean(self, mean):
        # Updates predicted state from previous state (function g)
        # Calculates motion update Jacobian (Gt)
        # Returns (g(mean), Gt)
        pass

    def get_process_noise(self, mean, covariance):
        # Returns Rt the motion noise covariance
        pass
    def predict_covariance(self, mean, covariance):
        pass

    def project_mean(self, mean):
        # Measurement prediction from state (function h)
        # Calculations sensor update Jacobian (Ht)
        # Returns (h(mean), Ht)
        pass
    def project_cov(self, mean, covariance):
        pass

    def predict(self, mean, covariance, last_detection, next_to_last_detection):
        """Run Kalman filter prediction step.

        Parameters
        ----------
        mean : ndarray
            The mean vector of the object state at the previous
            time step.
        covariance : ndarray
            The covariance matrix of the object state at the
            previous time step.

        Returns
        -------
        (ndarray, ndarray)
            Returns the mean vector and covariance matrix of the predicted
            state. Unobserved velocities are initialized to 0 mean.

        """
        # Perform prediction
        covariance = self.predict_covariance(mean, covariance, last_detection, next_to_last_detection)
        mean = self.predict_mean(mean)

        return mean, covariance
    def get_innovation_cov(self, covariance):
        pass

    def project(self, mean, covariance):
        """Project state distribution to measurement space.

        Parameters
        ----------
        mean : ndarray
            The state's mean vector 
        covariance : ndarray
            The state's covariance matrix

        Returns
        -------
        (ndarray, ndarray)
            Returns the projected mean and covariance matrix of the given state
            estimate.

        """

        # Measurement uncertainty scaled by estimated height
        return self.project_mean(mean), self.project_cov(mean, covariance)

    def update(self, mean, covariance, measurement_t, marginalization=None, JPDA=False):
        """Run Kalman filter correction step.

        Parameters
        ----------
        mean : ndarray
            The predicted state's mean vector (8 dimensional).
        covariance : ndarray
            The state's covariance matrix (8x8 dimensional).
        measurement : ndarray
            The 4 dimensional measurement vector (x, y, a, h), where (x, y)
            is the center position, a the aspect ratio, and h the height of the
            bounding box.

        Returns
        -------
        (ndarray, ndarray)
            Returns the measurement-corrected state distribution.

        """
        predicted_measurement, innovation_cov  = self.project(mean, covariance)
        # cholesky factorization used to solve for kalman gain since
        # K = covariance * update_mat.T * inv(innovation_cov)
        # so K is also the solution to 
        # innovation_cov * K = covariance * update_mat.T
        try:
            chol_factor, lower = scipy.linalg.cho_factor(
                innovation_cov, lower=True, check_finite=False)
            kalman_gain = scipy.linalg.cho_solve(
                (chol_factor, lower), np.dot(covariance, self._observation_mat.T).T,
                check_finite=False).T
        except:
            # in case cholesky factorization fails, revert to standard solver
            kalman_gain = np.linalg.solve(innovation_cov, np.dot(covariance, self._observation_mat.T).T).T

        if JPDA:
            # marginalization
            innovation = np.zeros((self.ndim)) 
            cov_soft = np.zeros((self.ndim, self.ndim))

            for measurement_idx, measurement in enumerate(measurement_t):

                p_ij = marginalization[measurement_idx + 1] # + 1 for dummy
                y_ij = measurement - predicted_measurement
                innovation += y_ij * p_ij
                cov_soft += p_ij * np.outer(y_ij, y_ij)

            cov_soft = cov_soft - np.outer(innovation, innovation)

            P_star = covariance - np.linalg.multi_dot((
                kalman_gain, innovation_cov, kalman_gain.T))

            p_0 = marginalization[0]
            P_0 = p_0 * covariance + (1 - p_0) * P_star

            new_covariance = P_0 + np.linalg.multi_dot((kalman_gain, cov_soft, kalman_gain.T))
            
        else:
            innovation = measurement_t - predicted_measurement

            new_covariance = covariance - np.linalg.multi_dot((
                kalman_gain, innovation_cov, kalman_gain.T))

        new_mean = mean + np.dot(innovation, kalman_gain.T)
        return new_mean, new_covariance


================================================
FILE: paper_experiments/utils/JPDA_matching.py
================================================
# vim: expandtab:ts=4:sw=4
from __future__ import absolute_import
import numpy as np
from linear_assignment import min_marg_matching
import pdb


def get_unmatched(all_idx, matches, i, marginalization=None):
    assigned = [match[i] for match in matches]
    unmatched = set(all_idx) - set(assigned)
    if marginalization is not None:
        # from 1 for dummy node
        in_gate_dets = np.nonzero(np.sum(
            marginalization[:, 1:], axis=0))[0].tolist()
        # unmatched = [d for d in unmatched if d not in in_gate_dets] # TODO: Filter by gate?
    return list(unmatched)


class Matcher:

    def __init__(self, detections, marginalizations, confirmed_tracks,
                 matching_strategy,
                 assignment_threshold=None):
        self.detections = detections
        self.marginalizations = marginalizations
        self.confirmed_tracks = confirmed_tracks
        self.assignment_threshold = assignment_threshold
        self.detection_indices = np.arange(len(detections))
        self.matching_strategy = matching_strategy

    def match(self):
        self.get_matches()
        self.get_unmatched_tracks()
        self.get_unmatched_detections()
        return self.matches, self.unmatched_tracks, self.unmatched_detections

    def get_matches(self):

        if self.matching_strategy == "max_and_threshold":
            self.max_and_threshold_matching()
        elif self.matching_strategy == "hungarian":
            self.hungarian()
        elif self.matching_strategy == "max_match":
            self.max_match()
        elif self.matching_strategy == "none":
            self.matches = []
        else: 
            raise Exception('Unrecognized matching strategy: {}'.
                            format(self.matching_strategy))

    def get_unmatched_tracks(self):
        self.unmatched_tracks = get_unmatched(self.confirmed_tracks,
                                              self.matches, 0)

    def get_unmatched_detections(self):
        self.unmatched_detections = get_unmatched(self.detection_indices, self.matches, 1, self.marginalizations)

    def max_match(self):
        self.matches = []
        if self.marginalizations.shape[0] == 0:
            return

        detection_map = {}
        for i, track_idx in enumerate(self.confirmed_tracks):
            marginalization = self.marginalizations[i,:]
            detection_id = np.argmax(marginalization) - 1  # subtract one for dummy

            if detection_id < 0:
                continue

            if detection_id not in detection_map.keys():
                detection_map[detection_id] = track_idx
            else:
                cur_track = detection_map[detection_id]
                track_update = track_idx if self.marginalizations[track_idx, detection_id] > self.marginalizations[cur_track, detection_id] else cur_track
                detection_map[detection_id] = track_update
            threshold_p = marginalization[detection_id + 1]
            if threshold_p < self.assignment_threshold:
                continue

        for detection in detection_map.keys():
            self.matches.append((detection_map[detection], detection))

    def max_and_threshold_matching(self):

        self.matches = []
        if self.marginalizations.shape[0] == 0:
            return

        for i, track_idx in enumerate(self.confirmed_tracks):
            marginalization = self.marginalizations[i,:]
            detection_id = np.argmax(marginalization) - 1  # subtract one for dummy

            if detection_id < 0:
                continue

            threshold_p = marginalization[detection_id + 1]
            if threshold_p < self.assignment_threshold:
                continue

            self.matches.append((track_idx, detection_id))

    def hungarian(self):
        self.matches, _, _ = min_marg_matching(self.marginalizations,
                                               self.confirmed_tracks,
                                               self.assignment_threshold)
                               


================================================
FILE: paper_experiments/utils/aligned_reid_utils.py
================================================
from __future__ import print_function
import os
import os.path as osp
import pickle
from scipy import io
import datetime
import time
from contextlib import contextmanager
import numpy as np
from PIL import Image
import torch
from torch.autograd import Variable
from models.aligned_reid_model import Model as aligned_reid_model
from models.deep_sort_model import ImageEncoder as deep_sort_model
from utils.resnet_reid_utils import ResNet_Loader

def time_str(fmt=None):
  if fmt is None:
    fmt = '%Y-%m-%d_%H:%M:%S'
  return datetime.datetime.today().strftime(fmt)


def load_pickle(path):
  """Check and load pickle object.
  According to this post: https://stackoverflow.com/a/41733927, cPickle and 
  disabling garbage collector helps with loading speed."""
  assert osp.exists(path)
  # gc.disable()
  with open(path, 'rb') as f:
    ret = pickle.load(f)
  # gc.enable()
  return ret


def save_pickle(obj, path):
  """Create dir and save file."""
  may_make_dir(osp.dirname(osp.abspath(path)))
  with open(path, 'wb') as f:
    pickle.dump(obj, f, protocol=2)


def save_mat(ndarray, path):
  """Save a numpy ndarray as .mat file."""
  io.savemat(path, dict(ndarray=ndarray))


def to_scalar(vt):
  """Transform a length-1 pytorch Variable or Tensor to scalar. 
  Suppose tx is a torch Tensor with shape tx.size() = torch.Size([1]), 
  then npx = tx.cpu().numpy() has shape (1,), not 1."""
  if isinstance(vt, Variable):
    return vt.data.cpu().numpy().flatten()[0]
  if torch.is_tensor(vt):
    return vt.cpu().numpy().flatten()[0]
  raise TypeError('Input should be a variable or tensor')


def transfer_optim_state(state, device_id=-1):
  """Transfer an optimizer.state to cpu or specified gpu, which means 
  transferring tensors of the optimizer.state to specified device. 
  The modification is in place for the state.
  Args:
    state: An torch.optim.Optimizer.state
    device_id: gpu id, or -1 which means transferring to cpu
  """
  for key, val in state.items():
    if isinstance(val, dict):
      transfer_optim_state(val, device_id=device_id)
    elif isinstance(val, Variable):
      raise RuntimeError("Oops, state[{}] is a Variable!".format(key))
    elif isinstance(val, torch.nn.Parameter):
      raise RuntimeError("Oops, state[{}] is a Parameter!".format(key))
    else:
      try:
        if device_id == -1:
          state[key] = val.cpu()
        else:
          state[key] = val.cuda(device=device_id)
      except:
        pass


def may_transfer_optims(optims, device_id=-1):
  """Transfer optimizers to cpu or specified gpu, which means transferring 
  tensors of the optimizer to specified device. The modification is in place 
  for the optimizers.
  Args:
    optims: A list, which members are either torch.nn.optimizer or None.
    device_id: gpu id, or -1 which means transferring to cpu
  """
  for optim in optims:
    if isinstance(optim, torch.optim.Optimizer):
      transfer_optim_state(optim.state, device_id=device_id)


def may_transfer_modules_optims(modules_and_or_optims, device_id=-1):
  """Transfer optimizers/modules to cpu or specified gpu.
  Args:
    modules_and_or_optims: A list, which members are either torch.nn.optimizer 
      or torch.nn.Module or None.
    device_id: gpu id, or -1 which means transferring to cpu
  """
  for item in modules_and_or_optims:
    if isinstance(item, torch.optim.Optimizer):
      transfer_optim_state(item.state, device_id=device_id)
    elif isinstance(item, torch.nn.Module):
      if device_id == -1:
        item.cpu()
      else:
        item.cuda(device=device_id)
    elif item is not None:
      print('[Warning] Invalid type {}'.format(item.__class__.__name__))


class TransferVarTensor(object):
  """Return a copy of the input Variable or Tensor on specified device."""

  def __init__(self, device_id=-1):
    self.device_id = device_id

  def __call__(self, var_or_tensor):
    return var_or_tensor.cpu() if self.device_id == -1 \
      else var_or_tensor.cuda(self.device_id)


class TransferModulesOptims(object):
  """Transfer optimizers/modules to cpu or specified gpu."""

  def __init__(self, device_id=-1):
    self.device_id = device_id

  def __call__(self, modules_and_or_optims):
    may_transfer_modules_optims(modules_and_or_optims, self.device_id)


def set_devices(sys_device_ids):
  """
  It sets some GPUs to be visible and returns some wrappers to transferring 
  Variables/Tensors and Modules/Optimizers.
  Args:
    sys_device_ids: a tuple; which GPUs to use
      e.g.  sys_device_ids = (), only use cpu
            sys_device_ids = (3,), use the 4th gpu
            sys_device_ids = (0, 1, 2, 3,), use first 4 gpus
            sys_device_ids = (0, 2, 4,), use the 1st, 3rd and 5th gpus
  Returns:
    TVT: a `TransferVarTensor` callable
    TMO: a `TransferModulesOptims` callable
  """
  # Set the CUDA_VISIBLE_DEVICES environment variable
  import os
  visible_devices = ''
  for i in sys_device_ids:
    visible_devices += '{}, '.format(i)
  os.environ['CUDA_VISIBLE_DEVICES'] = visible_devices
  # Return wrappers.
  # Models and user defined Variables/Tensors would be transferred to the
  # first device.
  device_id = 0 if len(sys_device_ids) > 0 else -1
  TVT = TransferVarTensor(device_id)
  TMO = TransferModulesOptims(device_id)
  return TVT, TMO


def set_devices_for_ml(sys_device_ids):
  """This version is for mutual learning.
  
  It sets some GPUs to be visible and returns some wrappers to transferring 
  Variables/Tensors and Modules/Optimizers.
  
  Args:
    sys_device_ids: a tuple of tuples; which devices to use for each model, 
      len(sys_device_ids) should be equal to number of models. Examples:
        
      sys_device_ids = ((-1,), (-1,))
        the two models both on CPU
      sys_device_ids = ((-1,), (2,))
        the 1st model on CPU, the 2nd model on GPU 2
      sys_device_ids = ((3,),)
        the only one model on the 4th gpu 
      sys_device_ids = ((0, 1), (2, 3))
        the 1st model on GPU 0 and 1, the 2nd model on GPU 2 and 3
      sys_device_ids = ((0,), (0,))
        the two models both on GPU 0
      sys_device_ids = ((0,), (0,), (1,), (1,))
        the 1st and 2nd model on GPU 0, the 3rd and 4th model on GPU 1
  
  Returns:
    TVTs: a list of `TransferVarTensor` callables, one for one model.
    TMOs: a list of `TransferModulesOptims` callables, one for one model.
    relative_device_ids: a list of lists; `sys_device_ids` transformed to 
      relative ids; to be used in `DataParallel`
  """
  import os

  all_ids = []
  for ids in sys_device_ids:
    all_ids += ids
  unique_sys_device_ids = list(set(all_ids))
  unique_sys_device_ids.sort()
  if -1 in unique_sys_device_ids:
    unique_sys_device_ids.remove(-1)

  # Set the CUDA_VISIBLE_DEVICES environment variable

  visible_devices = ''
  for i in unique_sys_device_ids:
    visible_devices += '{}, '.format(i)
  os.environ['CUDA_VISIBLE_DEVICES'] = visible_devices

  # Return wrappers

  relative_device_ids = []
  TVTs, TMOs = [], []
  for ids in sys_device_ids:
    relative_ids = []
    for id in ids:
      if id != -1:
        id = find_index(unique_sys_device_ids, id)
      relative_ids.append(id)
    relative_device_ids.append(relative_ids)

    # Models and user defined Variables/Tensors would be transferred to the
    # first device.
    TVTs.append(TransferVarTensor(relative_ids[0]))
    TMOs.append(TransferModulesOptims(relative_ids[0]))
  return TVTs, TMOs, relative_device_ids


def load_ckpt(modules_optims, ckpt_file, load_to_cpu=True, verbose=True):
  """Load state_dict's of modules/optimizers from file.
  Args:
    modules_optims: A list, which members are either torch.nn.optimizer 
      or torch.nn.Module.
    ckpt_file: The file path.
    load_to_cpu: Boolean. Whether to transform tensors in modules/optimizers 
      to cpu type.
  """
  map_location = (lambda storage, loc: storage) if load_to_cpu else None
  ckpt = torch.load(ckpt_file, map_location=map_location)
  for m, sd in zip(modules_optims, ckpt['state_dicts']):
    if 'fc.weight' in sd:
      del sd['fc.weight']
    if 'fc.bias' in sd:  
      del sd['fc.bias']
    load_state_dict(m, sd)
  if verbose:
    print('Resume from ckpt {}, \nepoch {}, \nscores {}'.format(
      ckpt_file, ckpt['ep'], ckpt['scores']))
  return ckpt['ep'], ckpt['scores']


def save_ckpt(modules_optims, ep, scores, ckpt_file):
  """Save state_dict's of modules/optimizers to file. 
  Args:
    modules_optims: A list, which members are either torch.nn.optimizer 
      or torch.nn.Module.
    ep: the current epoch number
    scores: the performance of current model
    ckpt_file: The file path.
  Note:
    torch.save() reserves device type and id of tensors to save, so when 
    loading ckpt, you have to inform torch.load() to load these tensors to 
    cpu or your desired gpu, if you change devices.
  """
  state_dicts = [m.state_dict() for m in modules_optims]
  ckpt = dict(state_dicts=state_dicts,
              ep=ep,
              scores=scores)
  may_make_dir(osp.dirname(osp.abspath(ckpt_file)))
  torch.save(ckpt, ckpt_file)


def load_state_dict(model, src_state_dict):
  """Copy parameters and buffers from `src_state_dict` into `model` and its 
  descendants. The `src_state_dict.keys()` NEED NOT exactly match 
  `model.state_dict().keys()`. For dict key mismatch, just
  skip it; for copying error, just output warnings and proceed.

  Arguments:
    model: A torch.nn.Module object. 
    src_state_dict (dict): A dict containing parameters and persistent buffers.
  Note:
    This is modified from torch.nn.modules.module.load_state_dict(), to make
    the warnings and errors more detailed.
  """
  from torch.nn import Parameter
  dest_state_dict = model.state_dict()
  for name, param in src_state_dict.items():
    ### CHANGED HERE FOR FINE TUNING
    if name not in dest_state_dict:
      continue
    if isinstance(param, Parameter):
      # backwards compatibility for serialized parameters
      param = param.data
    try:
      dest_state_dict[name].copy_(param)
    except Exception as e:
      print("Warning: Error occurs when copying '{}': {}"
            .format(name, str(e)))

  # src_missing = set(dest_state_dict.keys()) - set(src_state_dict.keys())
  # if len(src_missing) > 0:
  #   print("Keys not found in source state_dict: ")
  #   for n in src_missing:
  #     print('\t', n)

  # dest_missing = set(src_state_dict.keys()) - set(dest_state_dict.keys())
  # if len(dest_missing) > 0:
  #   print("Keys not found in destination state_dict: ")
  #   for n in dest_missing:
  #     print('\t', n)


def is_iterable(obj):
  return hasattr(obj, '__len__')


def may_set_mode(maybe_modules, mode):
  """maybe_modules: an object or a list of objects."""
  assert mode in ['train', 'eval']
  if not is_iterable(maybe_modules):
    maybe_modules = [maybe_modules]
  for m in maybe_modules:
    if isinstance(m, torch.nn.Module):
      if mode == 'train':
        m.train()
      else:
        m.eval()


def may_make_dir(path):
  """
  Args:
    path: a dir, or result of `osp.dirname(osp.abspath(file_path))`
  Note:
    `osp.exists('')` returns `False`, while `osp.exists('.')` returns `True`!
  """
  # This clause has mistakes:
  # if path is None or '':

  if path in [None, '']:
    return
  if not osp.exists(path):
    os.makedirs(path)


class AverageMeter(object):
  """Modified from Tong Xiao's open-reid. 
  Computes and stores the average and current value"""

  def __init__(self):
    self.val = 0
    self.avg = 0
    self.sum = 0
    self.count = 0

  def reset(self):
    self.val = 0
    self.avg = 0
    self.sum = 0
    self.count = 0

  def update(self, val, n=1):
    self.val = val
    self.sum += val * n
    self.count += n
    self.avg = float(self.sum) / (self.count + 1e-20)


class RunningAverageMeter(object):
  """Computes and stores the running average and current value"""

  def __init__(self, hist=0.99):
    self.val = None
    self.avg = None
    self.hist = hist

  def reset(self):
    self.val = None
    self.avg = None

  def update(self, val):
    if self.avg is None:
      self.avg = val
    else:
      self.avg = self.avg * self.hist + val * (1 - self.hist)
    self.val = val


class RecentAverageMeter(object):
  """Stores and computes the average of recent values."""

  def __init__(self, hist_size=100):
    self.hist_size = hist_size
    self.fifo = []
    self.val = 0

  def reset(self):
    self.fifo = []
    self.val = 0

  def update(self, val):
    self.val = val
    self.fifo.append(val)
    if len(self.fifo) > self.hist_size:
      del self.fifo[0]

  @property
  def avg(self):
    assert len(self.fifo) > 0
    return float(sum(self.fifo)) / len(self.fifo)


def get_model_wrapper(model, multi_gpu):
  from torch.nn.parallel import DataParallel
  if multi_gpu:
    return DataParallel(model)
  else:
    return model


class ReDirectSTD(object):
  """Modified from Tong Xiao's `Logger` in open-reid.
  This class overwrites sys.stdout or sys.stderr, so that console logs can
  also be written to file.
  Args:
    fpath: file path
    console: one of ['stdout', 'stderr']
    immediately_visible: If `False`, the file is opened only once and closed
      after exiting. In this case, the message written to file may not be
      immediately visible (Because the file handle is occupied by the
      program?). If `True`, each writing operation of the console will
      open, write to, and close the file. If your program has tons of writing
      operations, the cost of opening and closing file may be obvious. (?)
  Usage example:
    `ReDirectSTD('stdout.txt', 'stdout', False)`
    `ReDirectSTD('stderr.txt', 'stderr', False)`
  NOTE: File will be deleted if already existing. Log dir and file is created
    lazily -- if no message is written, the dir and file will not be created.
  """

  def __init__(self, fpath=None, console='stdout', immediately_visible=False):
    import sys
    import os
    import os.path as osp

    assert console in ['stdout', 'stderr']
    self.console = sys.stdout if console == 'stdout' else sys.stderr
    self.file = fpath
    self.f = None
    self.immediately_visible = immediately_visible
    if fpath is not None:
      # Remove existing log file.
      if osp.exists(fpath):
        os.remove(fpath)

    # Overwrite
    if console == 'stdout':
      sys.stdout = self
    else:
      sys.stderr = self

  def __del__(self):
    self.close()

  def __enter__(self):
    pass

  def __exit__(self, *args):
    self.close()

  def write(self, msg):
    self.console.write(msg)
    if self.file is not None:
      may_make_dir(os.path.dirname(osp.abspath(self.file)))
      if self.immediately_visible:
        with open(self.file, 'a') as f:
          f.write(msg)
      else:
        if self.f is None:
          self.f = open(self.file, 'w')
        self.f.write(msg)

  def flush(self):
    self.console.flush()
    if self.f is not None:
      self.f.flush()
      import os
      os.fsync(self.f.fileno())

  def close(self):
    self.console.close()
    if self.f is not None:
      self.f.close()


def set_seed(seed):
  import random
  random.seed(seed)
  print('setting random-seed to {}'.format(seed))

  import numpy as np
  np.random.seed(seed)
  print('setting np-random-seed to {}'.format(seed))

  import torch
  torch.backends.cudnn.enabled = False
  print('cudnn.enabled set to {}'.format(torch.backends.cudnn.enabled))
  # set seed for CPU
  torch.manual_seed(seed)
  print('setting torch-seed to {}'.format(seed))


def print_array(array, fmt='{:.2f}', end=' '):
  """Print a 1-D tuple, list, or numpy array containing digits."""
  s = ''
  for x in array:
    s += fmt.format(float(x)) + end
  s += '\n'
  print(s)
  return s


# Great idea from https://github.com/amdegroot/ssd.pytorch
def str2bool(v):
  return v.lower() in ("yes", "true", "t", "1")


def tight_float_str(x, fmt='{:.4f}'):
  return fmt.format(x).rstrip('0').rstrip('.')


def find_index(seq, item):
  for i, x in enumerate(seq):
    if item == x:
      return i
  return -1


def adjust_lr_exp(optimizer, base_lr, ep, total_ep, start_decay_at_ep):
  """Decay exponentially in the later phase of training. All parameters in the 
  optimizer share the same learning rate.
  
  Args:
    optimizer: a pytorch `Optimizer` object
    base_lr: starting learning rate
    ep: current epoch, ep >= 1
    total_ep: total number of epochs to train
    start_decay_at_ep: start decaying at the BEGINNING of this epoch
  
  Example:
    base_lr = 2e-4
    total_ep = 300
    start_decay_at_ep = 201
    It means the learning rate starts at 2e-4 and begins decaying after 200 
    epochs. And training stops after 300 epochs.
  
  NOTE: 
    It is meant to be called at the BEGINNING of an epoch.
  """
  assert ep >= 1, "Current epoch number should be >= 1"

  if ep < start_decay_at_ep:
    return

  for g in optimizer.param_groups:
    g['lr'] = (base_lr * (0.001 ** (float(ep + 1 - start_decay_at_ep)
                                    / (total_ep + 1 - start_decay_at_ep))))
  print('=====> lr adjusted to {:.10f}'.format(g['lr']).rstrip('0'))


def adjust_lr_staircase(optimizer, base_lr, ep, decay_at_epochs, factor):
  """Multiplied by a factor at the BEGINNING of specified epochs. All 
  parameters in the optimizer share the same learning rate.
  
  Args:
    optimizer: a pytorch `Optimizer` object
    base_lr: starting learning rate
    ep: current epoch, ep >= 1
    decay_at_epochs: a list or tuple; learning rate is multiplied by a factor 
      at the BEGINNING of these epochs
    factor: a number in range (0, 1)
  
  Example:
    base_lr = 1e-3
    decay_at_epochs = [51, 101]
    factor = 0.1
    It means the learning rate starts at 1e-3 and is multiplied by 0.1 at the 
    BEGINNING of the 51'st epoch, and then further multiplied by 0.1 at the 
    BEGINNING of the 101'st epoch, then stays unchanged till the end of 
    training.
  
  NOTE: 
    It is meant to be called at the BEGINNING of an epoch.
  """
  assert ep >= 1, "Current epoch number should be >= 1"

  if ep not in decay_at_epochs:
    return

  ind = find_index(decay_at_epochs, ep)
  for g in optimizer.param_groups:
    g['lr'] = base_lr * factor ** (ind + 1)
  print('=====> lr adjusted to {:.10f}'.format(g['lr']).rstrip('0'))


@contextmanager
def measure_time(enter_msg):
  st = time.time()
  print(enter_msg)
  yield
  print('Done, {:.2f}s'.format(time.time() - st))

# @profile
def generate_features(appearance_model, patches, opt, object_ids = None):
    Tensor = torch.cuda.FloatTensor if opt.using_cuda else torch.FloatTensor
    features = []
    for i, patch in enumerate(patches):
        if patch is None or patch.nelement()==0:
            features.append(None)
            continue
        patch = patch.unsqueeze(0)
        if opt.perfect:
            feature = torch.zeros(1024)
            feature[object_ids[i]] = 1
            feature = feature.type(Tensor)
        else:
            if opt.appearance_model == 'aligned_reid':
                with torch.no_grad():
                    feature ,_ = appearance_model(patch.cuda())
                    feature = feature.squeeze(0).type(Tensor)
            elif opt.appearance_model == 'deepsort':
                patch = patch.permute(0,2,3,1).cpu().numpy()
                feature = appearance_model(patch)
                feature = feature[0]
            elif opt.appearance_model == 'resnet_reid':
                patch = patch.permute(0,2,3,1)
                feature = appearance_model.inference([patch.squeeze(0)])
                feature = feature[0][0].type(Tensor)
        features.append(feature)
    return features

# @profile
def generate_features_batched(appearance_model, patches, opt, object_ids = None):
    if opt.perfect or opt.appearance_model == 'deepsort': # Do old/slow way if perfect features or deepsort features
        return generate_features(appearance_model, patches, opt, object_ids)

    if opt.appearance_model == 'resnet_reid':
        Tensor = torch.cuda.FloatTensor if opt.using_cuda else torch.FloatTensor

        features = []
        resnet_patches = []
        for i, patch in enumerate(patches):
            if patch is None or patch.nelement()==0:
                features.append(None)
            else:
                features.append(1)
                resnet_patches.append(patch.permute(1,2,0))

        resnet_features = appearance_model.inference(resnet_patches)
        ctr = 0
        for i in range(len(features)):
            if features[i] is not None:
                features[i] = resnet_features[ctr].type(Tensor)
                ctr += 1
        return features

    elif opt.appearance_model == 'aligned_reid':
        return generate_features(appearance_model, patches, opt, object_ids)   #TODO: Fix batched appearance features. This currently gives bad features
        Tensor = torch.cuda.FloatTensor if opt.using_cuda else torch.FloatTensor
        maxx = -1
        maxy = -1
        idxs = []
        features = []
        for i, patch in enumerate(patches):
            if patch is None or patch.nelement()==0:
                continue
            maxx = max(maxx, patch.size()[1])
            maxy = max(maxy, patch.size()[2])
            idxs.append(i)

        if(maxx==-1 and maxy==-1):
            return features
        batch = torch.zeros(len(idxs),3,maxx,maxy).cuda()
        for i, idx in enumerate(idxs):
            patch = patches[idx]
            patchx = patch.size()[1]
            patchy = patch.size()[2]
            batch[i,:,:patchx,:patchy] = patch

        with torch.no_grad():
            features_torch, _ = appearance_model(batch)
            features_torch = features_torch.type(Tensor)

            i = 0
            ctr = 0
            for idx in idxs:
                while(i < idx):
                    features.append(None)
                    i+=1
                features.append(features_torch[ctr,:])
                i+=1
                ctr+=1
            while(i<len(patches)):
                features.append(None)
                i+=1

        return features
    else:
        print("Critical Error! Attempted to batch appearance features but no model was selected")

def get_image_patches(input_img, detections):
    #Generates patches and also converts detections
    patches = []

    for detection in detections:
        x1, y1, x2, y2, _, _, _ = detection
            # Rescale coordinates to original dimensions
        x1 = x1.item()
        x2 = x2.item()
        y1 = y1.item()
        y2 = y2.item()

        box_h = round(y2-y1)
        box_w = round(x2-x1)
        x1=round(x1)
        y1=round(y1)

        patch = input_img[:, y1:y1+box_h, x1:x1+box_w]
        patches.append(patch)

    return patches

def create_appearance_model(model_type, alignreid_checkpoint, resnet_reid_checkpoint=None, cuda=True):
    if model_type == 'aligned_reid':
        appearance_model = aligned_reid_model()
        map_location = (lambda storage, loc: storage)
        sd = torch.load(alignreid_checkpoint, map_location=map_location)
        load_state_dict(appearance_model, sd['state_dicts'][0])
        if cuda:
            appearance_model.cuda()
        appearance_model.eval()
    elif model_type == 'deepsort':
        appearance_model = deep_sort_model()
    elif model_type == 'resnet_reid':
        appearance_model = ResNet_Loader(resnet_reid_checkpoint)

    return appearance_model


================================================
FILE: paper_experiments/utils/assign_ids_detections.py
================================================
import numpy as np
import os
import pdb
from tqdm import tqdm
from deep_sort_utils import non_max_suppression as deepsort_nms
from visualise import draw_track
import matplotlib.pyplot as plt
from PIL import Image
from evaluate_detections import iou

def assign_detection_id(detection_path, gt_path, conf_threshold = 0, iou_threshold = 0.5):
	#expecting detections and gt in file with format as in read_detections.py
	# applies confidence thresholding
	try:
		detections = np.loadtxt(detection_path, delimiter=',')
		gt = np.loadtxt(gt_path, delimiter=',')
	except:
		return
	gt_frames = gt[:, 0]
	det_confidence = detections[:, 6]

	###CONFIDENCE THRESHOLD
	detections = detections[det_confidence > conf_threshold]
	########

	det_frames = detections[:, 0]
	det_confidence = detections[:, 6]
	gt_boxes = np.asarray(list(zip(gt[:, 2], gt[:, 3], gt[:, 4], gt[:, 5])))
	det_boxes = np.asarray(list(zip(detections[:, 2], detections[:, 3], detections[:, 4], detections[:, 5])))
	out_matrix = []
	assigned_ids = []

	for frame in np.unique(det_frames):
		frame_mask_det = det_frames == frame
		frame_mask_gt = gt_frames == frame
		gt_ids = gt[frame_mask_gt, 1]
		frame_gt_boxes = gt_boxes[frame_mask_gt]
		frame_det_boxes = det_boxes[frame_mask_det]

		for i, det_box in enumerate(frame_det_boxes):
			iou_list = np.asarray([iou(gt_box, det_box) for gt_box in frame_gt_boxes])
			iou_sorted = np.argsort(iou_list)
			positive_idx = np.where(iou_list >= iou_threshold)[0]
			if len(positive_idx)==0:
				assigned_ids.append(-1)
			else:
				assigned_ids.append(gt_ids[iou_sorted[-1]])
	assigned_ids = np.expand_dims(np.asarray(assigned_ids), 1)
	
	try:
		out_matrix = np.hstack([np.expand_dims(detections[:,0], 1), assigned_ids, detections[:,2:]])
	except:
		pdb.set_trace()
	np.savetxt(detection_path, out_matrix, delimiter=',', fmt = '%.2f')


	return

if __name__=='__main__':
	ap = []
	KITTI_root = 'data/KITTI/sequences'
	for sequence in tqdm(range(21)):
		assign_detection_id(os.path.join(KITTI_root, '%.4d'%sequence, 'det','rrc_subcnn_car_det.txt'), 
										os.path.join(KITTI_root, '%.4d'%sequence, 'gt', 'gt_car.txt'))


================================================
FILE: paper_experiments/utils/calibration.py
================================================
import numpy as np
import cv2
import os
import yaml
import torch
import pdb

class Calibration(object):
    ''' Calibration matrices and utils
        3d XYZ in <label>.txt are in rect camera coord.
        2d box xy are in image2 coord
        Points in <lidar>.bin are in Velodyne coord.
        y_image2 = P^2_rect * x_rect
        y_image2 = P^2_rect * R0_rect * Tr_velo_to_cam * x_velo
        x_ref = Tr_velo_to_cam * x_velo
        x_rect = R0_rect * x_ref
        P^2_rect = [f^2_u,  0,      c^2_u,  -f^2_u b^2_x;
                    0,      f^2_v,  c^2_v,  -f^2_v b^2_y;
                    0,      0,      1,      0]
                 = K * [1|t]
        image2 coord:
         ----> x-axis (u)
        |
        |
        v y-axis (v)
        velodyne coord:
        front x, left y, up z
        rect/ref camera coord:
        right x, down y, front z
        Ref (KITTI paper): http://www.cvlibs.net/publications/Geiger2013IJRR.pdf
        TODO(rqi): do matrix multiplication only once for each projection.
    '''
    def __init__(self, calib_filepath):

        calibs = self.read_calib_file(calib_filepath)
        # Projection matrix from rect camera coord to image2 coord
        self.P = calibs['P2'] 
        self.P = np.reshape(self.P, [3,4])
        self.P_torch = torch.from_numpy(self.P).float().cuda()

        # Rigid transform from Velodyne coord to reference camera coord
        try:
            self.V2C = calibs['Tr_velo_to_cam']
        except:
            self.V2C = calibs['Tr_velo_cam']

        self.V2C = np.reshape(self.V2C, [3,4])
        self.C2V = inverse_rigid_trans(self.V2C)
        # Rotation from reference camera coord to rect camera coord
        try:
            self.R0 = calibs['R0_rect']
        except:
            self.R0 = calibs['R_rect']
        self.R0 = np.reshape(self.R0,[3,3])
        self.R0_torch = torch.from_numpy(self.R0).float().cuda()

        RA = np.zeros((4,4))
        RA[:3,:3] = self.R0
        RA[3,3] = 1
        self.D = np.matmul(self.P,RA).T
        self.D_torch = torch.from_numpy(self.D).float().cuda()

        # Camera intrinsics and extrinsics
        self.c_u = self.P[0,2]
        self.c_v = self.P[1,2]
        self.f_u = self.P[0,0]
        self.f_v = self.P[1,1]
        self.b_x = self.P[0,3]/(-self.f_u) # relative 
        self.b_y = self.P[1,3]/(-self.f_v)

    def read_calib_file(self, filepath):
        ''' Read in a calibration file and parse into a dictionary.
        Ref: https://github.com/utiasSTARS/pykitti/blob/master/pykitti/utils.py
        '''
        data = {}
        with open(filepath, 'r') as f:
            for line in f.readlines():
                line = line.rstrip()
                if len(line)==0: continue
                key, value = line.split(' ', 1)
                if key.endswith(':'):
                    key = key[:-1]
                # The only non-float values in these files are dates, which
                # we don't care about anyway
                try:
                    data[key] = np.array([float(x) for x in value.split()])
                except ValueError:
                    pass

        return data
    
    def read_calib_from_video(self, calib_root_dir):
        ''' Read calibration for camera 2 from video calib files.
            there are calib_cam_to_cam and calib_velo_to_cam under the calib_root_dir
        '''
        data = {}
        cam2cam = self.read_calib_file(os.path.join(calib_root_dir, 'calib_cam_to_cam.txt'))
        velo2cam = self.read_calib_file(os.path.join(calib_root_dir, 'calib_velo_to_cam.txt'))
        Tr_velo_to_cam = np.zeros((3,4))
        Tr_velo_to_cam[0:3,0:3] = np.reshape(velo2cam['R'], [3,3])
        Tr_velo_to_cam[:,3] = velo2cam['T']
        data['Tr_velo_to_cam'] = np.reshape(Tr_velo_to_cam, [12])
        data['R0_rect'] = cam2cam['R_rect_00']
        data['P2'] = cam2cam['P_rect_02']
        return data

    def cart2hom(self, pts_3d):
        ''' Input: nx3 points in Cartesian
            Oupput: nx4 points in Homogeneous by appending 1
        '''
        n = pts_3d.shape[0]
        pts_3d_hom = np.hstack((pts_3d, np.ones((n,1))))
        return pts_3d_hom
 
    def cart2hom_torch(self, pts_3d):
        n = pts_3d.size()[0]
        pts_3d_hom = torch.cat((pts_3d, torch.ones(n,1).to("cuda:0")), 1)
        return pts_3d_hom

    # =========================== 
    # ------- 3d to 3d ---------- 
    # =========================== 
    def project_velo_to_ref(self, pts_3d_velo):
        pts_3d_velo = self.cart2hom(pts_3d_velo) # nx4
        return np.dot(pts_3d_velo, np.transpose(self.V2C))

    def project_ref_to_velo(self, pts_3d_ref):
        pts_3d_ref = self.cart2hom(pts_3d_ref) # nx4
        return np.dot(pts_3d_ref, np.transpose(self.C2V))

    def project_rect_to_ref(self, pts_3d_rect):
        ''' Input and Output are nx3 points '''
        return np.transpose(np.dot(np.linalg.inv(self.R0), np.transpose(pts_3d_rect)))
    
    def project_ref_to_rect(self, pts_3d_ref):
        ''' Input and Output are nx3 points '''
        return np.transpose(np.dot(self.R0, np.transpose(pts_3d_ref)))

    def project_ref_to_rect_torch(self, pts_3d_ref):
        ''' Input and Output are nx3 points '''
        return torch.transpose(torch.matmul(self.R0_torch, torch.transpose(pts_3d_ref,0,1)),0,1)
 
    def project_rect_to_velo(self, pts_3d_rect):
        ''' Input: nx3 points in rect camera coord.
            Output: nx3 points in velodyne coord.
        ''' 
        pts_3d_ref = self.project_rect_to_ref(pts_3d_rect)
        return self.project_ref_to_velo(pts_3d_ref)

    def project_velo_to_rect(self, pts_3d_velo):
        pts_3d_ref = self.project_velo_to_ref(pts_3d_velo)
        return self.project_ref_to_rect(pts_3d_ref)

    # =========================== 
    # ------- 3d to 2d ---------- 
    # =========================== 
    def project_rect_to_image(self, pts_3d_rect):
        ''' Input: nx3 points in rect camera coord.
            Output: nx2 points in image2 coord.
        '''
        pts_3d_rect = self.cart2hom(pts_3d_rect)
        pts_2d = np.dot(pts_3d_rect, np.transpose(self.P)) # nx3
        pts_2d[:,0] /= pts_2d[:,2]
        pts_2d[:,1] /= pts_2d[:,2]
        return pts_2d[:,0:2]

    def project_rect_to_image_torch(self, pts_3d_rect):
        ''' Input: nx3 points in rect camera coord.
            Output: nx2 points in image2 coord.
        '''
        pts_3d_rect = self.cart2hom_torch(pts_3d_rect)
        pts_2d = torch.matmul(pts_3d_rect, torch.transpose(self.P_torch,0,1)) # nx3
        pts_2d[:,0] /= pts_2d[:,2]
        pts_2d[:,1] /= pts_2d[:,2]
        return pts_2d[:,0:2]

    def project_ref_to_image_torch(self, pts_3d_ref):
        ''' Input: nx3 points in ref camera coord.
            Output: nx2 points in image2 coord.
        '''
        pts_3d_ref = self.cart2hom_torch(pts_3d_ref)
        pts_2d = torch.matmul(pts_3d_ref, self.D_torch) # nx3
        pts_2d[:,0] /= pts_2d[:,2]
        pts_2d[:,1] /= pts_2d[:,2]
        return pts_2d[:,0:2]

    def project_velo_to_image(self, pts_3d_velo):
        ''' Input: nx3 points in velodyne coord.
            Output: nx2 points in image2 coord.
        '''
        pts_3d_rect = self.project_velo_to_rect(pts_3d_velo)
        return self.project_rect_to_image(pts_3d_rect)

    # =========================== 
    # ------- 2d to 3d ---------- 
    # =========================== 
    def project_image_to_rect(self, uv_depth):
        ''' Input: nx3 first two channels are uv, 3rd channel
                   is depth in rect camera coord.
            Output: nx3 points in rect camera coord.
        '''
        n = uv_depth.shape[0]
        x = ((uv_depth[:,0]-self.c_u)*uv_depth[:,2])/self.f_u + self.b_x
        y = ((uv_depth[:,1]-self.c_v)*uv_depth[:,2])/self.f_v + self.b_y
        pts_3d_rect = np.zeros((n,3))
        pts_3d_rect[:,0] = x
        pts_3d_rect[:,1] = y
        pts_3d_rect[:,2] = uv_depth[:,2]
        return pts_3d_rect

    def project_image_to_velo(self, uv_depth):
        pts_3d_rect = self.project_image_to_rect(uv_depth)
        return self.project_rect_to_velo(pts_3d_rect)

def rotx(t):
    ''' 3D Rotation about the x-axis. '''
    c = np.cos(t)
    s = np.sin(t)
    return np.array([[1,  0,  0],
                     [0,  c, -s],
                     [0,  s,  c]])


def roty(t):
    ''' Rotation about the y-axis. '''
    c = np.cos(t)
    s = np.sin(t)
    return np.array([[c,  0,  s],
                     [0,  1,  0],
                     [-s, 0,  c]])


def rotz(t):
    ''' Rotation about the z-axis. '''
    c = np.cos(t)
    s = np.sin(t)
    return np.array([[c, -s,  0],
                     [s,  c,  0],
                     [0,  0,  1]])


def transform_from_rot_trans(R, t):
    ''' Transforation matrix from rotation matrix and translation vector. '''
    R = R.reshape(3, 3)
    t = t.reshape(3, 1)
    return np.vstack((np.hstack([R, t]), [0, 0, 0, 1]))


def inverse_rigid_trans(Tr):
    ''' Inverse a rigid body transform matrix (3x4 as [R|t])
        [R'|-R't; 0|1]
    '''
    inv_Tr = np.zeros_like(Tr) # 3x4
    inv_Tr[0:3,0:3] = np.transpose(Tr[0:3,0:3])
    inv_Tr[0:3,3] = np.dot(-np.transpose(Tr[0:3,0:3]), Tr[0:3,3])
    return inv_Tr

def read_label(label_filename):
    lines = [line.rstrip() for line in open(label_filename)]
    objects = [Object3d(line) for line in lines]
    return objects

def load_image(img_filename):
    return cv2.imread(img_filename)

def load_velo_scan(velo_filename):
    scan = np.fromfile(velo_filename, dtype=np.float32)
    scan = scan.reshape((-1, 4))
    return scan

def project_to_image(pts_3d, P):
    ''' Project 3d points to image plane.
    Usage: pts_2d = projectToImage(pts_3d, P)
      input: pts_3d: nx3 matrix
             P:      3x4 projection matrix
      output: pts_2d: nx2 matrix
      P(3x4) dot pts_3d_extended(4xn) = projected_pts_2d(3xn)
      => normalize projected_pts_2d(2xn)
      <=> pts_3d_extended(nx4) dot P'(4x3) = projected_pts_2d(nx3)
          => normalize projected_pts_2d(nx2)
    '''
    n = pts_3d.shape[0]
    pts_3d_extend = np.hstack((pts_3d, np.ones((n,1))))
    print(('pts_3d_extend shape: ', pts_3d_extend.shape))
    pts_2d = np.dot(pts_3d_extend, np.transpose(P)) # nx3
    pts_2d[:,0] /= pts_2d[:,2]
    pts_2d[:,1] /= pts_2d[:,2]
    return pts_2d[:,0:2]


def compute_box_3d(obj, P):
    ''' Takes an object and a projection matrix (P) and projects the 3d
        bounding box into the image plane.
        Returns:
            corners_2d: (8,2) array in left image coord.
            corners_3d: (8,3) array in in rect camera coord.
    '''
    # compute rotational matrix around yaw axis
    R = roty(obj.ry)    

    # 3d bounding box dimensions
    l = obj.l;
    w = obj.w;
    h = obj.h;
    
    # 3d bounding box corners
    x_corners = [l/2,l/2,-l/2,-l/2,l/2,l/2,-l/2,-l/2];
    y_corners = [0,0,0,0,-h,-h,-h,-h];
    z_corners = [w/2,-w/2,-w/2,w/2,w/2,-w/2,-w/2,w/2];
    
    # rotate and translate 3d bounding box
    corners_3d = np.dot(R, np.vstack([x_corners,y_corners,z_corners]))
    #print corners_3d.shape
    corners_3d[0,:] = corners_3d[0,:] + obj.t[0];
    corners_3d[1,:] = corners_3d[1,:] + obj.t[1];
    corners_3d[2,:] = corners_3d[2,:] + obj.t[2];
    #print 'cornsers_3d: ', corners_3d 
    # only draw 3d bounding box for objs in front of the camera
    if np.any(corners_3d[2,:]<0.1):
        corners_2d = None
        return corners_2d, np.transpose(corners_3d)
    
    # project the 3d bounding box into the image plane
    corners_2d = project_to_image(np.transpose(corners_3d), P);
    #print 'corners_2d: ', corners_2d
    return corners_2d, np.transpose(corners_3d)


def compute_orientation_3d(obj, P):
    ''' Takes an object and a projection matrix (P) and projects the 3d
        object orientation vector into the image plane.
        Returns:
            orientation_2d: (2,2) array in left image coord.
            orientation_3d: (2,3) array in in rect camera coord.
    '''
    
    # compute rotational matrix around yaw axis
    R = roty(obj.ry)
   
    # orientation in object coordinate system
    orientation_3d = np.array([[0.0, obj.l],[0,0],[0,0]])
    
    # rotate and translate in camera coordinate system, project in image
    orientation_3d = np.dot(R, orientation_3d)
    orientation_3d[0,:] = orientation_3d[0,:] + obj.t[0]
    orientation_3d[1,:] = orientation_3d[1,:] + obj.t[1]
    orientation_3d[2,:] = orientation_3d[2,:] + obj.t[2]
    
    # vector behind image plane?
    if np.any(orientation_3d[2,:]<0.1):
      orientation_2d = None
      return orientation_2d, np.transpose(orientation_3d)
    
    # project orientation into the image plane
    orientation_2d = project_to_image(np.transpose(orientation_3d), P);
    return orientation_2d, np.transpose(orientation_3d)

def draw_projected_box3d(image, qs, color=(255,255,255), thickness=2):
    ''' Draw 3d bounding box in image
        qs: (8,3) array of vertices for the 3d box in following order:
            1 -------- 0
           /|         /|
          2 -------- 3 .
          | |        | |
          . 5 -------- 4
          |/         |/
          6 -------- 7
    '''
    qs = qs.astype(np.int32)
    for k in range(0,4):
       # Ref: http://docs.enthought.com/mayavi/mayavi/auto/mlab_helper_functions.html
       i,j=k,(k+1)%4
       # use LINE_AA for opencv3
       cv2.line(image, (qs[i,0],qs[i,1]), (qs[j,0],qs[j,1]), color, thickness, cv2.CV_AA)

       i,j=k+4,(k+1)%4 + 4
       cv2.line(image, (qs[i,0],qs[i,1]), (qs[j,0],qs[j,1]), color, thickness, cv2.CV_AA)

       i,j=k,k+4
       cv2.line(image, (qs[i,0],qs[i,1]), (qs[j,0],qs[j,1]), color, thickness, cv2.CV_AA)
    return image



class OmniCalibration(Calibration):
    def __init__(self, calib_folder):

        global_config = os.path.join(calib_folder, 'defaults.yaml')
        camera_config = os.path.join(calib_folder, 'cameras.yaml')

        with open(global_config) as f:
            self.global_config_dict = yaml.safe_load(f)
        
        with open(camera_config) as f:
            self.camera_config_dict = yaml.safe_load(f)
        
        self.median_focal_length_y = self.calculate_median_param_value(param = 'f_y')
        self.median_optical_center_y = self.calculate_median_param_value(param = 't_y')
        # image shape is (color channels, height, width)
        self.img_shape = 3, self.global_config_dict['image']['height'], self.global_config_dict['image']['width']
    
    def project_ref_to_image_torch(self, pointcloud):

        theta = (torch.atan2(pointcloud[:, 0], pointcloud[:, 2]) + np.pi) %(2*np.pi)
        horizontal_fraction = theta/ (2*np.pi)
        x = (horizontal_fraction * self.img_shape[2]) % self.img_shape[2]
        y = -self.median_focal_length_y*(pointcloud[:, 1]*torch.cos(theta)/pointcloud[:, 2]) + self.median_optical_center_y
        pts_2d = torch.stack([x, y], dim=1)
        
        return pts_2d


    def project_image_to_rect(self, uvdepth):

        theta = (uvdepth[:, 0]/self.img_shape[2])*2*np.pi - np.pi
        z = uvdepth[:, 2]*np.cos(theta)
        x = uvdepth[:, 2]*np.sin(theta)
        y = z*-1*(uvdepth[:, 1] - self.median_optical_center_y)/(self.median_focal_length_y * np.cos(theta))

        return np.stack([x,y,z], axis=1)

    def project_velo_to_ref(self, pointcloud):

        pointcloud = pointcloud[:, [1, 2, 0]]
        pointcloud[:, 0] *= -1
        pointcloud[:, 1] *= -1

        return pointcloud

    def move_lidar_to_camera_frame(self, pointcloud, upper = True):
        # assumed only rotation about z axis
        
        if upper:
            pointcloud -= self.global_config_dict['lidar_upper_to_rgb']['translation']
            theta = self.global_config_dict['lidar_upper_to_rgb']['rotation'][-1]
        else:
            pointcloud -= self.global_config_dict['lidar_lower_to_rgb']['translation']
            theta = self.global_config_dict['lidar_lower_to_rgb']['rotation'][-1]

        rotation_matrix = torch.Tensor([[np.cos(theta), np.sin(theta)], [-np.sin(theta), np.cos(theta)]]).type(pointcloud.type())
        pointcloud[:, :2] = torch.matmul(rotation_matrix.unsqueeze(0), pointcloud[:, :2].transpose(0,1)).transpose(0,1)
        return pointcloud
        
    
    def calculate_median_param_value(self, param):
        if param=='f_y':
            idx = 4
        elif param == 'f_x':
            idx = 0
        elif param == 't_y':
            idx = 5
        elif param == 't_x':
            idx = 2
        elif param == 's':
            idx = 1
        else:
            raise 'Wrong parameter!'

        omni_camera = ['sensor_0', 'sensor_2', 'sensor_4', 'sensor_6', 'sensor_8']
        parameter_list = []
        for sensor, camera_params in self.camera_config_dict['cameras'].items():
            if sensor not in omni_camera:
                continue
            K_matrix = camera_params['K'].split(' ')
            parameter_list.append(float(K_matrix[idx]))
        return np.median(parameter_list)


================================================
FILE: paper_experiments/utils/combine_and_process_detections.py
================================================
import os
from os import listdir
from os.path import isfile, join

#root = "/cvgl2/u/mihirp/depth_tracking/data/JRDB/sequences/"
#root = "/cvgl2/u/mihirp/depth_tracking/data/JRDB/test_sequences/"
#root = "/cvgl2/u/mihirp/depth_tracking/data/KITTI/sequences/"
root = "/cvgl2/u/mihirp/depth_tracking/data/KITTI/test_sequences/"

file_name = "new_subcnn_faster_rcnn"
# file_name = "detectron2_x101"

def threshold(filename, thresh, min, max):
  detections = []
  with open(filename, 'r') as readfile:
    dets = readfile.read().split('\n')
    dets = dets[:len(dets)-1] #filter out last line which is just \n
    for det in dets:
      parsedet = det.split(' ')
      score = float(parsedet[len(parsedet)-1])
      parsedet[len(parsedet)-1] = str((float(parsedet[len(parsedet)-1]) - thresh) / (max - thresh))
      if(score > thresh):
        detections.append(parsedet)
  return detections

for seq in sorted(os.listdir(root)): #21 for normal, 29 for testing
  path = os.path.join(root,seq,'det')

  with open(os.path.join(path,file_name+'_raw.txt'), 'w') as f:
    pred_dets = []
    #pred_dets.append(threshold(os.path.join(path,'rrc.txt'), .05, 0, 1))
    pred_dets.append(threshold(os.path.join(path,'subcnn.txt'), .8, 0, 1))
    #pred_dets.append(threshold(os.path.join(path,'faster_rcnn.txt'), .99, 0, 1))
    #pred_dets.append(threshold(os.path.join(path,'detectron2_x101.txt'), .9, 0, 1))
    #pred_dets.append(threshold(path+'regionlets.txt', 5, -5, 25))
    if len(pred_dets[0]) == 0:
      continue
    max_frames = int((pred_dets[0])[len(pred_dets[0])-1][0])

    det_ctrs = [0,0,0,0]
    for frame in range(max_frames+1):
      frame_num = 0
      for j in range(1): #TODO: Update to number of detectors used
        while det_ctrs[j] < len(pred_dets[j]) and int( (pred_dets[j])[det_ctrs[j]][0]) == frame:
          (pred_dets[j])[det_ctrs[j]][1] = str(frame_num)
          frame_num+=1
          f.write( " ".join( (pred_dets[j])[det_ctrs[j]] )+'\n')
          det_ctrs[j]+=1

  # Counts max/min of scores
  for ctr, pred_det in enumerate(pred_dets):
    minval = 1000
    maxval = 0
    for detection in pred_det:
      score = detection[len(detection)-1]
      if float(score)>maxval:
        maxval = float(score)
      if float(score)<minval:
        minval = float(score)
    # print("Detector: "+str(ctr)+" Max: "+str(maxval))
    # print("Detector: "+str(ctr)+" Min: "+str(minval))

  with open(os.path.join(path,file_name+'_raw.txt'), 'r') as f:
    lines = f.readlines()

  with open(os.path.join(path, file_name+'_car.txt'), 'w') as fcar:
    with open(os.path.join(path, file_name+'_ped.txt'), 'w') as fped:
      for line in lines:
        if len(line) < 5:
          continue
        vals = line.split(' ')
        min_x = float(vals[6])
        min_y = float(vals[7])
        max_x = float(vals[8])
        max_y = float(vals[9])
        score = vals[-1]
        out_line = vals[0]+',0,'+str(min_x)+','+str(min_y)+','+str(max_x-min_x)+','+str(max_y-min_y)+','+str(score)
        if vals[2] == 'Car':
          fcar.write(out_line)
        elif vals[2] == 'Pedestrian':
          fped.write(out_line)


================================================
FILE: paper_experiments/utils/dataset.py
================================================
import glob
import os
import pdb
import random
import sys
from itertools import compress

import numpy as np
import torch
import torchvision.transforms as transforms

from PIL import Image
from skimage.transform import resize
from torch.utils.data import Dataset
from tqdm import tqdm

from models.pointnet_model import PointNet
from .calibration import Calibration, OmniCalibration
from .read_detections import (read_ground_truth_2d_detections,
                              read_ground_truth_3d_detections)


class SequenceDataset(Dataset):
    def __init__(self, folder_path, point_cloud=False, cuda=False, omni=False):

        self.files = sorted(glob.glob('%s/imgs/*.*' % folder_path), key = lambda x: int(os.path.splitext(os.path.basename(x))[0]))
        self.files = [file for file in self.files if is_image_file(file)]
        self.point_cloud = point_cloud
        self.seq_name = os.path.split(folder_path)[-1]
        self.omni = omni
        if point_cloud:
            if self.omni:
                calib_folder = os.path.join(folder_path, 'calib')
                self.calib = OmniCalibration(calib_folder)
            else:
                self.calib_file = os.path.join(folder_path, 'calib', self.seq_name+'.txt')
                self.calib = Calibration(self.calib_file)
            self.depth_files = sorted(glob.glob('%s/*.*' % os.path.join(folder_path, 'depth')))
            self.depth_files = [file for file in self.depth_files if file.split('.')[-1]=='bin']
        else:
            self.calib = None
        self.cuda = cuda

    def __getitem__(self, index):


        img_path = self.files[index % len(self.files)]
        if self.point_cloud:
            depth_path = self.depth_files[index % len(self.depth_files)]
        # Extract image
        img = np.array(Image.open(img_path))

        # Channels-first
        input_img = np.transpose(img, (2, 0, 1))/255
        # As pytorch tensor
        input_img = torch.from_numpy(input_img).float()
        if self.cuda:
            input_img = input_img.cuda()
        frame_idx = int(os.path.basename(img_path)[:-4])
        if self.point_cloud:
            #velodyne coordinates and image coordinates are different.
            #velo_x = camera_z
            #velo_y = -camera_x
            #velo_z = -camera_y
            if self.omni:
                scan = np.load(depth_path)
            else:
                scan = np.fromfile(depth_path, dtype=np.float32)
            scan = scan.reshape((-1, 4))
            scan[:, :3] = self.calib.project_velo_to_ref(scan[:, :3])
            return frame_idx, img_path, input_img, scan
        else:
            return frame_idx, img_path, input_img, -1

    def __len__(self):
        return len(self.files)

def is_image_file(file):
    IMG_FILE_FORMATS = ['jpg', 'png', 'tif', 'bmp', 'jpeg']
    if file.split('.')[-1] in IMG_FILE_FORMATS:
        return True
    else:
        return False

class TripletDataset(Dataset):
    
    def __init__(self, feature_path, num_negative_samples = 100, cuda = True, sequence = False, test = False):
        if test:
            feature_file = os.path.join(feature_path, 'test_features.npy')
        else:
            feature_file = os.path.join(feature_path, 'features.npy')
        
        feature_array = np.load(feature_file)

        # feature_array = feature_array[:500]
        # feature_array = np.vstack([feature_array[146], feature_array[148], feature_array[149],feature_array[32], feature_array[10], feature_array[7],feature_array[9],feature_array[31], feature_array[8]])
        # feature_array = np.vstack([feature_array[10], feature_array[11],feature_array[9],feature_array[8],feature_array[249],feature_array[247]])
        # self.ids = feature_array[:, 0]
        # if not test:
        #     feature_array = feature_array[self.ids < 5]
        self.ids = feature_array[:, 0].astype(np.float32).astype(np.int32)
        self.unique_ids = np.unique(self.ids)
        self.frames = feature_array[:, 2].astype(np.float32).astype(np.int32)
        self.features = feature_array[:, 3:].astype(np.float32)
        self.sequences = feature_array[:, 1].astype(np.float32).astype(np.int32)
        self.sequence = sequence
        if self.sequence:
            self.size = self.unique_ids.size
        else:
            self.size = self.ids.size
        self.num_negative_samples = num_negative_samples
        self.tensor_type = torch.cuda.FloatTensor if cuda else torch.FloatTensor


    def __getitem__(self, index):
        
        if self.sequence:
            object_id = self.unique_ids[index]
            positive_ids = self.ids == object_id
            object_sequence = self.sequences[positive_ids][0]
            object_frames = self.frames[positive_ids]

            positive_sequence = self.features[positive_ids]
            positive_sequence = torch.Tensor(positive_sequence).type(self.tensor_type)
            negative_sequence = []
            for frame in object_frames[1:]:
                idx = np.logical_and(self.sequences==object_sequence, self.frames==frame)
                idx = np.logical_and(idx, self.ids!=object_id)
                if np.sum(idx)==0:
                    negative_sequence.append(None)
                else:
                    negative_sequence.append(torch.Tensor(self.features[idx]).type(self.tensor_type))
            negative_ids = np.random.choice(len(self.ids), size = self.num_negative_samples, replace = False)
            negative_ids = negative_ids[self.ids[negative_ids] != object_id]
            negative_features = self.features[negative_ids]
            negative_features = torch.Tensor(negative_features).type(self.tensor_type)
            
            return positive_sequence, negative_sequence, negative_features
        else:
            object_id = self.ids[index]
            anchor_feature = self.features[index]
            anchor_feature = torch.Tensor(anchor_feature).type(self.tensor_type)

            positive_ids = np.where(self.ids == object_id)[0]
            positive_feature = self.features[random.choice(positive_ids)]
            positive_feature = torch.Tensor(positive_feature).type(self.tensor_type)

            negative_ids = np.random.choice(len(self.ids), size = self.num_negative_samples, replace = False)
            negative_ids = negative_ids[self.ids[negative_ids] != object_id]
            negative_features = self.features[negative_ids]
            negative_features = torch.Tensor(negative_features).type(self.tensor_type)


            return anchor_feature, positive_feature, negative_features


    def __len__(self):
        return self.size

class STIPDataset(Dataset):
    def __init__(self, folder_path, img_size=416, point_cloud = False, pad = False):

        self.files = sorted(glob.glob('%s/imgs/*/*.*' % folder_path), key = lambda x: int(os.path.splitext(os.path.basename(x))[0]))
        self.files = [file for file in self.files if is_image_file(file)]
        self.img_shape = (img_size, img_size)
        self.pad = pad
        self.seq_name = os.path.split(folder_path)[-1]

    def __getitem__(self, index):


        img_path = self.files[index % len(self.files)]

        # Extract image
        img = np.array(Image.open(img_path))
        h, w, _ = img.shape
        dim_diff = np.abs(h - w)
        # Upper (left) and lower (right) padding
        pad1, pad2 = dim_diff // 2, dim_diff - dim_diff // 2
        # Determine padding
        pad = ((pad1, pad2), (0, 0), (0, 0)) if h <= w else ((0, 0), (pad1, pad2), (0, 0))
        # Add padding
        if self.pad:
            img = np.pad(img, pad, 'constant', constant_values=127.5) / 255.
            # Resize and normalize
            img = resize(img, (*self.img_shape, 3), mode='reflect', anti_aliasing = True)
        # Channels-first
        input_img = np.transpose(img, (2, 0, 1))/255
        # As pytorch tensor
        input_img = torch.from_numpy(input_img).float()

        return img_path, input_img, -1

    def __len__(self):
        return len(self.files)

def collate_fn(inputs):
    #ASSUMES BATCH SIZE IS ALWAYS 1
    return inputs[0]

================================================
FILE: paper_experiments/utils/deep_sort_utils.py
================================================
# vim: expandtab:ts=4:sw=4
import numpy as np
import cv2


def non_max_suppression(boxes, max_bbox_overlap, scores=None):
    """Suppress overlapping detections.

    Original code from [1]_ has been adapted to include confidence score.

    .. [1] http://www.pyimagesearch.com/2015/02/16/
           faster-non-maximum-suppression-python/

    Examples
    --------

        >>> boxes = [d.roi for d in detections]
        >>> scores = [d.confidence for d in detections]
        >>> indices = non_max_suppression(boxes, max_bbox_overlap, scores)
        >>> detections = [detections[i] for i in indices]

    Parameters
    ----------
    boxes : ndarray
        Array of ROIs (x, y, width, height).
    max_bbox_overlap : float
        ROIs that overlap more than this values are suppressed.
    scores : Optional[array_like]
        Detector confidence score.

    Returns
    -------
    List[int]
        Returns indices of detections that have survived non-maxima suppression.

    """
    if len(boxes) == 0:
        return []

    boxes = boxes.astype(np.float)
    pick = []

    x1 = boxes[:, 0]
    y1 = boxes[:, 1]
    x2 = boxes[:, 2] + boxes[:, 0]
    y2 = boxes[:, 3] + boxes[:, 1]

    area = (x2 - x1 + 1) * (y2 - y1 + 1)
    if scores is not None:
        idxs = np.argsort(scores)
    else:
        idxs = np.argsort(y2)

    while len(idxs) > 0:
        last = len(idxs) - 1
        i = idxs[last]
        pick.append(i)

        xx1 = np.maximum(x1[i], x1[idxs[:last]])
        yy1 = np.maximum(y1[i], y1[idxs[:last]])
        xx2 = np.minimum(x2[i], x2[idxs[:last]])
        yy2 = np.minimum(y2[i], y2[idxs[:last]])

        w = np.maximum(0, xx2 - xx1 + 1)
        h = np.maximum(0, yy2 - yy1 + 1)

        #overlap = (w * h) / (area[idxs[:last]]) # + area[idxs[last:last+1]] - w * h) #changed from deepsort to sum both areas
        overlap = (w * h) / (area[idxs[:last]] + area[idxs[last:last+1]] - w * h) #changed from deepsort to sum both areas
        threshold = np.where(y2[i]-y1[i] < 50, max_bbox_overlap-0.1, max_bbox_overlap)
        idxs = np.delete(
            idxs, np.concatenate(
                ([last], np.where(overlap > threshold)[0])))

    return pick


================================================
FILE: paper_experiments/utils/detection.py
================================================
# vim: expandtab:ts=4:sw=4
import numpy as np


class Detection(object):
    """
    This class represents a bounding box detection in a single image.

    Parameters
    ----------
    tlwh : array_like
        Bounding box in format `(x, y, w, h)`.
    confidence : float
        Detector confidence score.
    feature : array_like
        A feature vector that describes the object contained in this image.

    Attributes
    ----------
    tlwh : ndarray
        Bounding box in format `(top left x, top left y, width, height)`.
    confidence : ndarray
        Detector confidence score.
    feature : ndarray | NoneType
        A feature vector that describes the object contained in this image.

    """

    def __init__(self, tlwh, box_3d, confidence, appearance_feature, feature):
        self.tlwh = np.asarray(tlwh, dtype=np.float)
        # Note that detections format is centre of 3D box and dimensions (not bottom face)
        self.box_3d = box_3d
        if box_3d is not None:
            self.box_3d[1] -= box_3d[4]/2
            self.box_3d = np.asarray(box_3d, dtype=np.float32)
        self.confidence = float(confidence)
        self.appearance_feature = np.asarray(appearance_feature, dtype=np.float32)
        if feature is not None:
            self.feature = np.asarray(feature, dtype = np.float32)
        else:
            self.feature = None


    def to_tlbr(self):
        """Convert bounding box to format `(min x, min y, max x, max y)`, i.e.,
        `(top left, bottom right)`.
        """
        ret = self.tlwh.copy()
        ret[2:] += ret[:2]
        return ret

    def to_xyah(self):
        """Convert bounding box to format `(center x, center y, aspect ratio,
        height)`, where the aspect ratio is `width / height`.
        """
        ret = self.tlwh.copy()
        ret[:2] += ret[2:] / 2
        ret[2] /= ret[3]
        return ret
    def to_xywh(self):
        """Convert bounding box to format `(center x, center y, aspect ratio,
        height)`, where the aspect ratio is `width / height`.
        """
        ret = self.tlwh.copy()
        ret[:2] += ret[2:] / 2
        return ret
    def get_3d_distance(self):
        if self.box_3d is not None:
            return np.sqrt(self.box_3d[0]**2 + self.box_3d[2]**2)

================================================
FILE: paper_experiments/utils/double_measurement_kf.py
================================================
import random
import numpy as np
import scipy.linalg
import EKF
import pdb
import kf_2d
import os
import pickle
import torch
from copy import deepcopy
import matplotlib.pyplot as plt
from read_detections import read_ground_truth_3d_detections, read_ground_truth_2d_detections
np.set_printoptions(precision=4, suppress=True)
from calibration import Calibration
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from evaluation.distances import iou_matrix

class KF_3D(kf_2d.KalmanFilter2D):
    """
    3D Kalman Filter that tracks objets in 3D space

        The 8-dimensional state space

            x, y, z, l, h, w, theta, vx, vz

        contains the bounding box center position (x, z), the heading angle theta, the
        box dimensions l, w, h, and the x and z velocities.

        Object motion follows a constant velocity model. The bounding box location
        (x, y) is taken as direct observation of the state space (linear
        observation model).
    """
    def __init__(self, calib, pos_weight_3d, pos_weight, velocity_weight, theta_weight, 
                    std_process, std_measurement_2d, std_measurement_3d, 
                    initial_uncertainty, omni = True, debug=True):
        self.ndim, self.dt = 9, 1.

        # Create Kalman filter model matrices.
        # Motion model is constant velocity, i.e. x = x + Vx*dt
        self._motion_mat = np.eye(self.ndim, self.ndim)
        self._motion_mat[0, 7] = self.dt
        self._motion_mat[2, 8] = self.dt
        # Sensor model is direct observation, i.e. x = x
        self._observation_mat = np.eye(self.ndim - 2, self.ndim)
        if omni:
            self.x_constant = calib.img_shape[2]/(2*np.pi)
            self.y_constant = calib.median_focal_length_y
            self.calib = calib
        else:
            self.projection_matrix = calib.P

        self.omni = omni
        self._std_weight_pos_3d = pos_weight_3d
        self._std_weight_pos = pos_weight
        self._std_weight_vel = velocity_weight
        self._std_weight_theta= theta_weight

        self._std_weight_process = std_process
        self._initial_uncertainty = initial_uncertainty
        self._std_weight_measurement_2d = std_measurement_2d
        self._std_weight_measurement_3d = std_measurement_3d
        self.debug = debug

    def initiate(self, measurement_3d):

        mean_pos = measurement_3d
        mean_vel = np.zeros((2,))
        mean = np.r_[mean_pos, mean_vel]
        std = [
                self._std_weight_pos_3d * measurement_3d[0],
                self._std_weight_pos_3d * measurement_3d[1],
                self._std_weight_pos_3d * measurement_3d[2],
                self._std_weight_pos_3d * measurement_3d[3],
                self._std_weight_pos_3d * measurement_3d[4],
                self._std_weight_pos_3d * measurement_3d[5],
                self._std_weight_theta,
                self._std_weight_vel,
                self._std_weight_vel]
        covariance = np.diag(np.square(std))*(self._initial_uncertainty*self._std_weight_process)**2
        
        return mean, covariance
        
    def get_process_noise(self, mean):
        std_pos = [
            self._std_weight_pos_3d, # x
            self._std_weight_pos_3d, # y
            self._std_weight_pos_3d, # z
            self._std_weight_pos_3d, # l
            self._std_weight_pos_3d, # h            
            self._std_weight_pos_3d, # w
            self._std_weight_theta # theta
            ]
        std_vel = [
            self._std_weight_vel, # x
            self._std_weight_vel, # z
            ]
        self._motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))
        motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))*self._std_weight_process**2
        return motion_cov
    
    def get_2d_measurement_noise(self, measurement_2d):
        # Returns Qt the sensor noise covariance
                
        # Measurement uncertainty scaled by estimated height
        std = [
                self._std_weight_pos*measurement_2d[2],
                self._std_weight_pos*measurement_2d[3],
                self._std_weight_pos*measurement_2d[2],
                self._std_weight_pos*measurement_2d[3]]
        innovation_cov = np.diag(np.square(std))*self._std_weight_measurement_2d**2
        return innovation_cov
    
    def get_3d_measurement_noise(self, measurement):
        # Returns Qt the sensor noise covariance
                
        # Measurement uncertainty scaled by estimated height
        std = [
            self._std_weight_pos_3d * measurement[0], # x
            self._std_weight_pos_3d * measurement[1], # y
            self._std_weight_pos_3d * measurement[2], # z
            self._std_weight_pos_3d * measurement[3], # l
            self._std_weight_pos_3d * measurement[4], # h
            self._std_weight_pos_3d * measurement[5], # w
            self._std_weight_theta # theta
            ]
        innovation_cov = np.diag(np.square(std))*self._std_weight_measurement_3d**2
        return innovation_cov
    
    def gating_distance(self, mean, covariance, measurements,
                        only_position=False,
                        use_3d=True):
        """Compute gating distance between state distribution and measurements.

        A suitable distance threshold can be obtained from `chi2inv95`. If
        `only_position` is False, the chi-square distribution has 4 degrees of
        freedom, otherwise 2.

        Parameters
        ----------
        mean : ndarray
            Mean vector over the state distribution (8 dimensional).
        covariance : ndarray
            Covariance of the state distribution (8x8 dimensional).
        measurements : ndarray
            An Nx4 dimensional matrix of N measurements, each in
            format (x, y, a, h) where (x, y) is the bounding box center
            position, a the aspect ratio, and h the height.
        only_position : Optional[bool]
            If True, distance computation is done with respect to the bounding
            box center position only.

        Returns
        -------
        ndarray
            Returns an array of length N, where the i-th element contains the
            squared Mahalanobis distance between (mean, covariance) and
            `measurements[i]`.

        """
        if not use_3d:
            corner_points, corner_points_3d = self.calculate_corners(mean)
            H_2d = self.get_2d_measurement_matrix(mean, corner_points, corner_points_3d)
            min_x, min_y = np.amin(corner_points, axis = 0)[:2]
            max_x, max_y = np.amax(corner_points, axis = 0)[:2]
            cov = self.project_cov_2d(mean, covariance, H_2d)
            mean = np.array([min_x, min_y, max_x - min_x, max_y - min_y])
        else:
            mean, cov = mean[:7], covariance[:7, :7]
        if only_position:
            if use_3d:
                mean, cov = mean[:3], cov[:3, :3]
                measurements = measurements[:, :3]
            else:
                mean, cov = mean[:2], cov[:2, :2]
                measurements = measurements[:, :2]
        return EKF.squared_mahalanobis_distance(mean, cov, measurements)

    def project_cov(self, mean, covariance):
        # Returns S the innovation covariance (projected covariance)
                
        measurement_noise = self.get_3d_measurement_noise(mean)
        innovation_cov = (np.linalg.multi_dot((self._observation_mat, covariance,
                                          self._observation_mat.T))
                     + measurement_noise)
        return innovation_cov

    def project_cov_2d(self, mean, covariance, H_2d):
        # Returns S the innovation covariance (projected covariance)
                
        measurement_noise = self.get_2d_measurement_noise(mean)
        innovation_cov = (np.linalg.multi_dot((H_2d, covariance,
                                          H_2d.T))
                     + measurement_noise)
        return innovation_cov
    # @profile
    def update(self, mean, covariance, measurement_2d, measurement_3d = None, marginalization=None, JPDA=False):
        """Run Kalman filter correction step.

        Parameters
        ----------
        mean : ndarray
            The predicted state's mean vector (9 dimensional).
        covariance : ndarray
            The state's covariance matrix (9x9 dimensional).
        measurement_2d : ndarray
            The 4 dimensional measurement vector (x, y, w, h), where (x, y)
            is the center position, a the aspect ratio, and h the height of the
            bounding box.
        measurement_3d : ndarray
            The 7 dimensional measurement vector (x, y, z, l, h, w, theta), where (x, y, z)
            is the center bottom of the box, l, q, h are the dimensions of the bounding box
            theta is the orientation angle w.r.t. the positive x axis.
        Returns
        -------
        (ndarray, ndarray)
            Returns the measurement-corrected state distribution.

        """

        if np.any(np.isnan(mean)):
            return mean, covariance
        out_cov = covariance
        H_3d = self._observation_mat
        do_3d = True
        covariance_3d = None
        for meas in measurement_3d:
            if meas is None:
                do_3d = False
                break
        if do_3d:
            S_matrix = self.project_cov(mean, out_cov)
            try:
                chol_factor, lower = scipy.linalg.cho_factor(
                    S_matrix, lower=True, check_finite=False)
                kalman_gain = scipy.linalg.cho_solve(
                    (chol_factor, lower), np.dot(out_cov, H_3d.T).T,
                    check_finite=False).T
            except:
                # in case cholesky factorization fails, revert to standard solver
                kalman_gain = np.linalg.multi_dot((out_cov, H_3d.T, np.linalg.inv(S_matrix)))
            out_cov -= np.linalg.multi_dot((kalman_gain, S_matrix, kalman_gain.T))
            if JPDA:
                innovation_3d = 0
                cov_uncertainty_3d = 0
                for i, detection_3d in enumerate(measurement_3d):
                    innovation_partial = detection_3d - mean[:7]
                    innovation_3d += innovation_partial * marginalization[i+1]
                    cov_uncertainty_3d += marginalization[i+1] * np.outer(innovation_partial, innovation_partial)
                partial_cov = cov_uncertainty_3d-np.outer(innovation_3d, innovation_3d)
                out_cov *= 1 - marginalization[0]
                out_cov += np.linalg.multi_dot((kalman_gain, partial_cov, kalman_gain.T))
                out_cov += marginalization[0]*covariance
            else:
                out_cov = out_cov - np.linalg.multi_dot((kalman_gain, H_3d, out_cov))
                innovation_3d = measurement_3d - mean[:7]
            mean = mean + np.dot(kalman_gain, innovation_3d)
            post_3d_mean = mean
            covariance_3d = out_cov

        if measurement_2d is not None:
            corner_points, corner_points_3d = self.calculate_corners(mean)
            H_2d = self.get_2d_measurement_matrix(mean, corner_points, corner_points_3d)
            #update based on 2D
            min_x, min_y = np.amin(corner_points, axis = 0)[:2]
            max_x, max_y = np.amax(corner_points, axis = 0)[:2]
            S_matrix = self.project_cov_2d(np.array([min_x, min_y, max_x - min_x, max_y - min_y]), out_cov, H_2d)
            try:
                chol_factor, lower = scipy.linalg.cho_factor(
                    S_matrix, lower=True, check_finite=False)
                kalman_gain = scipy.linalg.cho_solve(
                    (chol_factor, lower), np.dot(out_cov, H_2d.T).T,
                    check_finite=False).T
            except:
                # in case cholesky factorization fails, revert to standard solver
                kalman_gain = np.linalg.multi_dot((out_cov, H_2d.T, np.linalg.inv(S_matrix)))
            out_cov = np.dot(np.eye(*out_cov.shape)-np.dot(kalman_gain, H_2d), out_cov)
            if JPDA:
                innovation_2d = 0
                cov_uncertainty_2d = 0
                for i, detection_2d in enumerate(measurement_2d):
                    innovation_partial = detection_2d[:4] - np.array([min_x, min_y, max_x - min_x, max_y - min_y])
                    innovation_2d += innovation_partial * marginalization[i+1] # +1 to account for dummy node
                    cov_uncertainty_2d += marginalization[i+1] * np.outer(innovation_partial, innovation_partial)
                partial_cov = cov_uncertainty_2d-np.outer(innovation_2d, innovation_2d)
                out_cov *= 1 - marginalization[0]
                out_cov += np.linalg.multi_dot((kalman_gain, partial_cov, kalman_gain.T))
                if covariance_3d is None:
                    out_cov += marginalization[0]*covariance
                else:
                    out_cov += marginalization[0]*covariance_3d                    
            else:
                innovation_2d = measurement_2d[:4] - np.array([min_x, min_y, max_x - min_x, max_y - min_y])
            mean = mean + np.dot(kalman_gain, innovation_2d)
        
        if self.debug:
            return mean, out_cov, post_3d_mean
        return mean, out_cov

    # @profile
    def get_2d_measurement_matrix(self, mean, corner_points, corner_points_3d):

        min_x = np.inf
        min_x_idx = None
        max_x = -np.inf
        max_x_idx = None
        min_y = np.inf
        min_y_idx = None
        max_y = -np.inf
        max_y_idx = None
        for idx, pt in enumerate(corner_points):
            if pt[0] < min_x:
                min_x_idx = idx
                min_x = pt[0]
            if pt[0] > max_x:
                max_x_idx = idx
                max_x = pt[0]
            if pt[1] < min_y:
                min_y_idx = idx
                min_y = pt[1]
            if pt[1] > max_y:
                max_y_idx = idx
                max_y = pt[1]
        if self.omni:
            jac_x = np.dot(self.jacobian_omni(corner_points_3d[min_x_idx])[0], self.corner_jacobian(mean, min_x_idx))
            jac_y = np.dot(self.jacobian_omni(corner_points_3d[min_y_idx])[1], self.corner_jacobian(mean, min_y_idx))
            jac_w = np.dot(self.jacobian_omni(corner_points_3d[max_x_idx])[0], self.corner_jacobian(mean, max_x_idx)) - jac_x
            jac_h = np.dot(self.jacobian_omni(corner_points_3d[max_y_idx])[1], self.corner_jacobian(mean, max_y_idx)) - jac_y
        else:
            jac_x = np.dot(self.jacobian(corner_points_3d[min_x_idx])[0], self.corner_jacobian(mean, min_x_idx))
            jac_y = np.dot(self.jacobian(corner_points_3d[min_y_idx])[1], self.corner_jacobian(mean, min_y_idx))
            jac_w = np.dot(self.jacobian(corner_points_3d[max_x_idx])[0], self.corner_jacobian(mean, max_x_idx)) - jac_x
            jac_h = np.dot(self.jacobian(corner_points_3d[max_y_idx])[1], self.corner_jacobian(mean, max_y_idx)) - jac_y
        jac = np.vstack([jac_x, jac_y, jac_w, jac_h])
        jac = np.hstack([jac, np.zeros((jac.shape[0], 2))])
        return jac 
    # Jacobian for projective transformation
    def jacobian(self, pt_3d):
        den = np.sum(self.projection_matrix[2] * pt_3d)
        dxy = (1 - self.projection_matrix[2] * pt_3d/den) * self.projection_matrix[0:2]/den

        return dxy[:, :3]
    
    def jacobian_omni(self, pt_3d):
        jac = np.zeros((2, 3))
        x, y, z = pt_3d[0], pt_3d[1], pt_3d[2]
        denominator = (x**2 + z**2)
        jac[0, 0] = -self.x_constant*(2*x*(z**2)/denominator)
        jac[0, 0] /= denominator
        jac[0, 2] = self.x_constant*2*z/denominator
        jac[0, 2] *= 1 - (z**2)/denominator

        jac[1, 0] = self.y_constant*x*y/denominator
        jac[1, 1] = -self.y_constant
        jac[1,2] = self.y_constant*z*y/denominator
        jac[1, :] /= np.sqrt(denominator)

        return jac

    def calculate_corners(self, box):
        x,y,z,l,h,w,theta = box[:7]
        pt_3d = []
        x_delta_1 = np.cos(theta)*l/2+np.sin(theta)*w/2
        x_delta_2 = np.cos(theta)*l/2 - np.sin(theta)*w/2
        z_delta_1 = np.sin(theta)*l/2-np.cos(theta)*w/2
        z_delta_2 = np.sin(theta)*l/2+np.cos(theta)*w/2
        pt_3d.append((x+x_delta_1, y + h/2, z+z_delta_1, 1))
        pt_3d.append((x+x_delta_2, y + h/2, z+z_delta_2, 1))
        pt_3d.append((x-x_delta_2, y + h/2, z-z_delta_2, 1))
        pt_3d.append((x-x_delta_1, y + h/2, z-z_delta_1, 1))
        pt_3d.append((x+x_delta_1, y - h/2, z+z_delta_1, 1))
        pt_3d.append((x+x_delta_2, y - h/2, z+z_delta_2, 1))
        pt_3d.append((x-x_delta_2, y - h/2, z-z_delta_2, 1))
        pt_3d.append((x-x_delta_1, y - h/2, z-z_delta_1, 1))
        pts_3d = np.vstack(pt_3d)
        pts_2d = self.project_2d(pts_3d)
        return pts_2d, pts_3d
    
    def corner_jacobian(self, pt_3d, corner_idx):
        _, _, _, l, _, w, theta = pt_3d[:7]
        jac = np.eye(3,7)
        
        jac[1, 4] = 0.5 if corner_idx < 4 else -0.5

        jac[0, 3] = 0.5*np.sin(theta) if corner_idx % 4 < 2 else -0.5*np.sin(theta)
        jac[0, 5] = 0.5*np.cos(theta) if corner_idx % 2 == 0 else -0.5*np.cos(theta)
        
        jac[2, 3] = 0.5*np.cos(theta) if corner_idx%4 < 2 else -0.5*np.cos(theta)
        jac[2, 5] = 0.5*np.sin(theta) if corner_idx%2 == 0 else -0.5*np.sin(theta)

        if corner_idx%4 == 0:
            jac[0, 6] = -np.sin(theta)*l/2 + np.cos(theta)*w/2
            jac[2, 6] = np.cos(theta)*l/2 + np.sin(theta)*w/2
        elif corner_idx%4==1:
            jac[0, 6] = -np.sin(theta)*l/2 - np.cos(theta)*w/2
            jac[2, 6] = np.cos(theta)*l/2 - np.sin(theta)*w/2
        elif corner_idx%4==2:
            jac[0, 6] = +np.sin(theta)*l/2 + np.cos(theta)*w/2
            jac[2, 6] = -np.cos(theta)*l/2 + np.sin(theta)*w/2
        else:
            jac[0, 6] = +np.sin(theta)*l/2 - np.cos(theta)*w/2
            jac[2, 6] = -np.cos(theta)*l/2 - np.sin(theta)*w/2

        return jac

    def project_2d(self, pts_3d):
        if self.omni:
            pts_2d = np.array(self.calib.project_ref_to_image_torch(torch.from_numpy(pts_3d)))
        else:
            pts_2d = np.dot(pts_3d, self.projection_matrix.T)
            pts_2d /= np.expand_dims(pts_2d[:, 2], 1)
        return pts_2d[:, :2]


def swap(detections_3d, iou, idx, swap_prob = 0):
    if random.random() > swap_prob:
        return detections_3d[idx]
    else:
        iou_row = iou[idx]
        iou_row[idx] = -1
        max_idx = np.argmax(iou_row)
        if iou_row[max_idx] > 0.4:
            # print("SWAP")
            return detections_3d[max_idx]
        else:
            return detections_3d[idx]


if __name__ == '__main__':
    seq = '0001'
    gt_path = os.path.join('data','KITTI','sequences', seq, 'gt')
    prob_3d_list = [0.6]
    prob_2d_list = [0.9]
    swap_prob = 0
    std_3d = 0.2
    std_2d = 5
    boxes_3d, ids, frame_3d = read_ground_truth_3d_detections(os.path.join(gt_path, '3d_detections.txt'), None)
    boxes_2d, object_ids, frame_2d = read_ground_truth_2d_detections(os.path.join(gt_path, 'gt.txt'), None, nms_threshold = 1)
    boxes_2d[:,2] -= boxes_2d[:,0]
    boxes_2d[:,3] -= boxes_2d[:,1]
    boxes_3d[:,1] -= boxes_3d[:, 4]/2
    calib = Calibration(os.path.join(os.path.dirname(gt_path), 'calib', seq+'.txt'))
    pos_weight = 0.05
    pos_weight_2d = 0.006
    velocity_weight = 0.0007
    theta_weight = 0.000300
    std_process = 2
    std_measurement_2d = 2.6
    std_measurement_3d = 0.01
    initial_uncertainty = 1
    
    kf = KF_3D(calib, pos_weight, pos_weight_2d, velocity_weight, theta_weight, 
                std_process, std_measurement_2d, std_measurement_3d, 
                initial_uncertainty, omni=False, debug=True)
    final_errors = np.zeros((len(prob_2d_list), len(prob_3d_list)))
    random.seed(14295)
    np.random.seed(14295)
    for idx_3d, prob_3d in enumerate(prob_3d_list):
        for idx_2d, prob_2d in enumerate(prob_2d_list):
            id_means = {idx:[] for idx in np.unique(ids)}
            id_means_2d = {idx:[] for idx in np.unique(ids)}
            id_preds = {idx:[] for idx in np.unique(ids)}
            id_meas = {idx:[] for idx in np.unique(ids)}
            id_errors = {idx:[] for idx in np.unique(ids)}
            for frame in sorted(np.unique(frame_2d)):
                frame_mask = frame_2d==frame
                frame_boxes_2d = boxes_2d[frame_mask]
                frame_boxes_3d = boxes_3d[frame_mask]
                frame_ids = ids[frame_mask]
                iou = 1-iou_matrix(frame_boxes_2d[:,:4], frame_boxes_2d[:,:4], max_iou=10) #output of function is 1 - IoU
                for idx, object_id in enumerate(frame_ids):
                    if frame_boxes_3d[idx][2] > 30:
                        continue
                    noise_2d = np.random.randn(*frame_boxes_2d[idx].shape)*std_2d
                    noise_3d = np.random.randn(*frame_boxes_3d[idx].shape)*std_3d
                    if len(id_means[object_id.item()]) == 0:
                        mean, cov = kf.initiate(frame_boxes_2d[idx]+noise_2d, frame_boxes_3d[idx]+noise_3d)
                        id_means[object_id.item()].append((mean, cov, frame))
                        # id_preds[object_id.item()].append((mean, cov, frame))
                        # id_meas[object_id.item()].append((frame_boxes_3d[idx], frame_boxes_2d[idx], frame))
                        # id_errors[object_id.item()].append((np.sqrt(np.sum((mean[:3] - frame_boxes_3d[idx][:3])**2)), frame))
                        continue
                    mean, cov = kf.predict(id_means[object_id.item()][-1][0], id_means[object_id.item()][-1][1])
                    id_preds[object_id.item()].append((mean, cov, frame))
                    # if object_id.item()==3:
                    #     print("3D box: ", frame_boxes_3d[idx])
                    #     print("Old mean:", id_means[object_id.item()][0])
                    #     print("Predicted mean:", mean)
                        # pdb.set_trace()
                    if random.random() < prob_2d:
                        if random.random() < prob_3d:
                            mean, cov, mean_2d = kf.update(mean, cov, frame_boxes_2d[idx]+noise_2d, swap(frame_boxes_3d, iou, idx, swap_prob)+noise_3d)
                        else:
                            mean, cov, mean_2d = kf.update(mean, cov, frame_boxes_2d[idx]+noise_2d, None)
                    # if object_id.item()==12:
                    #     print("Updated mean after 2D:", mean_2d)
                    #     print("Updated mean after 3D:", mean)
                    #     print("Error:", np.sqrt(np.sum((mean[:3] - frame_boxes_3d[idx][:3])**2)))
                    #     if np.sqrt(np.sum((mean[:3] - frame_boxes_3d[idx][:3])**2)) > 1:
                    #         pdb.set_trace()
                    id_means[object_id.item()].append((mean, cov, frame))
                    id_means_2d[object_id.item()].append((mean_2d, frame))
                    id_meas[object_id.item()].append((frame_boxes_3d[idx], frame_boxes_2d[idx], frame))
                    id_errors[object_id.item()].append((np.sqrt(np.sum((mean[:3] - frame_boxes_3d[idx][:3])**2)), frame))
            errors = [np.mean(error[0]) for idx, error in id_errors.items() if len(error) > 0]
            final_errors[idx_2d, idx_3d] = np.mean(errors)
            print("3D prob: %f %% & 2D prob: %f %% & swap prob: %f %%  RMSE: %f"%(prob_3d*100, prob_2d*100, swap_prob*100, final_errors[idx_2d, idx_3d]))
            # if :
            with open('results/kf_mean_pickle.p', 'wb') as f:
                pickle.dump([id_means, id_means_2d, id_meas, id_preds], f)

    print(final_errors)

================================================
FILE: paper_experiments/utils/evaluate_detections.py
================================================
import numpy as np
import os
import pdb
from tqdm import tqdm
from deep_sort_utils import non_max_suppression as deepsort_nms
from visualise import draw_track
import matplotlib.pyplot as plt
from PIL import Image


def evaluate_detections(detection_path_1, detection_path_2, detection_path_3, detection_path_4, gt_path):
	#expecting detections and gt in file with format as in read_detections.py
	# applies confidence thresholding
	try:
		detections_1 = np.loadtxt(detection_path_1, delimiter=',')
		# detections_2 = np.loadtxt(detection_path_2, delimiter=',')
		# detections_3 = np.loadtxt(detection_path_3, delimiter=',')
		# detections_4 = np.loadtxt(detection_path_4, delimiter=',')
		# detections = np.concatenate([detections_1, detections_2, detections_3, detections_4])
		detections = detections_1
		gt = np.loadtxt(gt_path, delimiter=',')
	except:
		return
	gt_frames = gt[:, 0]
	det_confidence = detections[:, 6]

	###CONFIDENCE THRESHOLD
	detections = detections[det_confidence > 0.9]
	########

	print("Average number of detections per frame = %f"%(detections.shape[0]/len(np.unique(gt_frames))))

	det_frames = detections[:, 0]
	det_confidence = detections[:, 6]
	gt_boxes = np.asarray(list(zip(gt[:, 2], gt[:, 3], gt[:, 4], gt[:, 5])))
	det_boxes = np.asarray(list(zip(detections[:, 2], detections[:, 3], detections[:, 4], detections[:, 5])))
	assignments = []
	missed_detections = 0
	for frame in np.unique(gt_frames):
		frame_mask_det = det_frames == frame
		frame_mask_gt = gt_frames == frame
		frame_gt_boxes = gt_boxes[frame_mask_gt]
		frame_det_boxes = det_boxes[frame_mask_det]
		frame_confidence = det_confidence[frame_mask_det]
		x1 = np.expand_dims(detections[frame_mask_det,2].astype(np.float32), 1)
		y1 = np.expand_dims(detections[frame_mask_det,3].astype(np.float32), 1)
		w = np.expand_dims(detections[frame_mask_det,4].astype(np.float32), 1)
		h = np.expand_dims(detections[frame_mask_det,5].astype(np.float32), 1)
		conf = np.expand_dims(detections[frame_mask_det,6].astype(np.float32), 1)
		boxes = np.hstack([x1, y1, w, h])
		indices = deepsort_nms(boxes, 0.75, np.squeeze(conf))
		frame_det_boxes = frame_det_boxes[indices]

		# print(frame_confidence)
		positive_arr = np.asarray([False]*len(frame_det_boxes))
		for i, gt_box in enumerate(frame_gt_boxes):
			iou_list = np.asarray([iou(gt_box, det_box) for det_box in frame_det_boxes])
			positive_idx = np.where(iou_list >= 0.5)[0]
			if len(positive_idx) == 0:
				missed_detections += 1
				plt.figure(0)

				plt.imshow(Image.open(os.path.join(os.path.split(detection_path_1)[0], '..','imgs','%.6d.png'%frame)))
				draw_track(None, gt_box, det = False)
				for det_box in frame_det_boxes:
					draw_track(None, det_box, det = True)
				# 	print(det_box)
				# print('Boxes:')
				# print(boxes)
				# print('FRAME DONE')
				plt.show()


			positive_arr[positive_idx] = True
		assignments.extend(list(zip(positive_arr, frame_confidence)))
	assignments = sorted(assignments, key = lambda x: x[1], reverse = True)
	predictions = list(zip(*assignments))[0]
	true_positives = np.cumsum(predictions)
	false_negatives = np.cumsum(predictions[::-1])[::-1]+missed_detections
	precision = true_positives/range(1,len(true_positives)+1)
	recall = true_positives/(true_positives + false_negatives)
	print("Total missed detections = %d"%missed_detections)
	base = 0
	idx = []
	for i,recall_val in enumerate(recall):
		if recall_val > base:
			base += 0.1
			idx.append(i)
		if base >1:
			break
	precision_vals = [np.amax(precision[index:]) for index in idx]
	if len(precision_vals) < 11:
		precision_vals.extend([0]*(11-len(precision_vals)))
	print(precision_vals)

	return np.mean(precision_vals)


def iou(bbox_1, bbox_2):

	x1_1, y1_1, w_1, h_1 = bbox_1
	x1_2, y1_2, w_2, h_2 = bbox_2
	x2_1 = x1_1 + w_1
	y2_1 = y1_1 + h_1

	x2_2 = x1_2 + w_2
	y2_2 = y1_2 + h_2
	
	area_1 = abs(x2_1 - x1_1)*abs(y2_1-y1_1)
	area_2 = abs(x2_2 - x1_2)*abs(y2_2-y1_2)


	intersection = max(0, (min(x2_1, x2_2) - max(x1_1, x1_2))) * max(0, (min(y2_1, y2_2) - max(y1_1, y1_2)))
	union = area_1 + area_2 - intersection

	return intersection / union

if __name__=='__main__':
	ap = []
	KITTI_root = 'data/KITTI/sequences'
	for sequence in tqdm(range(21)):
		ap.append(evaluate_detections(os.path.join(KITTI_root, '%.4d'%sequence, 'det','subcnn_car_det.txt'), 
										os.path.join(KITTI_root, '%.4d'%sequence, 'det','rrc_car_det.txt'),
										os.path.join(KITTI_root, '%.4d'%sequence, 'det','lsvm_car_det.txt'),
										os.path.join(KITTI_root, '%.4d'%sequence, 'det','regionlets_car_det.txt'), 
										os.path.join(KITTI_root, '%.4d'%sequence, 'gt', 'gt_car.txt')))
	ap = [ap_val for ap_val in ap if ap_val is not None]
	print("FINAL AVERAGE PRECISION OVER ALL SEQUENCES IS: %f"%np.mean(ap))



================================================
FILE: paper_experiments/utils/featurepointnet_model_util.py
================================================
import open3d as o3d
import numpy as np
import tensorflow as tf
import os
import sys
import torch
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(BASE_DIR)
import featurepointnet_tf_util as tf_util

# -----------------
# Global Constants
# -----------------

NUM_HEADING_BIN = 12
NUM_SIZE_CLUSTER = 8 # one cluster for each type
NUM_OBJECT_POINT = 512
g_type2class={'Car':0, 'Van':1, 'Truck':2, 'Pedestrian':3,
              'Person_sitting':4, 'Cyclist':5, 'Tram':6, 'Misc':7}
g_class2type = {g_type2class[t]:t for t in g_type2class}
g_type2onehotclass = {'Car': 0, 'Pedestrian': 1, 'Cyclist': 2}
#Added 0.5m and 0.2m for car and pedestrian to make boxes slightly bigger
g_type_mean_size = {'Car': np.array([3.88311640418,1.62856739989,1.52563191462]),
                    'Van': np.array([5.06763659,1.9007158,2.20532825]),
                    'Truck': np.array([10.13586957,2.58549199,3.2520595]),
                    'Pedestrian': np.array([0.84422524,0.66068622,1.76255119]),
          
Download .txt
gitextract_mbelvxqp/

├── CMakeLists.txt
├── LICENSE
├── README.md
├── calib/
│   ├── cameras.yaml
│   └── defaults.yaml
├── config/
│   └── featurepointnet.cfg
├── launch/
│   └── jpda_tracker.launch
├── msg/
│   ├── __init__.py
│   ├── detection2d_with_feature.msg
│   ├── detection2d_with_feature_array.msg
│   ├── detection3d_with_feature.msg
│   └── detection3d_with_feature_array.msg
├── package.xml
├── paper_experiments/
│   ├── models/
│   │   ├── __init__.py
│   │   ├── aligned_reid_model.py
│   │   ├── combination_model.py
│   │   ├── deep_sort_model.py
│   │   ├── featurepointnet_model.py
│   │   ├── pointnet_model.py
│   │   ├── resnet_reid_models.py
│   │   └── yolo_models.py
│   ├── requirements.txt
│   ├── track.py
│   └── utils/
│       ├── EKF.py
│       ├── JPDA_matching.py
│       ├── aligned_reid_utils.py
│       ├── assign_ids_detections.py
│       ├── calibration.py
│       ├── combine_and_process_detections.py
│       ├── dataset.py
│       ├── deep_sort_utils.py
│       ├── detection.py
│       ├── double_measurement_kf.py
│       ├── evaluate_detections.py
│       ├── featurepointnet_model_util.py
│       ├── featurepointnet_tf_util.py
│       ├── imm.py
│       ├── iou_matching.py
│       ├── kf_2d.py
│       ├── kf_3d.py
│       ├── linear_assignment.py
│       ├── logger.py
│       ├── mbest_ilp.py
│       ├── nn_matching.py
│       ├── pointnet_tf_util.py
│       ├── pointnet_transform_nets.py
│       ├── read_detections.py
│       ├── resnet_reid_utils.py
│       ├── test_jpda.py
│       ├── test_kf/
│       │   ├── .gitignore
│       │   ├── run_kf_test.py
│       │   ├── single_track_4state_test.p.val
│       │   ├── single_track_6state_test.p.val
│       │   ├── two_track_4state_test.p.val
│       │   └── write_kf_test.py
│       ├── track.py
│       ├── track_3d.py
│       ├── tracker.py
│       ├── tracker_3d.py
│       ├── tracking_utils.py
│       ├── visualise.py
│       └── yolo_utils/
│           ├── __init__.py
│           ├── datasets.py
│           ├── parse_config.py
│           └── utils.py
├── requirements.txt
└── src/
    ├── 3d_detector.py
    ├── EKF.py
    ├── JPDA_matching.py
    ├── __init__.py
    ├── aligned_reid_model.py
    ├── aligned_reid_utils.py
    ├── calibration.py
    ├── combination_model.py
    ├── deep_sort_utils.py
    ├── detection.py
    ├── distances.py
    ├── double_measurement_kf.py
    ├── evaluation/
    │   ├── __init__.py
    │   ├── distances 2.py
    │   └── distances.py
    ├── featurepointnet_model.py
    ├── featurepointnet_model_util.py
    ├── featurepointnet_tf_util.py
    ├── iou_matching.py
    ├── kf_2d.py
    ├── linear_assignment.py
    ├── mbest_ilp.py
    ├── nn_matching.py
    ├── pointnet_model.py
    ├── template 2.py
    ├── template.py
    ├── track_3d 2.py
    ├── track_3d.py
    ├── tracker_3d 2.py
    ├── tracker_3d.py
    ├── tracker_3d_node 2.py
    ├── tracker_3d_node.py
    ├── tracking_utils 2.py
    └── tracking_utils.py
Download .txt
SYMBOL INDEX (839 symbols across 76 files)

FILE: paper_experiments/models/aligned_reid_model.py
  class Model (line 10) | class Model(nn.Module):
    method __init__ (line 11) | def __init__(self, local_conv_out_channels=128, num_classes=None):
    method forward (line 24) | def forward(self, x):
  function conv3x3 (line 60) | def conv3x3(in_planes, out_planes, stride=1):
  class BasicBlock (line 66) | class BasicBlock(nn.Module):
    method __init__ (line 69) | def __init__(self, inplanes, planes, stride=1, downsample=None):
    method forward (line 79) | def forward(self, x):
  class Bottleneck (line 98) | class Bottleneck(nn.Module):
    method __init__ (line 101) | def __init__(self, inplanes, planes, stride=1, downsample=None):
    method forward (line 114) | def forward(self, x):
  class ResNet (line 137) | class ResNet(nn.Module):
    method __init__ (line 139) | def __init__(self, block, layers):
    method _make_layer (line 160) | def _make_layer(self, block, planes, blocks, stride=1):
    method forward (line 177) | def forward(self, x):
  function remove_fc (line 191) | def remove_fc(state_dict):
  function resnet18 (line 200) | def resnet18(pretrained=False):
  function resnet34 (line 212) | def resnet34(pretrained=False):
  function resnet50 (line 224) | def resnet50(pretrained=False):
  function resnet101 (line 236) | def resnet101(pretrained=False):
  function resnet152 (line 249) | def resnet152(pretrained=False):

FILE: paper_experiments/models/combination_model.py
  class CombiNet (line 6) | class CombiNet(nn.Module):
    method __init__ (line 7) | def __init__(self, in_dim = 2560, hidden_units = 512, out_dim = 2560):
    method forward (line 16) | def forward(self, x):
  class CombiLSTM (line 30) | class CombiLSTM(nn.Module):
    method __init__ (line 31) | def __init__(self, in_dim = 2560, hidden_units = 512, out_dim = 2560):
    method forward (line 43) | def forward(self, x, hidden = None):
  function weight_init (line 65) | def weight_init(m):

FILE: paper_experiments/models/deep_sort_model.py
  class ImageEncoder (line 5) | class ImageEncoder(object):
    method __init__ (line 7) | def __init__(self, checkpoint_filename="weights/deep_sort_weights.pb",...
    method __call__ (line 26) | def __call__(self, data_x):

FILE: paper_experiments/models/featurepointnet_model.py
  class FPointNet (line 13) | class FPointNet():
    method __init__ (line 14) | def __init__(self, config_path):
    method __call__ (line 57) | def __call__(self, input_point_cloud, rot_angle, peds=False):
    method get_instance_seg_v1_net (line 130) | def get_instance_seg_v1_net(self, point_cloud, one_hot_vec, is_trainin...
    method get_3d_box_estimation_v1_net (line 201) | def get_3d_box_estimation_v1_net(self, object_point_cloud, one_hot_vec...
    method get_model (line 250) | def get_model(self, point_cloud, one_hot_vec, is_training, bn_decay=No...
    method get_depth_feature_op (line 298) | def get_depth_feature_op(self, is_training):
    method get_depth_feature (line 321) | def get_depth_feature(self, object_pointcloud):
    method softmax (line 327) | def softmax(self, x):
  function create_depth_model (line 334) | def create_depth_model(model, config_path):

FILE: paper_experiments/models/pointnet_model.py
  class PointNet (line 9) | class PointNet():
    method __init__ (line 10) | def __init__(self, config_path):
    method __call__ (line 37) | def __call__(self, input_point_cloud):
    method placeholder_inputs (line 43) | def placeholder_inputs(self, batch_size, num_point):
    method get_model (line 49) | def get_model(self, point_cloud, is_training, bn_decay=None):
    method get_loss (line 96) | def get_loss(self, pred, label, end_points, reg_weight=0.001):

FILE: paper_experiments/models/resnet_reid_models.py
  class FeatureResNet (line 8) | class FeatureResNet(nn.Module):
    method __init__ (line 9) | def __init__(self,n_layers=50,pretrained=True):
    method forward (line 25) | def forward(self,x):
  class ResNet (line 30) | class ResNet(nn.Module):
    method __init__ (line 31) | def __init__(self,n_id,n_layers=50,pretrained=True):
    method forward (line 47) | def forward(self,x):
  class NLayersFC (line 54) | class NLayersFC(nn.Module):
    method __init__ (line 55) | def __init__(self, in_dim, out_dim, hidden_dim=1, n_layers=0):
    method forward (line 69) | def forward(self, x):
  class ICT_ResNet (line 72) | class ICT_ResNet(nn.Module):
    method __init__ (line 73) | def __init__(self,n_id,n_color,n_type,n_layers=50,pretrained=True):
    method forward (line 91) | def forward(self,x):
  class TripletNet (line 101) | class TripletNet(nn.Module):
    method __init__ (line 102) | def __init__(self, net):
    method forward (line 106) | def forward(self, x, y, z):

FILE: paper_experiments/models/yolo_models.py
  function create_modules (line 19) | def create_modules(module_defs):
  class EmptyLayer (line 94) | class EmptyLayer(nn.Module):
    method __init__ (line 97) | def __init__(self):
  class Interpolate (line 100) | class Interpolate(nn.Module):
    method __init__ (line 101) | def __init__(self, scale_factor, mode):
    method forward (line 107) | def forward(self, x):
  class YOLOLayer (line 111) | class YOLOLayer(nn.Module):
    method __init__ (line 114) | def __init__(self, anchors, num_classes, img_dim):
    method forward (line 128) | def forward(self, x, targets=None):
  class Darknet (line 240) | class Darknet(nn.Module):
    method __init__ (line 243) | def __init__(self, config_path):
    method forward (line 252) | def forward(self, x, targets=None):
    method load_weights (line 282) | def load_weights(self, weights_path):
    method save_weights (line 337) | def save_weights(self, path, cutoff=-1):

FILE: paper_experiments/track.py
  function parse_arguments (line 28) | def parse_arguments():
  function main (line 92) | def main(opt):

FILE: paper_experiments/utils/EKF.py
  function squared_mahalanobis_distance (line 79) | def squared_mahalanobis_distance(mean, covariance, measurements):
  class EKF (line 106) | class EKF(object):
    method __init__ (line 112) | def __init__(self):
    method initiate (line 115) | def initiate(self, measurement):
    method predict_mean (line 132) | def predict_mean(self, mean):
    method get_process_noise (line 138) | def get_process_noise(self, mean, covariance):
    method predict_covariance (line 141) | def predict_covariance(self, mean, covariance):
    method project_mean (line 144) | def project_mean(self, mean):
    method project_cov (line 149) | def project_cov(self, mean, covariance):
    method predict (line 152) | def predict(self, mean, covariance, last_detection, next_to_last_detec...
    method get_innovation_cov (line 176) | def get_innovation_cov(self, covariance):
    method project (line 179) | def project(self, mean, covariance):
    method update (line 200) | def update(self, mean, covariance, measurement_t, marginalization=None...

FILE: paper_experiments/utils/JPDA_matching.py
  function get_unmatched (line 8) | def get_unmatched(all_idx, matches, i, marginalization=None):
  class Matcher (line 19) | class Matcher:
    method __init__ (line 21) | def __init__(self, detections, marginalizations, confirmed_tracks,
    method match (line 31) | def match(self):
    method get_matches (line 37) | def get_matches(self):
    method get_unmatched_tracks (line 51) | def get_unmatched_tracks(self):
    method get_unmatched_detections (line 55) | def get_unmatched_detections(self):
    method max_match (line 58) | def max_match(self):
    method max_and_threshold_matching (line 84) | def max_and_threshold_matching(self):
    method hungarian (line 103) | def hungarian(self):

FILE: paper_experiments/utils/aligned_reid_utils.py
  function time_str (line 17) | def time_str(fmt=None):
  function load_pickle (line 23) | def load_pickle(path):
  function save_pickle (line 35) | def save_pickle(obj, path):
  function save_mat (line 42) | def save_mat(ndarray, path):
  function to_scalar (line 47) | def to_scalar(vt):
  function transfer_optim_state (line 58) | def transfer_optim_state(state, device_id=-1):
  function may_transfer_optims (line 83) | def may_transfer_optims(optims, device_id=-1):
  function may_transfer_modules_optims (line 96) | def may_transfer_modules_optims(modules_and_or_optims, device_id=-1):
  class TransferVarTensor (line 115) | class TransferVarTensor(object):
    method __init__ (line 118) | def __init__(self, device_id=-1):
    method __call__ (line 121) | def __call__(self, var_or_tensor):
  class TransferModulesOptims (line 126) | class TransferModulesOptims(object):
    method __init__ (line 129) | def __init__(self, device_id=-1):
    method __call__ (line 132) | def __call__(self, modules_and_or_optims):
  function set_devices (line 136) | def set_devices(sys_device_ids):
  function set_devices_for_ml (line 165) | def set_devices_for_ml(sys_device_ids):
  function load_ckpt (line 230) | def load_ckpt(modules_optims, ckpt_file, load_to_cpu=True, verbose=True):
  function save_ckpt (line 253) | def save_ckpt(modules_optims, ep, scores, ckpt_file):
  function load_state_dict (line 274) | def load_state_dict(model, src_state_dict):
  function is_iterable (line 315) | def is_iterable(obj):
  function may_set_mode (line 319) | def may_set_mode(maybe_modules, mode):
  function may_make_dir (line 332) | def may_make_dir(path):
  class AverageMeter (line 348) | class AverageMeter(object):
    method __init__ (line 352) | def __init__(self):
    method reset (line 358) | def reset(self):
    method update (line 364) | def update(self, val, n=1):
  class RunningAverageMeter (line 371) | class RunningAverageMeter(object):
    method __init__ (line 374) | def __init__(self, hist=0.99):
    method reset (line 379) | def reset(self):
    method update (line 383) | def update(self, val):
  class RecentAverageMeter (line 391) | class RecentAverageMeter(object):
    method __init__ (line 394) | def __init__(self, hist_size=100):
    method reset (line 399) | def reset(self):
    method update (line 403) | def update(self, val):
    method avg (line 410) | def avg(self):
  function get_model_wrapper (line 415) | def get_model_wrapper(model, multi_gpu):
  class ReDirectSTD (line 423) | class ReDirectSTD(object):
    method __init__ (line 443) | def __init__(self, fpath=None, console='stdout', immediately_visible=F...
    method __del__ (line 464) | def __del__(self):
    method __enter__ (line 467) | def __enter__(self):
    method __exit__ (line 470) | def __exit__(self, *args):
    method write (line 473) | def write(self, msg):
    method flush (line 485) | def flush(self):
    method close (line 492) | def close(self):
  function set_seed (line 498) | def set_seed(seed):
  function print_array (line 515) | def print_array(array, fmt='{:.2f}', end=' '):
  function str2bool (line 526) | def str2bool(v):
  function tight_float_str (line 530) | def tight_float_str(x, fmt='{:.4f}'):
  function find_index (line 534) | def find_index(seq, item):
  function adjust_lr_exp (line 541) | def adjust_lr_exp(optimizer, base_lr, ep, total_ep, start_decay_at_ep):
  function adjust_lr_staircase (line 573) | def adjust_lr_staircase(optimizer, base_lr, ep, decay_at_epochs, factor):
  function measure_time (line 609) | def measure_time(enter_msg):
  function generate_features (line 616) | def generate_features(appearance_model, patches, opt, object_ids = None):
  function generate_features_batched (line 645) | def generate_features_batched(appearance_model, patches, opt, object_ids...
  function get_image_patches (line 713) | def get_image_patches(input_img, detections):
  function create_appearance_model (line 735) | def create_appearance_model(model_type, alignreid_checkpoint, resnet_rei...

FILE: paper_experiments/utils/assign_ids_detections.py
  function assign_detection_id (line 11) | def assign_detection_id(detection_path, gt_path, conf_threshold = 0, iou...

FILE: paper_experiments/utils/calibration.py
  class Calibration (line 8) | class Calibration(object):
    method __init__ (line 33) | def __init__(self, calib_filepath):
    method read_calib_file (line 71) | def read_calib_file(self, filepath):
    method read_calib_from_video (line 92) | def read_calib_from_video(self, calib_root_dir):
    method cart2hom (line 107) | def cart2hom(self, pts_3d):
    method cart2hom_torch (line 115) | def cart2hom_torch(self, pts_3d):
    method project_velo_to_ref (line 123) | def project_velo_to_ref(self, pts_3d_velo):
    method project_ref_to_velo (line 127) | def project_ref_to_velo(self, pts_3d_ref):
    method project_rect_to_ref (line 131) | def project_rect_to_ref(self, pts_3d_rect):
    method project_ref_to_rect (line 135) | def project_ref_to_rect(self, pts_3d_ref):
    method project_ref_to_rect_torch (line 139) | def project_ref_to_rect_torch(self, pts_3d_ref):
    method project_rect_to_velo (line 143) | def project_rect_to_velo(self, pts_3d_rect):
    method project_velo_to_rect (line 150) | def project_velo_to_rect(self, pts_3d_velo):
    method project_rect_to_image (line 157) | def project_rect_to_image(self, pts_3d_rect):
    method project_rect_to_image_torch (line 167) | def project_rect_to_image_torch(self, pts_3d_rect):
    method project_ref_to_image_torch (line 177) | def project_ref_to_image_torch(self, pts_3d_ref):
    method project_velo_to_image (line 187) | def project_velo_to_image(self, pts_3d_velo):
    method project_image_to_rect (line 197) | def project_image_to_rect(self, uv_depth):
    method project_image_to_velo (line 211) | def project_image_to_velo(self, uv_depth):
  function rotx (line 215) | def rotx(t):
  function roty (line 224) | def roty(t):
  function rotz (line 233) | def rotz(t):
  function transform_from_rot_trans (line 242) | def transform_from_rot_trans(R, t):
  function inverse_rigid_trans (line 249) | def inverse_rigid_trans(Tr):
  function read_label (line 258) | def read_label(label_filename):
  function load_image (line 263) | def load_image(img_filename):
  function load_velo_scan (line 266) | def load_velo_scan(velo_filename):
  function project_to_image (line 271) | def project_to_image(pts_3d, P):
  function compute_box_3d (line 291) | def compute_box_3d(obj, P):
  function compute_orientation_3d (line 329) | def compute_orientation_3d(obj, P):
  function draw_projected_box3d (line 358) | def draw_projected_box3d(image, qs, color=(255,255,255), thickness=2):
  class OmniCalibration (line 385) | class OmniCalibration(Calibration):
    method __init__ (line 386) | def __init__(self, calib_folder):
    method project_ref_to_image_torch (line 402) | def project_ref_to_image_torch(self, pointcloud):
    method project_image_to_rect (line 413) | def project_image_to_rect(self, uvdepth):
    method project_velo_to_ref (line 422) | def project_velo_to_ref(self, pointcloud):
    method move_lidar_to_camera_frame (line 430) | def move_lidar_to_camera_frame(self, pointcloud, upper = True):
    method calculate_median_param_value (line 445) | def calculate_median_param_value(self, param):

FILE: paper_experiments/utils/combine_and_process_detections.py
  function threshold (line 13) | def threshold(filename, thresh, min, max):

FILE: paper_experiments/utils/dataset.py
  class SequenceDataset (line 23) | class SequenceDataset(Dataset):
    method __init__ (line 24) | def __init__(self, folder_path, point_cloud=False, cuda=False, omni=Fa...
    method __getitem__ (line 44) | def __getitem__(self, index):
    method __len__ (line 75) | def __len__(self):
  function is_image_file (line 78) | def is_image_file(file):
  class TripletDataset (line 85) | class TripletDataset(Dataset):
    method __init__ (line 87) | def __init__(self, feature_path, num_negative_samples = 100, cuda = Tr...
    method __getitem__ (line 115) | def __getitem__(self, index):
    method __len__ (line 157) | def __len__(self):
  class STIPDataset (line 160) | class STIPDataset(Dataset):
    method __init__ (line 161) | def __init__(self, folder_path, img_size=416, point_cloud = False, pad...
    method __getitem__ (line 169) | def __getitem__(self, index):
    method __len__ (line 194) | def __len__(self):
  function collate_fn (line 197) | def collate_fn(inputs):

FILE: paper_experiments/utils/deep_sort_utils.py
  function non_max_suppression (line 6) | def non_max_suppression(boxes, max_bbox_overlap, scores=None):

FILE: paper_experiments/utils/detection.py
  class Detection (line 5) | class Detection(object):
    method __init__ (line 29) | def __init__(self, tlwh, box_3d, confidence, appearance_feature, featu...
    method to_tlbr (line 44) | def to_tlbr(self):
    method to_xyah (line 52) | def to_xyah(self):
    method to_xywh (line 60) | def to_xywh(self):
    method get_3d_distance (line 67) | def get_3d_distance(self):

FILE: paper_experiments/utils/double_measurement_kf.py
  class KF_3D (line 19) | class KF_3D(kf_2d.KalmanFilter2D):
    method __init__ (line 34) | def __init__(self, calib, pos_weight_3d, pos_weight, velocity_weight, ...
    method initiate (line 65) | def initiate(self, measurement_3d):
    method get_process_noise (line 84) | def get_process_noise(self, mean):
    method get_2d_measurement_noise (line 102) | def get_2d_measurement_noise(self, measurement_2d):
    method get_3d_measurement_noise (line 114) | def get_3d_measurement_noise(self, measurement):
    method gating_distance (line 130) | def gating_distance(self, mean, covariance, measurements,
    method project_cov (line 179) | def project_cov(self, mean, covariance):
    method project_cov_2d (line 188) | def project_cov_2d(self, mean, covariance, H_2d):
    method update (line 197) | def update(self, mean, covariance, measurement_2d, measurement_3d = No...
    method get_2d_measurement_matrix (line 301) | def get_2d_measurement_matrix(self, mean, corner_points, corner_points...
    method jacobian (line 338) | def jacobian(self, pt_3d):
    method jacobian_omni (line 344) | def jacobian_omni(self, pt_3d):
    method calculate_corners (line 360) | def calculate_corners(self, box):
    method corner_jacobian (line 379) | def corner_jacobian(self, pt_3d, corner_idx):
    method project_2d (line 406) | def project_2d(self, pts_3d):
  function swap (line 415) | def swap(detections_3d, iou, idx, swap_prob = 0):

FILE: paper_experiments/utils/evaluate_detections.py
  function evaluate_detections (line 11) | def evaluate_detections(detection_path_1, detection_path_2, detection_pa...
  function iou (line 99) | def iou(bbox_1, bbox_2):

FILE: paper_experiments/utils/featurepointnet_model_util.py
  function tf_gather_object_pc (line 39) | def tf_gather_object_pc(point_cloud, mask, npoints=512):
  function get_box3d_corners_helper (line 72) | def get_box3d_corners_helper(centers, headings, sizes):
  function get_box3d_corners (line 99) | def get_box3d_corners(center, heading_residuals, size_residuals):
  function huber_loss (line 124) | def huber_loss(error, delta):
  function parse_output_to_tensors (line 132) | def parse_output_to_tensors(output, end_points):
  function from_prediction_to_label_format (line 170) | def from_prediction_to_label_format(center, angle_class, angle_res,\
  function size2class (line 179) | def size2class(size, type_name):
  function class2size (line 194) | def class2size(pred_cls, residual):
  function angle2class (line 199) | def angle2class(angle, num_class):
  function class2angle (line 219) | def class2angle(pred_cls, residual, num_class, to_label_format=True):
  function rotate_pc_along_y (line 230) | def rotate_pc_along_y(pc, rot_angle):
  function placeholder_inputs (line 249) | def placeholder_inputs(batch_size, num_point):
  function point_cloud_masking (line 274) | def point_cloud_masking(point_cloud, logits, end_points, xyz_only=True):
  function get_center_regression_net (line 322) | def get_center_regression_net(object_point_cloud, one_hot_vec,
  function get_loss (line 360) | def get_loss(mask_label, center_label, \
  function get_lidar_in_image_fov (line 482) | def get_lidar_in_image_fov(pc_velo, calib, xmin, ymin, xmax, ymax,
  function preprocess_pointcloud (line 497) | def preprocess_pointcloud(detections, point_cloud, pc_image_coord,
  function generate_detections_3d (line 551) | def generate_detections_3d(detector, detections_2d, point_cloud, calib, ...
  function convert_depth_features (line 564) | def convert_depth_features(depth_features_orig, ids_3d, cuda = True):

FILE: paper_experiments/utils/featurepointnet_tf_util.py
  function _variable_on_cpu (line 10) | def _variable_on_cpu(name, shape, initializer, use_fp16=False):
  function _variable_with_weight_decay (line 24) | def _variable_with_weight_decay(name, shape, stddev, wd, use_xavier=True):
  function conv1d (line 52) | def conv1d(inputs,
  function conv2d (line 120) | def conv2d(inputs,
  function conv2d_transpose (line 188) | def conv2d_transpose(inputs,
  function conv3d (line 268) | def conv3d(inputs,
  function fully_connected (line 327) | def fully_connected(inputs,
  function max_pool2d (line 366) | def max_pool2d(inputs,
  function avg_pool2d (line 391) | def avg_pool2d(inputs,
  function max_pool3d (line 417) | def max_pool3d(inputs,
  function avg_pool3d (line 442) | def avg_pool3d(inputs,
  function batch_norm_template_unused (line 468) | def batch_norm_template_unused(inputs, is_training, scope, moments_dims,...
  function batch_norm_template (line 512) | def batch_norm_template(inputs, is_training, scope, moments_dims_unused,...
  function batch_norm_for_fc (line 534) | def batch_norm_for_fc(inputs, is_training, bn_decay, scope):
  function batch_norm_for_conv1d (line 548) | def batch_norm_for_conv1d(inputs, is_training, bn_decay, scope, data_for...
  function batch_norm_for_conv2d (line 565) | def batch_norm_for_conv2d(inputs, is_training, bn_decay, scope, data_for...
  function batch_norm_for_conv3d (line 580) | def batch_norm_for_conv3d(inputs, is_training, bn_decay, scope):
  function dropout (line 594) | def dropout(inputs,

FILE: paper_experiments/utils/imm.py
  class IMMFilter2D (line 11) | class IMMFilter2D(EKF.EKF):
    method __init__ (line 31) | def __init__(self, kf_vel_params=(1./20, 1./160, 1, 1, 2), kf_walk_par...
    method initiate (line 38) | def initiate(self, measurement, flow):
    method gating_distance (line 64) | def gating_distance(self, mean, covariance, measurements,
    method update (line 94) | def update(self, mean, covariance, measurement, model_probabilities, m...
    method predict (line 147) | def predict(self, mean, covariance, model_probabilities):
    method mix_models (line 176) | def mix_models(self, mean_1, cov_1, mean_2, cov_2, model_transition_pr...
    method combine_states (line 193) | def combine_states(mean, cov, model_probabilities):
  function generate_particle_motion (line 200) | def generate_particle_motion(motion_matrices, initial_state, process_noi...
  function generate_observations (line 215) | def generate_observations(input_state_list, observation_matrix, observat...

FILE: paper_experiments/utils/iou_matching.py
  function iou (line 8) | def iou(bbox, candidates):
  function iou_cost (line 43) | def iou_cost(tracks, detections, track_indices=None,

FILE: paper_experiments/utils/kf_2d.py
  class KalmanFilter2D (line 8) | class KalmanFilter2D(EKF.EKF):
    method __init__ (line 25) | def __init__(self, pos_weight, velocity_weight, std_process, std_measu...
    method initiate (line 47) | def initiate(self, measurement, flow):
    method predict_mean (line 87) | def predict_mean(self, mean):
    method predict_covariance (line 93) | def predict_covariance(self, mean, covariance, last_detection, next_to...
    method get_process_noise (line 101) | def get_process_noise(self, mean, last_detection, next_to_last_detecti...
    method project_mean (line 136) | def project_mean(self, mean):
    method get_measurement_noise (line 144) | def get_measurement_noise(self, measurement):
    method project_cov (line 156) | def project_cov(self, mean, covariance):
    method gating_distance (line 165) | def gating_distance(self, mean, covariance, measurements,
  class RandomWalkKalmanFilter2D (line 206) | class RandomWalkKalmanFilter2D(KalmanFilter2D): #TODO UPDATE THIS DOCUME...
    method __init__ (line 222) | def __init__(self, pos_weight, velocity_weight, std_process, std_measu...

FILE: paper_experiments/utils/kf_3d.py
  class KalmanFilter3D (line 8) | class KalmanFilter3D(EKF.EKF):
    method __init__ (line 24) | def __init__(self):
    method initiate (line 76) | def initiate(self, measurement):
    method motion_update (line 103) | def motion_update(self, mean, covariance):
    method get_motion_cov (line 110) | def get_motion_cov(self, mean, covariance):
    method sensor_update (line 115) | def sensor_update(self, mean, covariance):
    method get_innovation_cov (line 122) | def get_innovation_cov(self, mean, covariance):
    method adjust_angle (line 126) | def adjust_angle(self, measured, target):
    method update (line 131) | def update(self, mean, covariance, meas_in, marginalization=None, JPDA...
    method gating_distance (line 139) | def gating_distance(self, mean, covariance, measurements,

FILE: paper_experiments/utils/linear_assignment.py
  function min_marg_matching (line 14) | def min_marg_matching(marginalizations, track_indices=None, max_distance...
  function min_cost_matching (line 60) | def min_cost_matching(
  function JPDA (line 141) | def JPDA(
  function calculate_entropy (line 212) | def calculate_entropy(matrix, idx, idy):
  function get_JPDA_output (line 220) | def get_JPDA_output(cluster, cost_matrix, dummy_node_cost_app, dummy_nod...
  function matching_cascade (line 273) | def matching_cascade(
  function gate_cost_matrix (line 339) | def gate_cost_matrix(
  function find_clusters (line 410) | def find_clusters(cost_matrix, cutoff):

FILE: paper_experiments/utils/logger.py
  class Logger (line 6) | class Logger:
    method __init__ (line 7) | def __init__(self, logdir):
    method close (line 12) | def close(self):
    method log_scalar (line 15) | def log_scalar(self, tag, value, global_step):
    method log_image (line 21) | def log_image(self, tag, img, global_step):

FILE: paper_experiments/utils/mbest_ilp.py
  function ilp_assignment (line 16) | def ilp_assignment(model):
  function initialize_model (line 29) | def initialize_model(cost_matrix, cutoff, model = None):
  function cache (line 59) | def cache(func):
  function num_solutions (line 74) | def num_solutions(cost_matrix):
  function enumerate_solutions (line 85) | def enumerate_solutions(cost_matrix, cutoff, num_solutions):
  function new_m_best_sol (line 104) | def new_m_best_sol(cost_matrix, m_sol, cutoff, model = None):
  function linear_assignment_wrapper (line 189) | def linear_assignment_wrapper(a):

FILE: paper_experiments/utils/nn_matching.py
  function _pdist (line 6) | def _pdist(a, b):
  function _cosine_distance (line 32) | def _cosine_distance(a, b, data_is_normalized=False):
  function _cosine_distance_torch (line 57) | def _cosine_distance_torch(a, b, data_is_normalized=False):
  function _nn_euclidean_distance (line 66) | def _nn_euclidean_distance(x, y):
  function _nn_euclidean_distance_torch (line 86) | def _nn_euclidean_distance_torch(x, y):
  function _nn_cosine_distance (line 111) | def _nn_cosine_distance(x, y):
  function _nn_cosine_distance_torch (line 131) | def _nn_cosine_distance_torch(x,y):
  class NearestNeighborDistanceMetric (line 138) | class NearestNeighborDistanceMetric(object):
    method __init__ (line 162) | def __init__(self, metric, budget=None):
    method partial_fit (line 178) | def partial_fit(self, features, features_2d, targets, targets_2d, acti...
    method distance (line 209) | def distance(self, features, targets, compare_2d=False):
    method distance_torch (line 235) | def distance_torch(self, features, targets, compare_2d=False):
    method check_samples (line 248) | def check_samples(self, targets):

FILE: paper_experiments/utils/pointnet_tf_util.py
  function _variable_on_cpu (line 10) | def _variable_on_cpu(name, shape, initializer, use_fp16=False):
  function _variable_with_weight_decay (line 24) | def _variable_with_weight_decay(name, shape, stddev, wd, use_xavier=True):
  function conv1d (line 52) | def conv1d(inputs,
  function conv2d (line 112) | def conv2d(inputs,
  function conv2d_transpose (line 172) | def conv2d_transpose(inputs,
  function conv3d (line 252) | def conv3d(inputs,
  function fully_connected (line 311) | def fully_connected(inputs,
  function max_pool2d (line 350) | def max_pool2d(inputs,
  function avg_pool2d (line 375) | def avg_pool2d(inputs,
  function max_pool3d (line 401) | def max_pool3d(inputs,
  function avg_pool3d (line 426) | def avg_pool3d(inputs,
  function batch_norm_template (line 455) | def batch_norm_template(inputs, is_training, scope, moments_dims, bn_dec...
  function batch_norm_for_fc (line 495) | def batch_norm_for_fc(inputs, is_training, bn_decay, scope):
  function batch_norm_for_conv1d (line 509) | def batch_norm_for_conv1d(inputs, is_training, bn_decay, scope):
  function batch_norm_for_conv2d (line 525) | def batch_norm_for_conv2d(inputs, is_training, bn_decay, scope):
  function batch_norm_for_conv3d (line 540) | def batch_norm_for_conv3d(inputs, is_training, bn_decay, scope):
  function dropout (line 554) | def dropout(inputs,

FILE: paper_experiments/utils/pointnet_transform_nets.py
  function input_transform_net (line 10) | def input_transform_net(point_cloud, is_training, bn_decay=None, K=3):
  function feature_transform_net (line 54) | def feature_transform_net(inputs, is_training, bn_decay=None, K=64):

FILE: paper_experiments/utils/read_detections.py
  function read_ground_truth_2d_detections (line 5) | def read_ground_truth_2d_detections(detection_path_2d, frame_idx, detect...
  function read_ground_truth_3d_detections (line 82) | def read_ground_truth_3d_detections(detection_path_3d, frame_idx):

FILE: paper_experiments/utils/resnet_reid_utils.py
  class Feature_ResNet (line 14) | class Feature_ResNet(nn.Module):
    method __init__ (line 15) | def __init__(self,n_layer,output_color):
    method forward (line 24) | def forward(self,x):
  class ResNet_Loader (line 35) | class ResNet_Loader(object):
    method __init__ (line 36) | def __init__(self,model_path,n_layer=50,batch_size=4,output_color=False):
    method inference (line 56) | def inference(self,patches):

FILE: paper_experiments/utils/test_kf/run_kf_test.py
  class Track (line 12) | class Track:
    method __init__ (line 13) | def __init__(self, track_id, first_detection, kf_type):
    method update (line 36) | def update(self, measurement, gt, frame):
    method plot (line 53) | def plot(self):
  function file2data (line 99) | def file2data(fname):
  function cmp_tracks (line 108) | def cmp_tracks(track1, track2):
  function cmp (line 114) | def cmp(data, val):
  function validate (line 128) | def validate(data, fname):
  function run_kf_test (line 137) | def run_kf_test(fname, kf_type):

FILE: paper_experiments/utils/test_kf/write_kf_test.py
  function data2file (line 8) | def data2file(data, fname):
  function add_noise (line 17) | def add_noise(center, std):
  function single_track_4state_test (line 23) | def single_track_4state_test():
  function two_track_4state_test (line 49) | def two_track_4state_test():
  function single_track_6state_test (line 88) | def single_track_6state_test():

FILE: paper_experiments/utils/track.py
  class TrackState (line 9) | class TrackState:
  class Track (line 24) | class Track:
    method __init__ (line 70) | def __init__(self, mean, covariance, model_probabilities, track_id, n_...
    method to_tlwh (line 107) | def to_tlwh(self, kf):
    method to_tlbr (line 129) | def to_tlbr(self):
    method update_feature (line 143) | def update_feature(self, img, appearance_model):
    method predict (line 168) | def predict(self, kf):
    method update (line 186) | def update(self, kf, detection, detections_3d=None,
    method delete_track (line 239) | def delete_track(self):
    method mark_missed (line 242) | def mark_missed(self):
    method update_velocity (line 250) | def update_velocity(self, new_detection):
    method is_tentative (line 265) | def is_tentative(self):
    method is_confirmed (line 270) | def is_confirmed(self):
    method is_deleted (line 274) | def is_deleted(self):
    method is_exiting (line 278) | def is_exiting(self):
    method mark_exiting (line 281) | def mark_exiting(self):
    method feature_update (line 284) | def feature_update(self, detections, detection_idx, lstm, JPDA=False, ...

FILE: paper_experiments/utils/track_3d.py
  class TrackState (line 6) | class TrackState:
  class Track_3d (line 21) | class Track_3d:
    method __init__ (line 67) | def __init__(self, mean, covariance, track_id, n_init, max_age,
    method to_tlwh3d (line 96) | def to_tlwh3d(self):
    method to_tlwh (line 109) | def to_tlwh(self, kf):
    method predict (line 124) | def predict(self, kf):
    method update (line 139) | def update(self, kf, detection, compare_2d=False,
    method mark_missed (line 178) | def mark_missed(self):
    method is_tentative (line 186) | def is_tentative(self):
    method is_confirmed (line 191) | def is_confirmed(self):
    method is_deleted (line 195) | def is_deleted(self):

FILE: paper_experiments/utils/tracker.py
  class Tracker (line 16) | class Tracker:
    method __init__ (line 46) | def __init__(self, max_age=5, n_init=3,
    method gated_metric (line 81) | def gated_metric(self, tracks, dets, track_indices, detection_indices,...
    method predict (line 100) | def predict(self):
    method update (line 109) | def update(self, cur_frame, detections, compare_2d = False):
    method _match (line 170) | def _match(self, detections, compare_2d):
    method _initiate_track (line 207) | def _initiate_track(self, detection, flow=None):
    method prune_tracks (line 221) | def prune_tracks(self):

FILE: paper_experiments/utils/tracker_3d.py
  class Tracker_3d (line 14) | class Tracker_3d:
    method __init__ (line 44) | def __init__(self, max_age=30, n_init=3,
    method gated_metric (line 68) | def gated_metric(self, tracks, dets, track_indices, detection_indices,...
    method predict (line 97) | def predict(self):
    method update (line 106) | def update(self, input_img, detections, compare_2d):
    method _match (line 159) | def _match(self, detections, compare_2d):
    method _initiate_track (line 195) | def _initiate_track(self, detection):
    method prune_tracks (line 205) | def prune_tracks(self):

FILE: paper_experiments/utils/tracking_utils.py
  function create_detector (line 14) | def create_detector(config_path, weight_path, cuda):
  function get_depth_patches (line 23) | def get_depth_patches(point_cloud, box_3d, ids_3d, rot_angles, num_point...
  function non_max_suppression_3D_prime (line 63) | def non_max_suppression_3D_prime(detections, boxes_3d, ids_3d, ids_2d, n...
  function non_max_suppression_3D (line 77) | def non_max_suppression_3D(depth_patches, ids_3d, ids_2d, nms_thresh = 1...
  function iou_3d (line 108) | def iou_3d(patch_1, patch_2):
  function convert_detections (line 128) | def convert_detections(detections, features, appearance_features, detect...
  function combine_features (line 147) | def combine_features(features, depth_features, ids_3d, combination_model...
  function filter (line 164) | def filter(detections):

FILE: paper_experiments/utils/visualise.py
  function draw_track (line 9) | def draw_track(bbox, track = None, bbox_colors = None, det = True,
  function draw_detection (line 38) | def draw_detection(detection, color='k'):
  function draw_ellipse (line 47) | def draw_ellipse(track, color):
  function draw_velocity (line 73) | def draw_velocity(track, color):
  function draw_box3d (line 84) | def draw_box3d(mu, color, alpha, facecolor='none', ax=None):
  function draw_velocity_3d (line 105) | def draw_velocity_3d(track, color, ax=None):
  function draw_ellipse3d (line 116) | def draw_ellipse3d(covariance, x, y, color, ax=None):
  function draw_track3d (line 136) | def draw_track3d(track, color, ax=None):
  function draw_detection3d (line 148) | def draw_detection3d(det, color, ax=None):

FILE: paper_experiments/utils/yolo_utils/datasets.py
  class ImageFolder (line 19) | class ImageFolder(Dataset):
    method __init__ (line 20) | def __init__(self, folder_path, img_size=416):
    method __getitem__ (line 24) | def __getitem__(self, index):
    method __len__ (line 45) | def __len__(self):
  class ListDataset (line 49) | class ListDataset(Dataset):
    method __init__ (line 50) | def __init__(self, list_path, img_size=416):
    method __getitem__ (line 57) | def __getitem__(self, index):
    method __len__ (line 120) | def __len__(self):

FILE: paper_experiments/utils/yolo_utils/parse_config.py
  function parse_model_config (line 3) | def parse_model_config(path):
  function parse_data_config (line 23) | def parse_data_config(path):

FILE: paper_experiments/utils/yolo_utils/utils.py
  function load_classes (line 14) | def load_classes(path):
  function weights_init_normal (line 23) | def weights_init_normal(m):
  function compute_ap (line 32) | def compute_ap(recall, precision):
  function bbox_iou (line 60) | def bbox_iou(box1, box2, x1y1x2y2=True):
  function bbox_iou_numpy (line 93) | def bbox_iou_numpy(box1, box2):
  function non_max_suppression (line 127) | def non_max_suppression(prediction, num_classes, conf_thres=0.5, nms_thr...
  function build_targets (line 187) | def build_targets(
  function to_categorical (line 256) | def to_categorical(y, num_classes):

FILE: src/3d_detector.py
  class Detector_3d (line 28) | class Detector_3d:
    method __init__ (line 29) | def __init__(self):
    method get_3d_feature (line 60) | def get_3d_feature(self, y1_bboxes, pointcloud_upper, pointcloud_lower):
    method publish_pointcloud_from_array (line 169) | def publish_pointcloud_from_array(self, pointcloud, publisher, frame =...
    method cleanup (line 178) | def cleanup(self):
  function main (line 181) | def main(args):

FILE: src/EKF.py
  function squared_mahalanobis_distance (line 79) | def squared_mahalanobis_distance(mean, covariance, measurements):
  class EKF (line 95) | class EKF(object):
    method __init__ (line 101) | def __init__(self):
    method initiate (line 104) | def initiate(self, measurement):
    method predict_mean (line 121) | def predict_mean(self, mean):
    method get_process_noise (line 127) | def get_process_noise(self, mean, covariance):
    method predict_covariance (line 130) | def predict_covariance(self, mean, covariance):
    method project_mean (line 133) | def project_mean(self, mean):
    method project_cov (line 138) | def project_cov(self, mean, covariance):
    method predict (line 141) | def predict(self, mean, covariance):
    method get_innovation_cov (line 165) | def get_innovation_cov(self, covariance):
    method project (line 168) | def project(self, mean, covariance):
    method update (line 189) | def update(self, mean, covariance, measurement_t, marginalization=None...

FILE: src/JPDA_matching.py
  function get_unmatched (line 8) | def get_unmatched(all_idx, matches, i, marginalization=None):
  class Matcher (line 19) | class Matcher:
    method __init__ (line 21) | def __init__(self, detections, marginalizations, confirmed_tracks,
    method match (line 31) | def match(self):
    method get_matches (line 37) | def get_matches(self):
    method get_unmatched_tracks (line 51) | def get_unmatched_tracks(self):
    method get_unmatched_detections (line 55) | def get_unmatched_detections(self):
    method max_match (line 58) | def max_match(self):
    method max_and_threshold_matching (line 84) | def max_and_threshold_matching(self):
    method hungarian (line 103) | def hungarian(self):

FILE: src/aligned_reid_model.py
  class Model (line 10) | class Model(nn.Module):
    method __init__ (line 11) | def __init__(self, local_conv_out_channels=128, num_classes=None):
    method forward (line 24) | def forward(self, x):
  function conv3x3 (line 55) | def conv3x3(in_planes, out_planes, stride=1):
  class BasicBlock (line 61) | class BasicBlock(nn.Module):
    method __init__ (line 64) | def __init__(self, inplanes, planes, stride=1, downsample=None):
    method forward (line 74) | def forward(self, x):
  class Bottleneck (line 93) | class Bottleneck(nn.Module):
    method __init__ (line 96) | def __init__(self, inplanes, planes, stride=1, downsample=None):
    method forward (line 109) | def forward(self, x):
  class ResNet (line 132) | class ResNet(nn.Module):
    method __init__ (line 134) | def __init__(self, block, layers):
    method _make_layer (line 155) | def _make_layer(self, block, planes, blocks, stride=1):
    method forward (line 172) | def forward(self, x):
  function remove_fc (line 186) | def remove_fc(state_dict):
  function resnet18 (line 195) | def resnet18(pretrained=False):
  function resnet34 (line 207) | def resnet34(pretrained=False):
  function resnet50 (line 219) | def resnet50(pretrained=False):
  function resnet101 (line 231) | def resnet101(pretrained=False):
  function resnet152 (line 244) | def resnet152(pretrained=False):

FILE: src/aligned_reid_utils.py
  function time_str (line 16) | def time_str(fmt=None):
  function load_pickle (line 22) | def load_pickle(path):
  function save_pickle (line 34) | def save_pickle(obj, path):
  function save_mat (line 41) | def save_mat(ndarray, path):
  function to_scalar (line 46) | def to_scalar(vt):
  function transfer_optim_state (line 57) | def transfer_optim_state(state, device_id=-1):
  function may_transfer_optims (line 82) | def may_transfer_optims(optims, device_id=-1):
  function may_transfer_modules_optims (line 95) | def may_transfer_modules_optims(modules_and_or_optims, device_id=-1):
  class TransferVarTensor (line 114) | class TransferVarTensor(object):
    method __init__ (line 117) | def __init__(self, device_id=-1):
    method __call__ (line 120) | def __call__(self, var_or_tensor):
  class TransferModulesOptims (line 125) | class TransferModulesOptims(object):
    method __init__ (line 128) | def __init__(self, device_id=-1):
    method __call__ (line 131) | def __call__(self, modules_and_or_optims):
  function set_devices (line 135) | def set_devices(sys_device_ids):
  function set_devices_for_ml (line 164) | def set_devices_for_ml(sys_device_ids):
  function load_ckpt (line 229) | def load_ckpt(modules_optims, ckpt_file, load_to_cpu=True, verbose=True):
  function save_ckpt (line 252) | def save_ckpt(modules_optims, ep, scores, ckpt_file):
  function load_state_dict (line 273) | def load_state_dict(model, src_state_dict):
  function is_iterable (line 314) | def is_iterable(obj):
  function may_set_mode (line 318) | def may_set_mode(maybe_modules, mode):
  function may_make_dir (line 331) | def may_make_dir(path):
  class AverageMeter (line 347) | class AverageMeter(object):
    method __init__ (line 351) | def __init__(self):
    method reset (line 357) | def reset(self):
    method update (line 363) | def update(self, val, n=1):
  class RunningAverageMeter (line 370) | class RunningAverageMeter(object):
    method __init__ (line 373) | def __init__(self, hist=0.99):
    method reset (line 378) | def reset(self):
    method update (line 382) | def update(self, val):
  class RecentAverageMeter (line 390) | class RecentAverageMeter(object):
    method __init__ (line 393) | def __init__(self, hist_size=100):
    method reset (line 398) | def reset(self):
    method update (line 402) | def update(self, val):
    method avg (line 409) | def avg(self):
  function get_model_wrapper (line 414) | def get_model_wrapper(model, multi_gpu):
  class ReDirectSTD (line 422) | class ReDirectSTD(object):
    method __init__ (line 442) | def __init__(self, fpath=None, console='stdout', immediately_visible=F...
    method __del__ (line 463) | def __del__(self):
    method __enter__ (line 466) | def __enter__(self):
    method __exit__ (line 469) | def __exit__(self, *args):
    method write (line 472) | def write(self, msg):
    method flush (line 484) | def flush(self):
    method close (line 491) | def close(self):
  function set_seed (line 497) | def set_seed(seed):
  function print_array (line 514) | def print_array(array, fmt='{:.2f}', end=' '):
  function str2bool (line 525) | def str2bool(v):
  function tight_float_str (line 529) | def tight_float_str(x, fmt='{:.4f}'):
  function find_index (line 533) | def find_index(seq, item):
  function adjust_lr_exp (line 540) | def adjust_lr_exp(optimizer, base_lr, ep, total_ep, start_decay_at_ep):
  function adjust_lr_staircase (line 572) | def adjust_lr_staircase(optimizer, base_lr, ep, decay_at_epochs, factor):
  function measure_time (line 608) | def measure_time(enter_msg):
  function generate_features (line 615) | def generate_features(appearance_model, patches):
  function generate_features_batched (line 626) | def generate_features_batched(appearance_model, patches, object_ids = No...
  function get_image_patches (line 674) | def get_image_patches(input_img, detections):
  function create_appearance_model (line 689) | def create_appearance_model(alignreid_checkpoint, resnet_reid_checkpoint...

FILE: src/calibration.py
  class Calibration (line 8) | class Calibration(object):
    method __init__ (line 33) | def __init__(self, calib_filepath):
    method read_calib_file (line 71) | def read_calib_file(self, filepath):
    method read_calib_from_video (line 92) | def read_calib_from_video(self, calib_root_dir):
    method cart2hom (line 107) | def cart2hom(self, pts_3d):
    method cart2hom_torch (line 115) | def cart2hom_torch(self, pts_3d):
    method project_velo_to_ref (line 123) | def project_velo_to_ref(self, pts_3d_velo):
    method project_ref_to_velo (line 127) | def project_ref_to_velo(self, pts_3d_ref):
    method project_rect_to_ref (line 131) | def project_rect_to_ref(self, pts_3d_rect):
    method project_ref_to_rect (line 135) | def project_ref_to_rect(self, pts_3d_ref):
    method project_ref_to_rect_torch (line 139) | def project_ref_to_rect_torch(self, pts_3d_ref):
    method project_rect_to_velo (line 143) | def project_rect_to_velo(self, pts_3d_rect):
    method project_velo_to_rect (line 150) | def project_velo_to_rect(self, pts_3d_velo):
    method project_rect_to_image (line 157) | def project_rect_to_image(self, pts_3d_rect):
    method project_rect_to_image_torch (line 167) | def project_rect_to_image_torch(self, pts_3d_rect):
    method project_ref_to_image_torch (line 177) | def project_ref_to_image_torch(self, pts_3d_ref):
    method project_velo_to_image (line 187) | def project_velo_to_image(self, pts_3d_velo):
    method project_image_to_rect (line 197) | def project_image_to_rect(self, uv_depth):
    method project_image_to_velo (line 211) | def project_image_to_velo(self, uv_depth):
  function rotx (line 215) | def rotx(t):
  function roty (line 224) | def roty(t):
  function rotz (line 233) | def rotz(t):
  function transform_from_rot_trans (line 242) | def transform_from_rot_trans(R, t):
  function inverse_rigid_trans (line 249) | def inverse_rigid_trans(Tr):
  function read_label (line 258) | def read_label(label_filename):
  function load_image (line 263) | def load_image(img_filename):
  function load_velo_scan (line 266) | def load_velo_scan(velo_filename):
  function project_to_image (line 271) | def project_to_image(pts_3d, P):
  function compute_box_3d (line 291) | def compute_box_3d(obj, P):
  function compute_orientation_3d (line 329) | def compute_orientation_3d(obj, P):
  function draw_projected_box3d (line 358) | def draw_projected_box3d(image, qs, color=(255,255,255), thickness=2):
  class OmniCalibration (line 385) | class OmniCalibration(Calibration):
    method __init__ (line 386) | def __init__(self, calib_folder):
    method project_ref_to_image_torch (line 402) | def project_ref_to_image_torch(self, pointcloud):
    method project_image_to_rect (line 413) | def project_image_to_rect(self, uvdepth):
    method project_velo_to_ref (line 422) | def project_velo_to_ref(self, pointcloud):
    method move_lidar_to_camera_frame (line 430) | def move_lidar_to_camera_frame(self, pointcloud, upper = True):
    method calculate_median_param_value (line 450) | def calculate_median_param_value(self, param):

FILE: src/combination_model.py
  class CombiNet (line 6) | class CombiNet(nn.Module):
    method __init__ (line 7) | def __init__(self, in_dim = 2560, hidden_units = 512, out_dim = 2560):
    method forward (line 16) | def forward(self, x):
  class CombiLSTM (line 30) | class CombiLSTM(nn.Module):
    method __init__ (line 31) | def __init__(self, in_dim = 2560, hidden_units = 512, out_dim = 2560):
    method forward (line 43) | def forward(self, x, hidden = None):
  function weight_init (line 65) | def weight_init(m):

FILE: src/deep_sort_utils.py
  function non_max_suppression (line 6) | def non_max_suppression(boxes, max_bbox_overlap, scores=None):

FILE: src/detection.py
  class Detection (line 5) | class Detection(object):
    method __init__ (line 29) | def __init__(self, tlwh, box_3d, confidence, appearance_feature, featu...
    method to_tlbr (line 44) | def to_tlbr(self):
    method to_xyah (line 52) | def to_xyah(self):
    method to_xywh (line 60) | def to_xywh(self):
    method get_3d_distance (line 67) | def get_3d_distance(self):

FILE: src/distances.py
  function norm2squared_matrix (line 10) | def norm2squared_matrix(objs, hyps, max_d2=float('inf')):
  function iou_matrix (line 52) | def iou_matrix(objs, hyps, max_iou=1.):
  function find_area (line 112) | def find_area(vertices):
  function get_angle (line 118) | def get_angle(p):
  function clip_polygon (line 125) | def clip_polygon(box1, box2):
  function compute_intersection_point (line 163) | def compute_intersection_point(pt1, pt2, line1):
  function point_inside_edge (line 189) | def point_inside_edge(pt, edge):
  function iou_matrix_3d (line 197) | def iou_matrix_3d(objs, hyps, max_iou=1.):

FILE: src/double_measurement_kf.py
  class KF_3D (line 18) | class KF_3D(kf_2d.KalmanFilter2D):
    method __init__ (line 33) | def __init__(self, calib, pos_weight_3d, pos_weight, velocity_weight, ...
    method initiate (line 64) | def initiate(self, measurement_3d):
    method get_process_noise (line 83) | def get_process_noise(self, mean):
    method get_2d_measurement_noise (line 102) | def get_2d_measurement_noise(self, measurement_2d):
    method get_3d_measurement_noise (line 114) | def get_3d_measurement_noise(self, measurement):
    method gating_distance (line 130) | def gating_distance(self, mean, covariance, measurements,
    method project_cov (line 182) | def project_cov(self, mean, covariance):
    method project_cov_2d (line 191) | def project_cov_2d(self, mean, covariance, H_2d):
    method update (line 200) | def update(self, mean, covariance, measurement_2d, measurement_3d = No...
    method get_2d_measurement_matrix (line 312) | def get_2d_measurement_matrix(self, mean, corner_points, corner_points...
    method jacobian (line 349) | def jacobian(self, pt_3d):
    method jacobian_omni (line 356) | def jacobian_omni(self, pt_3d):
    method calculate_corners (line 370) | def calculate_corners(self, box):
    method corner_jacobian (line 389) | def corner_jacobian(self, pt_3d, corner_idx):
    method project_2d (line 416) | def project_2d(self, pts_3d):
  function swap (line 436) | def swap(detections_3d, iou, idx, swap_prob = 0):

FILE: src/evaluation/distances 2.py
  function norm2squared_matrix (line 10) | def norm2squared_matrix(objs, hyps, max_d2=float('inf')):
  function iou_matrix (line 52) | def iou_matrix(objs, hyps, max_iou=1.):
  function find_area (line 112) | def find_area(vertices):
  function get_angle (line 118) | def get_angle(p):
  function clip_polygon (line 125) | def clip_polygon(box1, box2):
  function sort_points (line 163) | def sort_points(pts, center):
  function compute_intersection_point (line 169) | def compute_intersection_point(pt1, pt2, line1):
  function point_inside_edge (line 195) | def point_inside_edge(pt, edge):
  function iou_matrix_3d (line 203) | def iou_matrix_3d(objs, hyps, max_iou=1.):

FILE: src/evaluation/distances.py
  function norm2squared_matrix (line 10) | def norm2squared_matrix(objs, hyps, max_d2=float('inf')):
  function iou_matrix (line 52) | def iou_matrix(objs, hyps, max_iou=1.):
  function find_area (line 112) | def find_area(vertices):
  function get_angle (line 118) | def get_angle(p):
  function clip_polygon (line 125) | def clip_polygon(box1, box2):
  function sort_points (line 163) | def sort_points(pts, center):
  function compute_intersection_point (line 169) | def compute_intersection_point(pt1, pt2, line1):
  function point_inside_edge (line 195) | def point_inside_edge(pt, edge):
  function iou_matrix_3d (line 203) | def iou_matrix_3d(objs, hyps, max_iou=1.):

FILE: src/featurepointnet_model.py
  class FPointNet (line 13) | class FPointNet():
    method __init__ (line 14) | def __init__(self, config_path):
    method __call__ (line 57) | def __call__(self, input_point_cloud, rot_angle, peds=False):
    method get_instance_seg_v1_net (line 126) | def get_instance_seg_v1_net(self, point_cloud, one_hot_vec, is_trainin...
    method get_3d_box_estimation_v1_net (line 197) | def get_3d_box_estimation_v1_net(self, object_point_cloud, one_hot_vec...
    method get_model (line 246) | def get_model(self, point_cloud, one_hot_vec, is_training, bn_decay=No...
    method get_depth_feature_op (line 294) | def get_depth_feature_op(self, is_training):
    method get_depth_feature (line 317) | def get_depth_feature(self, object_pointcloud):
    method softmax (line 323) | def softmax(self, x):
  function create_depth_model (line 330) | def create_depth_model(model, config_path):

FILE: src/featurepointnet_model_util.py
  function tf_gather_object_pc (line 39) | def tf_gather_object_pc(point_cloud, mask, npoints=512):
  function get_box3d_corners_helper (line 72) | def get_box3d_corners_helper(centers, headings, sizes):
  function get_box3d_corners (line 99) | def get_box3d_corners(center, heading_residuals, size_residuals):
  function huber_loss (line 124) | def huber_loss(error, delta):
  function parse_output_to_tensors (line 132) | def parse_output_to_tensors(output, end_points):
  function from_prediction_to_label_format (line 170) | def from_prediction_to_label_format(center, angle_class, angle_res,\
  function size2class (line 179) | def size2class(size, type_name):
  function class2size (line 194) | def class2size(pred_cls, residual):
  function angle2class (line 199) | def angle2class(angle, num_class):
  function class2angle (line 219) | def class2angle(pred_cls, residual, num_class, to_label_format=True):
  function rotate_pc_along_y (line 230) | def rotate_pc_along_y(pc, rot_angle):
  function rotate_pc_along_y_torch (line 247) | def rotate_pc_along_y_torch(pc, rot_angle):
  function placeholder_inputs (line 270) | def placeholder_inputs(batch_size, num_point):
  function point_cloud_masking (line 295) | def point_cloud_masking(point_cloud, logits, end_points, xyz_only=True):
  function get_center_regression_net (line 343) | def get_center_regression_net(object_point_cloud, one_hot_vec,
  function softmax (line 380) | def softmax(x):
  function get_loss (line 388) | def get_loss(mask_label, center_label, \
  function get_lidar_in_image_fov (line 510) | def get_lidar_in_image_fov(pc_velo, calib, xmin, ymin, xmax, ymax,
  function preprocess_pointcloud (line 524) | def preprocess_pointcloud(detections, point_cloud, pc_image_coord,
  function generate_detections_3d (line 576) | def generate_detections_3d(detector, detections_2d, point_cloud, calib, ...
  function convert_depth_features (line 590) | def convert_depth_features(depth_features_orig, ids_3d):

FILE: src/featurepointnet_tf_util.py
  function _variable_on_cpu (line 10) | def _variable_on_cpu(name, shape, initializer, use_fp16=False):
  function _variable_with_weight_decay (line 24) | def _variable_with_weight_decay(name, shape, stddev, wd, use_xavier=True):
  function conv1d (line 52) | def conv1d(inputs,
  function conv2d (line 120) | def conv2d(inputs,
  function conv2d_transpose (line 188) | def conv2d_transpose(inputs,
  function conv3d (line 268) | def conv3d(inputs,
  function fully_connected (line 327) | def fully_connected(inputs,
  function max_pool2d (line 366) | def max_pool2d(inputs,
  function avg_pool2d (line 391) | def avg_pool2d(inputs,
  function max_pool3d (line 417) | def max_pool3d(inputs,
  function avg_pool3d (line 442) | def avg_pool3d(inputs,
  function batch_norm_template_unused (line 468) | def batch_norm_template_unused(inputs, is_training, scope, moments_dims,...
  function batch_norm_template (line 512) | def batch_norm_template(inputs, is_training, scope, moments_dims_unused,...
  function batch_norm_for_fc (line 534) | def batch_norm_for_fc(inputs, is_training, bn_decay, scope):
  function batch_norm_for_conv1d (line 548) | def batch_norm_for_conv1d(inputs, is_training, bn_decay, scope, data_for...
  function batch_norm_for_conv2d (line 565) | def batch_norm_for_conv2d(inputs, is_training, bn_decay, scope, data_for...
  function batch_norm_for_conv3d (line 580) | def batch_norm_for_conv3d(inputs, is_training, bn_decay, scope):
  function dropout (line 594) | def dropout(inputs,

FILE: src/iou_matching.py
  function iou (line 8) | def iou(bbox, candidates):
  function iou_cost (line 43) | def iou_cost(tracks, detections, track_indices=None,

FILE: src/kf_2d.py
  class KalmanFilter2D (line 8) | class KalmanFilter2D(EKF.EKF):
    method __init__ (line 25) | def __init__(self, pos_weight, velocity_weight, std_process, std_measu...
    method initiate (line 47) | def initiate(self, measurement, flow):
    method predict_mean (line 87) | def predict_mean(self, mean):
    method predict_covariance (line 93) | def predict_covariance(self, mean, covariance):
    method get_process_noise (line 100) | def get_process_noise(self, mean):
    method project_mean (line 118) | def project_mean(self, mean):
    method get_measurement_noise (line 126) | def get_measurement_noise(self, measurement):
    method project_cov (line 138) | def project_cov(self, mean, covariance):
    method gating_distance (line 147) | def gating_distance(self, mean, covariance, measurements,
  class RandomWalkKalmanFilter2D (line 187) | class RandomWalkKalmanFilter2D(KalmanFilter2D): #TODO UPDATE THIS DOCUME...
    method __init__ (line 203) | def __init__(self, pos_weight, velocity_weight, std_process, std_measu...

FILE: src/linear_assignment.py
  function min_marg_matching (line 15) | def min_marg_matching(marginalizations, track_indices=None, max_distance...
  function min_cost_matching (line 61) | def min_cost_matching(
  function JPDA (line 142) | def JPDA(
  function calculate_entropy (line 208) | def calculate_entropy(matrix, idx, idy):
  function get_JPDA_output (line 216) | def get_JPDA_output(cluster, cost_matrix, dummy_node_cost_app, dummy_nod...
  function matching_cascade (line 273) | def matching_cascade(
  function gate_cost_matrix (line 339) | def gate_cost_matrix(
  function find_clusters (line 401) | def find_clusters(cost_matrix, cutoff):

FILE: src/mbest_ilp.py
  function ilp_assignment (line 16) | def ilp_assignment(model):
  function initialize_model (line 29) | def initialize_model(cost_matrix, cutoff, model = None):
  function cache (line 59) | def cache(func):
  function num_solutions (line 74) | def num_solutions(cost_matrix):
  function enumerate_solutions (line 85) | def enumerate_solutions(cost_matrix, cutoff, num_solutions):
  function new_m_best_sol (line 104) | def new_m_best_sol(cost_matrix, m_sol, cutoff, model = None):
  function linear_assignment_wrapper (line 189) | def linear_assignment_wrapper(a):

FILE: src/nn_matching.py
  function _pdist (line 6) | def _pdist(a, b):
  function _cosine_distance (line 32) | def _cosine_distance(a, b, data_is_normalized=False):
  function _cosine_distance_torch (line 57) | def _cosine_distance_torch(a, b, data_is_normalized=False):
  function _nn_euclidean_distance (line 66) | def _nn_euclidean_distance(x, y):
  function _nn_euclidean_distance_torch (line 86) | def _nn_euclidean_distance_torch(x, y):
  function _nn_cosine_distance (line 111) | def _nn_cosine_distance(x, y):
  function _nn_cosine_distance_torch (line 131) | def _nn_cosine_distance_torch(x,y):
  class NearestNeighborDistanceMetric (line 138) | class NearestNeighborDistanceMetric(object):
    method __init__ (line 162) | def __init__(self, metric, budget=None):
    method partial_fit (line 178) | def partial_fit(self, features, features_2d, targets, targets_2d, acti...
    method distance (line 209) | def distance(self, features, targets, compare_2d=False):
    method distance_torch (line 235) | def distance_torch(self, features, targets, compare_2d=False):
    method check_samples (line 248) | def check_samples(self, targets):

FILE: src/pointnet_model.py
  class PointNet (line 9) | class PointNet():
    method __init__ (line 10) | def __init__(self, config_path):
    method __call__ (line 37) | def __call__(self, input_point_cloud):
    method placeholder_inputs (line 43) | def placeholder_inputs(self, batch_size, num_point):
    method get_model (line 49) | def get_model(self, point_cloud, is_training, bn_decay=None):
    method get_loss (line 96) | def get_loss(self, pred, label, end_points, reg_weight=0.001):

FILE: src/template 2.py
  class Appearance_Features (line 19) | class Appearance_Features:
    method __init__ (line 20) | def __init__(self):
    method get_2d_feature (line 39) | def get_2d_feature(self, y1_bboxes, ros_image):
    method cleanup (line 86) | def cleanup(self):
  function main (line 89) | def main(args):

FILE: src/template.py
  class Appearance_Features (line 19) | class Appearance_Features:
    method __init__ (line 20) | def __init__(self):
    method get_2d_feature (line 39) | def get_2d_feature(self, y1_bboxes, ros_image):
    method cleanup (line 86) | def cleanup(self):
  function main (line 89) | def main(args):

FILE: src/track_3d 2.py
  class TrackState (line 6) | class TrackState:
  class Track_3d (line 21) | class Track_3d:
    method __init__ (line 67) | def __init__(self, mean, covariance, track_id, n_init, max_age,
    method to_tlwh3d (line 97) | def to_tlwh3d(self):
    method to_tlwh (line 112) | def to_tlwh(self, kf):
    method predict (line 127) | def predict(self, kf):
    method update (line 142) | def update(self, kf, detection, compare_2d=False,
    method mark_missed (line 191) | def mark_missed(self):
    method is_tentative (line 199) | def is_tentative(self):
    method is_confirmed (line 204) | def is_confirmed(self):
    method is_deleted (line 208) | def is_deleted(self):
    method feature_update (line 212) | def feature_update(self, detections, detection_idx, lstm, JPDA=False, ...
    method get_cov (line 244) | def get_cov(self):

FILE: src/track_3d.py
  class TrackState (line 6) | class TrackState:
  class Track_3d (line 21) | class Track_3d:
    method __init__ (line 67) | def __init__(self, mean, covariance, track_id, n_init, max_age,
    method to_tlwh3d (line 97) | def to_tlwh3d(self):
    method to_tlwh (line 112) | def to_tlwh(self, kf):
    method predict (line 127) | def predict(self, kf):
    method update (line 142) | def update(self, kf, detection, compare_2d=False,
    method mark_missed (line 191) | def mark_missed(self):
    method is_tentative (line 199) | def is_tentative(self):
    method is_confirmed (line 204) | def is_confirmed(self):
    method is_deleted (line 208) | def is_deleted(self):
    method feature_update (line 212) | def feature_update(self, detections, detection_idx, lstm, JPDA=False, ...
    method get_cov (line 244) | def get_cov(self):

FILE: src/tracker_3d 2.py
  class Tracker_3d (line 15) | class Tracker_3d:
    method __init__ (line 45) | def __init__(self, max_age=30, n_init=3,
    method gated_metric (line 71) | def gated_metric(self, tracks, dets, track_indices, detection_indices,...
    method predict (line 99) | def predict(self):
    method update (line 108) | def update(self, input_img, detections):
    method _match (line 148) | def _match(self, detections):
    method _initiate_track (line 213) | def _initiate_track(self, detection):
    method prune_tracks (line 223) | def prune_tracks(self):

FILE: src/tracker_3d.py
  class Tracker_3d (line 15) | class Tracker_3d:
    method __init__ (line 45) | def __init__(self, max_age=30, n_init=3,
    method gated_metric (line 71) | def gated_metric(self, tracks, dets, track_indices, detection_indices,...
    method predict (line 99) | def predict(self):
    method update (line 108) | def update(self, input_img, detections):
    method _match (line 148) | def _match(self, detections):
    method _initiate_track (line 213) | def _initiate_track(self, detection):
    method prune_tracks (line 223) | def prune_tracks(self):

FILE: src/tracker_3d_node 2.py
  class Tracker_3D_node (line 30) | class Tracker_3D_node:
    method __init__ (line 31) | def __init__(self):
    method do_3d_tracking (line 87) | def do_3d_tracking(self, detections_2d, detections_3d):
    method find_time_diff_2d (line 157) | def find_time_diff_2d(self, a):
    method find_time_diff_3d (line 161) | def find_time_diff_3d(self, a):
    method cleanup (line 165) | def cleanup(self):
  function main (line 174) | def main(args):

FILE: src/tracker_3d_node.py
  class Tracker_3D_node (line 30) | class Tracker_3D_node:
    method __init__ (line 31) | def __init__(self):
    method do_3d_tracking (line 87) | def do_3d_tracking(self, detections_2d, detections_3d):
    method find_time_diff_2d (line 157) | def find_time_diff_2d(self, a):
    method find_time_diff_3d (line 161) | def find_time_diff_3d(self, a):
    method cleanup (line 165) | def cleanup(self):
  function main (line 174) | def main(args):

FILE: src/tracking_utils 2.py
  function create_detector (line 13) | def create_detector(config_path, weight_path, cuda):
  function get_depth_patches (line 22) | def get_depth_patches(point_cloud, box_3d, ids_3d, rot_angles, num_point...
  function non_max_suppression_3D_prime (line 62) | def non_max_suppression_3D_prime(detections, boxes_3d, ids_3d, ids_2d, n...
  function non_max_suppression_3D (line 76) | def non_max_suppression_3D(depth_patches, ids_3d, ids_2d, nms_thresh = 1...
  function iou_3d (line 107) | def iou_3d(patch_1, patch_2):
  function convert_detections (line 127) | def convert_detections(detections, features, appearance_features, detect...
  function combine_features (line 146) | def combine_features(features, depth_features, ids_3d, combination_model...
  function filter (line 164) | def filter(detections):

FILE: src/tracking_utils.py
  function create_detector (line 13) | def create_detector(config_path, weight_path, cuda):
  function get_depth_patches (line 22) | def get_depth_patches(point_cloud, box_3d, ids_3d, rot_angles, num_point...
  function non_max_suppression_3D_prime (line 62) | def non_max_suppression_3D_prime(detections, boxes_3d, ids_3d, ids_2d, n...
  function non_max_suppression_3D (line 76) | def non_max_suppression_3D(depth_patches, ids_3d, ids_2d, nms_thresh = 1...
  function iou_3d (line 107) | def iou_3d(patch_1, patch_2):
  function convert_detections (line 127) | def convert_detections(detections, features, appearance_features, detect...
  function combine_features (line 146) | def combine_features(features, depth_features, ids_3d, combination_model...
  function filter (line 164) | def filter(detections):
Condensed preview — 100 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (761K chars).
[
  {
    "path": "CMakeLists.txt",
    "chars": 6977,
    "preview": "cmake_minimum_required(VERSION 2.8.3)\nproject(jpda_rospack)\n\n## Compile as C++11, supported in ROS Kinetic and newer\n# a"
  },
  {
    "path": "LICENSE",
    "chars": 1091,
    "preview": "MIT License\n\nCopyright (c) 2020 Stanford Vision and Learning Group\n\nPermission is hereby granted, free of charge, to any"
  },
  {
    "path": "README.md",
    "chars": 3833,
    "preview": "# JRMOT ROS package\n\nThe repository contains the code for the work \"JRMOT: A Real-Time 3D Multi-Object Tracker and a New"
  },
  {
    "path": "calib/cameras.yaml",
    "chars": 3432,
    "preview": "stitching:\n  radius: 3360000\n  rotation: 0\n  scalewidth: 1831\n  crop: 1\ncameras:\n  # camera order matters!\n  sensor_0:\n "
  },
  {
    "path": "calib/defaults.yaml",
    "chars": 877,
    "preview": "calibrated:\n  # the lidar_to_rgb parameters allow tweaking of the transformation between lidar and rgb frames\n  # the de"
  },
  {
    "path": "config/featurepointnet.cfg",
    "chars": 113,
    "preview": "[general]\nnum_point = 1024\nmodel_path = /home/sibot/jr2_catkin_ws/src/jpda_rospack/src/fpointnet_jrdb/model.ckpt\n"
  },
  {
    "path": "launch/jpda_tracker.launch",
    "chars": 1457,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<launch>\n  <!-- Console launch prefix -->\n  <arg name=\"output\"        default=\"s"
  },
  {
    "path": "msg/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "msg/detection2d_with_feature.msg",
    "chars": 711,
    "preview": "# This message contains a 2D bounding box corresponding to the detection of a person\n# Also contains the feature of this"
  },
  {
    "path": "msg/detection2d_with_feature_array.msg",
    "chars": 66,
    "preview": "Header header\ndetection2d_with_feature[] detection2d_with_features"
  },
  {
    "path": "msg/detection3d_with_feature.msg",
    "chars": 879,
    "preview": "# This message contains a 3D bounding box corresponding to the detection of a person\n# Also contains the feature of this"
  },
  {
    "path": "msg/detection3d_with_feature_array.msg",
    "chars": 66,
    "preview": "Header header\ndetection3d_with_feature[] detection3d_with_features"
  },
  {
    "path": "package.xml",
    "chars": 3010,
    "preview": "<?xml version=\"1.0\"?>\n<package format=\"2\">\n  <name>jpda_rospack</name>\n  <version>0.0.1</version>\n  <description>The jpd"
  },
  {
    "path": "paper_experiments/models/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "paper_experiments/models/aligned_reid_model.py",
    "chars": 7458,
    "preview": "import torch\nimport torch.nn as nn\nimport torch.nn.init as init\nimport torch.nn.functional as F\nimport torch.utils.model"
  },
  {
    "path": "paper_experiments/models/combination_model.py",
    "chars": 2103,
    "preview": "import pdb\n\nimport numpy as np\nimport torch.nn as nn\n\nclass CombiNet(nn.Module):\n\tdef __init__(self, in_dim = 2560, hidd"
  },
  {
    "path": "paper_experiments/models/deep_sort_model.py",
    "chars": 1424,
    "preview": "import tensorflow as tf\nfrom skimage.transform import resize\nimport numpy as np\n\nclass ImageEncoder(object):\n\n    def __"
  },
  {
    "path": "paper_experiments/models/featurepointnet_model.py",
    "chars": 16765,
    "preview": "import os, pdb\nimport numpy as np\nimport tensorflow as tf\ntf.logging.set_verbosity(tf.logging.ERROR)\nimport configparser"
  },
  {
    "path": "paper_experiments/models/pointnet_model.py",
    "chars": 4887,
    "preview": "import os, pdb\nimport tensorflow as tf\ntf.logging.set_verbosity(tf.logging.ERROR)\nimport configparser\nfrom utils.pointne"
  },
  {
    "path": "paper_experiments/models/resnet_reid_models.py",
    "chars": 4430,
    "preview": "import torch\nimport torch.nn as nn\nfrom torch.autograd import Variable\nimport torchvision.models as models\nfrom torchvis"
  },
  {
    "path": "paper_experiments/models/yolo_models.py",
    "chars": 14786,
    "preview": "from __future__ import division\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.autograd "
  },
  {
    "path": "paper_experiments/requirements.txt",
    "chars": 1760,
    "preview": "absl-py==0.7.0\nastor==0.7.1\nbackcall==0.1.0\nbleach==3.3.0\ncatkin-pkg==0.4.12\ncertifi==2018.11.29\nchardet==3.0.4\ncloudpic"
  },
  {
    "path": "paper_experiments/track.py",
    "chars": 19764,
    "preview": "import open3d as o3d\nimport torch\nimport argparse\nimport os, pdb, sys, copy, pickle\nimport time\nimport random\nimport num"
  },
  {
    "path": "paper_experiments/utils/EKF.py",
    "chars": 7392,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport scipy.linalg\nimport pdb\n\n\"\"\"\nTable for the 0.95 quantile of the chi"
  },
  {
    "path": "paper_experiments/utils/JPDA_matching.py",
    "chars": 4046,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nfrom linear_assignment import min_m"
  },
  {
    "path": "paper_experiments/utils/aligned_reid_utils.py",
    "chars": 23425,
    "preview": "from __future__ import print_function\nimport os\nimport os.path as osp\nimport pickle\nfrom scipy import io\nimport datetime"
  },
  {
    "path": "paper_experiments/utils/assign_ids_detections.py",
    "chars": 2124,
    "preview": "import numpy as np\nimport os\nimport pdb\nfrom tqdm import tqdm\nfrom deep_sort_utils import non_max_suppression as deepsor"
  },
  {
    "path": "paper_experiments/utils/calibration.py",
    "chars": 16997,
    "preview": "import numpy as np\nimport cv2\nimport os\nimport yaml\nimport torch\nimport pdb\n\nclass Calibration(object):\n    ''' Calibrat"
  },
  {
    "path": "paper_experiments/utils/combine_and_process_detections.py",
    "chars": 3126,
    "preview": "import os\nfrom os import listdir\nfrom os.path import isfile, join\n\n#root = \"/cvgl2/u/mihirp/depth_tracking/data/JRDB/seq"
  },
  {
    "path": "paper_experiments/utils/dataset.py",
    "chars": 8101,
    "preview": "import glob\nimport os\nimport pdb\nimport random\nimport sys\nfrom itertools import compress\n\nimport numpy as np\nimport torc"
  },
  {
    "path": "paper_experiments/utils/deep_sort_utils.py",
    "chars": 2197,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport cv2\n\n\ndef non_max_suppression(boxes, max_bbox_overlap, scores=None)"
  },
  {
    "path": "paper_experiments/utils/detection.py",
    "chars": 2273,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\n\n\nclass Detection(object):\n    \"\"\"\n    This class represents a bounding bo"
  },
  {
    "path": "paper_experiments/utils/double_measurement_kf.py",
    "chars": 23706,
    "preview": "import random\nimport numpy as np\nimport scipy.linalg\nimport EKF\nimport pdb\nimport kf_2d\nimport os\nimport pickle\nimport t"
  },
  {
    "path": "paper_experiments/utils/evaluate_detections.py",
    "chars": 4760,
    "preview": "import numpy as np\nimport os\nimport pdb\nfrom tqdm import tqdm\nfrom deep_sort_utils import non_max_suppression as deepsor"
  },
  {
    "path": "paper_experiments/utils/featurepointnet_model_util.py",
    "chars": 25485,
    "preview": "import open3d as o3d\nimport numpy as np\nimport tensorflow as tf\nimport os\nimport sys\nimport torch\nBASE_DIR = os.path.dir"
  },
  {
    "path": "paper_experiments/utils/featurepointnet_tf_util.py",
    "chars": 21762,
    "preview": "\"\"\" Wrapper functions for TensorFlow layers.\n\nAuthor: Charles R. Qi\nDate: November 2017\n\"\"\"\n\nimport numpy as np\nimport t"
  },
  {
    "path": "paper_experiments/utils/imm.py",
    "chars": 12814,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport scipy.linalg\nimport utils.EKF as EKF\nimport pdb\nimport utils.kf_2d "
  },
  {
    "path": "paper_experiments/utils/iou_matching.py",
    "chars": 3372,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nfrom . import linear_assignment\nimp"
  },
  {
    "path": "paper_experiments/utils/kf_2d.py",
    "chars": 10355,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport scipy.linalg\nimport utils.EKF as EKF\nimport pdb\nnp.set_printoptions"
  },
  {
    "path": "paper_experiments/utils/kf_3d.py",
    "chars": 6181,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport scipy.linalg\nimport EKF\nimport pdb\n\n\nclass KalmanFilter3D(EKF.EKF):"
  },
  {
    "path": "paper_experiments/utils/linear_assignment.py",
    "chars": 18699,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nfrom sklearn.utils.linear_assignmen"
  },
  {
    "path": "paper_experiments/utils/logger.py",
    "chars": 1134,
    "preview": "import io, os\nimport numpy as np\nfrom PIL import Image\nimport tensorflow as tf\n#courtesy https://becominghuman.ai/loggin"
  },
  {
    "path": "paper_experiments/utils/mbest_ilp.py",
    "chars": 9392,
    "preview": "from gurobipy import Model, quicksum, LinExpr, GRB\nimport numpy as np\nimport copy\nimport time\nfrom sklearn.utils.linear_"
  },
  {
    "path": "paper_experiments/utils/nn_matching.py",
    "chars": 8291,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport pdb\nimport torch\n\ndef _pdist(a, b):\n    \"\"\"Compute pair-wise square"
  },
  {
    "path": "paper_experiments/utils/pointnet_tf_util.py",
    "chars": 19388,
    "preview": "\"\"\" Wrapper functions for TensorFlow layers.\n\nAuthor: Charles R. Qi\nDate: November 2016\n\"\"\"\n\nimport numpy as np\nimport t"
  },
  {
    "path": "paper_experiments/utils/pointnet_transform_nets.py",
    "chars": 4297,
    "preview": "import tensorflow as tf\nimport numpy as np\nimport sys\nimport os\nBASE_DIR = os.path.dirname(os.path.abspath(__file__))\nsy"
  },
  {
    "path": "paper_experiments/utils/read_detections.py",
    "chars": 4678,
    "preview": "import numpy as np\nimport pdb\nfrom deep_sort_utils import non_max_suppression as deepsort_nms\n\ndef read_ground_truth_2d_"
  },
  {
    "path": "paper_experiments/utils/resnet_reid_utils.py",
    "chars": 4006,
    "preview": "import torch\nimport os\nimport sys\nimport torch.nn as nn\nfrom torch.autograd import Variable\nfrom torchvision import tran"
  },
  {
    "path": "paper_experiments/utils/test_jpda.py",
    "chars": 1095,
    "preview": "from gurobipy import *\nfrom numpy import *\n'''\ndef mycallback(model, where):\n    if where == GRB.callback.MIP:\n        p"
  },
  {
    "path": "paper_experiments/utils/test_kf/.gitignore",
    "chars": 4,
    "preview": "*.p\n"
  },
  {
    "path": "paper_experiments/utils/test_kf/run_kf_test.py",
    "chars": 5003,
    "preview": "import sys\nsys.path.insert(0, '..')\nimport kalman_filter\nimport kf_simple3d\nimport numpy as np\nimport matplotlib.pyplot "
  },
  {
    "path": "paper_experiments/utils/test_kf/write_kf_test.py",
    "chars": 2583,
    "preview": "import sys\nsys.path.insert(0, '..')\nimport kalman_filter\nimport numpy as np\nimport pickle\nimport pdb\n\ndef data2file(data"
  },
  {
    "path": "paper_experiments/utils/track.py",
    "chars": 12377,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport pdb\nimport torch\nimport copy\n\nfrom .imm import IMMFilter2D\n\nclass T"
  },
  {
    "path": "paper_experiments/utils/track_3d.py",
    "chars": 6442,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport pdb\nimport torch\n\nclass TrackState:\n    \"\"\"\n    Enumeration type fo"
  },
  {
    "path": "paper_experiments/utils/tracker.py",
    "chars": 11193,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nimport pdb\nfrom . import kf_2d, kf_"
  },
  {
    "path": "paper_experiments/utils/tracker_3d.py",
    "chars": 9781,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nimport pdb\nfrom . import double_mea"
  },
  {
    "path": "paper_experiments/utils/tracking_utils.py",
    "chars": 6888,
    "preview": "import torch, sys, os, pdb\nimport numpy as np\nfrom PIL import Image\nfrom scipy.spatial import Delaunay\nsys.path.append(o"
  },
  {
    "path": "paper_experiments/utils/visualise.py",
    "chars": 5072,
    "preview": "import matplotlib\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as plt_patches\nimport numpy as np\nimport uti"
  },
  {
    "path": "paper_experiments/utils/yolo_utils/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "paper_experiments/utils/yolo_utils/datasets.py",
    "chars": 4241,
    "preview": "import glob\nimport random\nimport os\nimport numpy as np\n\nimport torch\n\nfrom torch.utils.data import Dataset\nfrom PIL impo"
  },
  {
    "path": "paper_experiments/utils/yolo_utils/parse_config.py",
    "chars": 1261,
    "preview": "\n\ndef parse_model_config(path):\n    \"\"\"Parses the yolo-v3 layer configuration file and returns module definitions\"\"\"\n   "
  },
  {
    "path": "paper_experiments/utils/yolo_utils/utils.py",
    "chars": 9955,
    "preview": "from __future__ import division\nimport math\nimport time\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as"
  },
  {
    "path": "requirements.txt",
    "chars": 154,
    "preview": "cycler==0.10.0\nkiwisolver==1.1.0\nmatplotlib==3.1.2\nnumpy==1.21.0\nopencv-python==4.2.0.32\npyparsing==2.4.6\npython-dateuti"
  },
  {
    "path": "src/3d_detector.py",
    "chars": 8994,
    "preview": "#!/home/sibot/anaconda2/bin/python\n\"\"\" yolo_bbox_to_sort.py\n    Subscribe to the Yolo 2 bboxes, and publish the detectio"
  },
  {
    "path": "src/EKF.py",
    "chars": 6920,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport scipy.linalg\nimport pdb\n\n\"\"\"\nTable for the 0.95 quantile of the chi"
  },
  {
    "path": "src/JPDA_matching.py",
    "chars": 4019,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nfrom linear_assignment import min_m"
  },
  {
    "path": "src/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/aligned_reid_model.py",
    "chars": 7345,
    "preview": "import torch\nimport torch.nn as nn\nimport torch.nn.init as init\nimport torch.nn.functional as F\nimport torch.utils.model"
  },
  {
    "path": "src/aligned_reid_utils.py",
    "chars": 20940,
    "preview": "from __future__ import print_function\nimport os\nimport os.path as osp\nimport pickle\nfrom scipy import io\nimport datetime"
  },
  {
    "path": "src/calibration.py",
    "chars": 17365,
    "preview": "import numpy as np\nimport cv2\nimport os\nimport yaml\nimport torch\nimport pdb\n\nclass Calibration(object):\n    ''' Calibrat"
  },
  {
    "path": "src/combination_model.py",
    "chars": 2101,
    "preview": "import pdb\n\nimport numpy as np\nimport torch.nn as nn\n\nclass CombiNet(nn.Module):\n\tdef __init__(self, in_dim = 2560, hidd"
  },
  {
    "path": "src/deep_sort_utils.py",
    "chars": 1994,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport cv2\n\n\ndef non_max_suppression(boxes, max_bbox_overlap, scores=None)"
  },
  {
    "path": "src/detection.py",
    "chars": 2211,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\n\n\nclass Detection(object):\n    \"\"\"\n    This class represents a bounding bo"
  },
  {
    "path": "src/distances.py",
    "chars": 8172,
    "preview": "\"\"\"py-motmetrics - metrics for multiple object tracker (MOT) benchmarking.\n\nChristoph Heindl, 2017\nhttps://github.com/ch"
  },
  {
    "path": "src/double_measurement_kf.py",
    "chars": 19217,
    "preview": "import random\nimport numpy as np\nimport scipy.linalg\nimport EKF\nimport pdb\nimport kf_2d\nimport os\nimport pickle\nimport t"
  },
  {
    "path": "src/evaluation/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/evaluation/distances 2.py",
    "chars": 8430,
    "preview": "\"\"\"py-motmetrics - metrics for multiple object tracker (MOT) benchmarking.\n\nChristoph Heindl, 2017\nhttps://github.com/ch"
  },
  {
    "path": "src/evaluation/distances.py",
    "chars": 8430,
    "preview": "\"\"\"py-motmetrics - metrics for multiple object tracker (MOT) benchmarking.\n\nChristoph Heindl, 2017\nhttps://github.com/ch"
  },
  {
    "path": "src/featurepointnet_model.py",
    "chars": 16504,
    "preview": "import os, pdb\nimport numpy as np\nimport tensorflow as tf\ntf.logging.set_verbosity(tf.logging.ERROR)\nimport configparser"
  },
  {
    "path": "src/featurepointnet_model_util.py",
    "chars": 26104,
    "preview": "# import open3d as o3d\nimport numpy as np\nimport tensorflow as tf\nimport os\nimport sys\nimport torch\nBASE_DIR = os.path.d"
  },
  {
    "path": "src/featurepointnet_tf_util.py",
    "chars": 21762,
    "preview": "\"\"\" Wrapper functions for TensorFlow layers.\n\nAuthor: Charles R. Qi\nDate: November 2017\n\"\"\"\n\nimport numpy as np\nimport t"
  },
  {
    "path": "src/iou_matching.py",
    "chars": 3365,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nimport linear_assignment\nimport pdb"
  },
  {
    "path": "src/kf_2d.py",
    "chars": 9616,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport scipy.linalg\nimport EKF\nimport pdb\nnp.set_printoptions(precision=4,"
  },
  {
    "path": "src/linear_assignment.py",
    "chars": 18297,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nfrom sklearn.utils.linear_assignmen"
  },
  {
    "path": "src/mbest_ilp.py",
    "chars": 9392,
    "preview": "from gurobipy import Model, quicksum, LinExpr, GRB\nimport numpy as np\nimport copy\nimport time\nfrom sklearn.utils.linear_"
  },
  {
    "path": "src/nn_matching.py",
    "chars": 8284,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport pdb\nimport torch\n\ndef _pdist(a, b):\n    \"\"\"Compute pair-wise square"
  },
  {
    "path": "src/pointnet_model.py",
    "chars": 4887,
    "preview": "import os, pdb\nimport tensorflow as tf\ntf.logging.set_verbosity(tf.logging.ERROR)\nimport configparser\nfrom utils.pointne"
  },
  {
    "path": "src/template 2.py",
    "chars": 4061,
    "preview": "#!/home/sibot/anaconda2/bin/python\n\"\"\" yolo_bbox_to_sort.py\n    Subscribe to the Yolo 2 bboxes, and publish the detectio"
  },
  {
    "path": "src/template.py",
    "chars": 4061,
    "preview": "#!/home/sibot/anaconda2/bin/python\n\"\"\" yolo_bbox_to_sort.py\n    Subscribe to the Yolo 2 bboxes, and publish the detectio"
  },
  {
    "path": "src/track_3d 2.py",
    "chars": 9356,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport pdb\nimport torch\n\nclass TrackState:\n    \"\"\"\n    Enumeration type fo"
  },
  {
    "path": "src/track_3d.py",
    "chars": 9356,
    "preview": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport pdb\nimport torch\n\nclass TrackState:\n    \"\"\"\n    Enumeration type fo"
  },
  {
    "path": "src/tracker_3d 2.py",
    "chars": 11233,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nimport pdb\nimport double_measuremen"
  },
  {
    "path": "src/tracker_3d.py",
    "chars": 11233,
    "preview": "# vim: expandtab:ts=4:sw=4\nfrom __future__ import absolute_import\nimport numpy as np\nimport pdb\nimport double_measuremen"
  },
  {
    "path": "src/tracker_3d_node 2.py",
    "chars": 7568,
    "preview": "#!/home/sibot/anaconda2/bin/python\n\"\"\" yolo_bbox_to_sort.py\n    Subscribe to the Yolo 2 bboxes, and publish the detectio"
  },
  {
    "path": "src/tracker_3d_node.py",
    "chars": 7568,
    "preview": "#!/home/sibot/anaconda2/bin/python\n\"\"\" yolo_bbox_to_sort.py\n    Subscribe to the Yolo 2 bboxes, and publish the detectio"
  },
  {
    "path": "src/tracking_utils 2.py",
    "chars": 6892,
    "preview": "import torch, sys, os, pdb\nimport numpy as np\nfrom PIL import Image\nfrom scipy.spatial import Delaunay\nsys.path.append(o"
  },
  {
    "path": "src/tracking_utils.py",
    "chars": 6892,
    "preview": "import torch, sys, os, pdb\nimport numpy as np\nfrom PIL import Image\nfrom scipy.spatial import Delaunay\nsys.path.append(o"
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the StanfordVL/JRMOT_ROS GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 100 files (715.3 KB), approximately 190.5k tokens, and a symbol index with 839 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!