Code Monkey home page Code Monkey logo

odam's Introduction

ODaM - Object Detection and Monitoring

GoDoc Sourcegraph Go Report Card GitHub tag

v0.9.0

ODaM is project aimed to do monitoring such as: pedestrian detection and counting, vehicle detection and counting, speed estimation of objects, sending detected objects to gRPC server for detailed analysis.

YOLOv4 + Kalman filter for tracking YOLOv4 + simple centroid tracking
YOLOv4 Tiny + Kalman filter for tracking YOLOv4 Tiny + simple centroid tracking

Work in progress

We are working on this.

Not too fast, but it is what it is.

Former version (until #21) of this repository were containing a lot of business logic via go-darknet. Current version depends on OpenCV's DNN module.

Table of Contents

About

ODaM is tool for doing monitoring via Darknet's neural network called Yolo V4 (paper: https://arxiv.org/abs/2004.10934).

It's built on top of GoCV.

QA section

Who are you and what do you do?

There is info about me here: https://github.com/LdDl

You can have chat with me in Telegram/Gmail

Is this library / software or even framework?

I think about it as software with library capabilities.

What it capable of?

Not that much currently:

  • Object detection via darknet: OpenCV::ddn module is used
  • Object tracking via two possible techniques: Kalman tracking (filtering) or Centroid tracking;
  • Sending data to dedicated gRPC server;
  • MJPEG / imshow optional visual output;
  • Speed estimation based of GIS calculations (via matching pixels to WGS84).

Why Go?

Well, C++ is a killer in computer vision field and Python has a great battery included bindings for C++ code.

But I do no think that I'm ready to build gRPC/REST or any other web components of this software in C++ or Python (C++ is not that easy and Python...I just don't like Python syntax). That's why I prefer to stick with Go.

Why did you pick JSON for configuration purposes instead of TOML/YAML/INI or any other well-suited formats?

  1. Compared to TOML, JSON is not that 'human friendly', but still readable.
  2. It is in standart Go's library.
  3. Well, it is in standart Go's library.
  4. You got the idea.

Why bindings to Darknet instead of Opencv included stuff?

Sometimes you just do not need full OpenCV installation for object detection. I have such ANPR projet here: https://github.com/LdDl/license_plate_recognition I guess when I'm done with stable core I might switch from Go's Darknet bindings to OpenCV one (since ODaM-project requires OpenCV installation obviously)

What are your plans?

There is ROADMAP.md, but overall I am planning to extend capabilities of software:

  • Improve perfomance
  • Implement some cool tracking techniques (e.g. SORT)
  • Do gRPC accepting microservice for enabling software to catch information from external devices/systems/microservices and etc. E.g: you want to send message 'there is red light on traffic light" to instance of software, then it would look like grpcServer.Send('there is red light on traffic light'). After that any captured object will have state with message above in it. So you can catch traffic offenders.
  • Introduce convex polygon based calculations (same as virtual lines but for polygons)

How to help you?

If you are here, then you are already helped a lot, since you noticed my existence :harold_face:

If you want to make PR for some undone features (algorithms mainly) I'll glad to take a look.

Installation

notice: targeted for Linux users (no Windows/OSX instructions currenlty)

Need to enable CUDA (GPU) in every installation step where it's possible.

  1. Install CUDA (we recommend version 10.2)

    wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
    sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
    wget http://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda-repo-ubuntu1804-10-2-local-10.2.89-440.33.01_1.0-1_amd64.deb
    sudo dpkg -i cuda-repo-ubuntu1804-10-2-local-10.2.89-440.33.01_1.0-1_amd64.deb
    sudo apt-key add /var/cuda-repo-10-2-local-10.2.89-440.33.01/7fa2af80.pub
    sudo apt-get update
    sudo apt-get -y install cuda
    echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc
    echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:LD_LIBRARY_PATH'  >> ~/.bashrc
    source ~/.bashrc
  2. Install cuDNN (we recommend version v7.6.5 (November 18th, 2019), for CUDA 10.2) Go to NVIDIA's site and download *.deb package. After downloading *.deb package install it:

    sudo dpkg -i libcudnn7_7.6.5.32-1+cuda10.2_amd64.deb
    sudo dpkg -i libcudnn7-dev_7.6.5.32-1+cuda10.2_amd64.deb
    sudo dpkg -i libcudnn7-doc_7.6.5.32-1+cuda10.2_amd64.deb

    Do not forget to check if cuDNN installed properly:

    cp -r /usr/src/cudnn_samples_v7/ $HOME
    cd  $HOME/cudnn_samples_v7/mnistCUDNN
    make clean && make
    ./mnistCUDNN
    cd -
  3. GoCV - instructions link.

  4. Blob tracking library - instructions link

  5. If you want to use gRPC client-server model: gRPC - instructions link

    You need to implement your gRPC server as following proto-file: https://github.com/LdDl/odam/blob/master/yolo_grpc.proto.

    If you need to rebuild *.pb.go file, call this is from project root folder:

    protoc -I . yolo_grpc.proto --go_out=plugins=grpc:.
    

    In case of my needs I need to detect license plates on vehicles and do OCR on server-side: you can take a look on https://github.com/LdDl/license_plate_recognition for gRPC server example

After steps above done:

go install github.com/LdDl/odam/cmd/odam

Check if executable available

odam -h

and you will see something like this:

Usage of ./odam:
-settings string
        Path to application's settings (default "conf.json")

Usage

notice: targeted for Linux users (no Windows/OSX instructions currenlty)

  • Prepare neural network stuff
    • Download YOLO's weights, configuration file and *.names file. Your way may warry, but here is our script: download_data.sh
      ./download_data_v4.sh
      
    • Make sure there is link to *.names file in YOLO's configuration file:
      [yolo]
      mask = 0,1,2
      anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
      classes=80
      num=9
      jitter=.3
      ignore_thresh = .7
      truth_thresh = 1
      random=1
      names = coco.names # <<========= here is the link to 'coco.names' file
      
  • Prepare configuration file for application. Example of file: conf.json. Description of fields:
{
    "video_settings": { # Video input settings
        "source": "rtsp://127.0.0.1:554/h264", # Link to RTSP stream
        "width": 1920, # Width of image in video source
        "height": 1080, # Height of image in video source
        "reduced_width": 640, # Desired width of image (for imshow and MJPEG streaming, also reduces inference time (processing > accuracy) for neural network)
        "reduced_height": 360, # Desired height of image (for imshow and MJPEG streaming, also reduces inference time (processing > accuracy) for neural network)
        "camera_id": "f2abe45e-aad8-40a2-a3b7-0c610c0f3dda" # Unique ID for video source (useful for 'client-server' model)
    },
    "neural_network_settings": { # YOLO neural network settings
        "darknet_cfg": "yolov3.cfg", # Path to configuration.file
        "darknet_weights": "yolov3.weights", # Path to weights wile
        "darknet_classes": "coco.names", # Path to *.names file (labels of objects)
        "conf_threshold": 0.2, # Confidence threshold
        "nms_threshold": 0.4, # NMS threshold (postprocessing)
        "target_classes": ["car", "motorbike", "bus", "train", "truck"] # What classes you want to detect (if you want to use public dataset, but ignore some classes)
    },
    "cuda_settings":{ # CUDA settings, currently useless
        "enable": true # CUDA settings, currently useless
    },
    "mjpeg_settings":{ # MJPEG streaming settings
        "imshow_enable": false, # Do you want to enable imshow() feature (useful for testing purposes)
        "enable": true, # Do you want to enable this feature?
        "port": 35678 # Listening port fo connections
    },
    "grpc_settings": { # gRPC 'client-server' model settings
        "enable": true, # Do you want to enable this feature?
        "server_ip": "localhost", # gRPC server's IP
        "server_port": 50051 # gRPC server's listening port
    },
    "classes_settings": [ # classes settings (according to 'target_classes' in 'neural_network_settings')
        {
            "class_name": "car", # Corresponding class label
            "drawing_settings": {
                "bbox_settings": { # Setting for bounding boxes (detected objects)
                    "rgba": [255, 255, 0, 0], # Color of bounding box border
                    "thickness": 2 # Thickness as is
                },
                "centroid_settings": { # Setting for centroid of bounding boxes
                    "rgba": [255, 0, 0, 0], # Color of circle
                    "radius": 4, # Radius of circle
                    "thickness": 2 # Thickness as is
                },
                "text_settings": { # Setting for text above bounding boxes
                    "rgba": [0, 255, 0, 0], # Text color
                    "scale": 0.5, # Size of text
                    "thickness": 1, # Thickness as is
                    "font": "hershey_simplex" # Text font
                },
                "display_object_id": true # If you want to display object identifier
            }
        },
        {
            "class_name": "motorbike", # see "car" ref.
            "drawing_settings": {} # if propetry is empty, then default values are used
        },
        {
            "class_name": "bus", # see "car" ref.
            "drawing_settings": {} # if propetry is empty, then default values are used
        },
        {
            "class_name": "train", # see "car" ref.
            "drawing_settings": {} # if propetry is empty, then default values are used
        },
        {
            "class_name": "truck", # see "car" ref.
            "drawing_settings": {} # if propetry is empty, then default values are used
        }
    ],
    "tracker_settings": { # Tracked settings
        "tracker_type": "simple/kalman" # Use one of supported trackers. Simple tracker should fit realy simple scenes, while Kalman should be used with complicated scenes.
        "max_points_in_track": 150, # Restriction for maximum points in single track (>=1). Default value 10 (in case of value less than 1)
        "lines_settings":[
            {
                "line_id": 1, # Unique ID for line id (useful for 'client-server' model)
                "begin": [150, 800], # [X1,Y1], start point of line (usually, left side)
                "end": [1600, 800], # [X2,Y2], end point of line (usually, right side)
                "direction": "to_detector", # Direction of line (possible values: 'to_detector' and 'from_detector')
                "detect_classes": ["car", "motorbike", "bus", "train", "truck"], # What classes must be cropped (as detected objects) that were captured by detection line.
                "rgba": [255, 0, 0, 0], # Color of detection line
                "crop_mode": "crop" # When 'grpc_settings' field 'enable' is set to TRUE this option will be used for sending either cropped detected object (bbox==crop) or full image with bbox info to gRPC server-side application. Default is 'crop'
            }
        ],
        "speed_estimation_settings": { # Setting for speed estimation bas on GIS convertion between different spatial systems
            "enabled": false, # Enable this feature or not
            "mapper": [ # Map pixel coordinate to EPSG4326 coordinates
                # You should provide coordinates in correct order.
                # E.g. right bottom -> left bottom -> left top -> right top
                # Coordinates should match reduced_width and reduces_height attributes.
                {"image_coordinates": [640, 360], "epsg4326": [37.61891380882616, 54.20564268115055]},
                {"image_coordinates": [640, 0], "epsg4326": [37.61875545294513, 54.20546281228973]},
                {"image_coordinates": [0, 0], "epsg4326": [37.61903085447736, 54.20543126804313]},
                {"image_coordinates": [0, 360], "epsg4326": [37.61906183714973, 54.20562590237201]}
            ]
        }
    },
    "matpprof_settings": { # pprof for GoCV. Useful for debugging
        "enable": true # Do you want to enable this feature?
    }
}
  • Run
    odam --settings=conf.json
    

Screenshots

  • gocv.Imshow() output:

  • MJPEG streaming output:

Support

If you have troubles or questions please open an issue. Feel free to make PR's (we do not have contributing guidelines currently, but we will someday)

Roadmap

Please see ROADMAP.md

Dependencies

  • Bindings to OpenCV - GoCV. License is Apache-2.0
  • MJPEG streaming via GoCV - mjpeg. No license currently
  • Darknet (AlexeyAB's fork) - darknet. License is YOLO LICENSE
  • Tracking objects - gocv-blob. No license currently
  • gRPC for doing "'client-server'" application - grpc. License is Apache-2.0

License

You can check it here

Developers

LdDl https://github.com/LdDl

Pavel7824 https://github.com/Pavel7824

Former one: cpllbstr https://github.com/cpllbstr

odam's People

Contributors

lddl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

odam's Issues

[FEATURE REQUEST] Convex and concave polygons

Is your feature request related to a problem? Please describe.
Along with virtual line virtual polygon are needed.
They can give us:

  1. Traffic "lane" control
  2. Monitoring area of interests
  3. Estimating how much time object were in certain area (well, it could be analyzed in postprocess via track information also)

Describe the solution you'd like
Implement VirtualPolygon:

  • Constructor
  • Determine if polygon either convex or concave
  • Check if point in polygon (well, for convex and concave polygons algorithms may differ)
  • Check if blob has entered polygon
  • Check if blob has left polygon
  • Scale function

Describe alternatives you've considered
nope

Additional context
We need also:

  • Option to configure polygons
  • Match polygons' Euclidean coordinates to WGS84
  • Write test for math calculations (determine if point is inside of polygon is not easy task for some types of polygon)

[FEATURE REQUEST] Velocity estimation

Is your feature request related to a problem? Please describe.
Estimate velocity of objects on each frame

Describe the solution you'd like

  1. Match pixel grid to real geographic grid via GetPerspectiveTransform2f - https://docs.opencv.org/master/da/d54/group__imgproc__transform.html#ga20f62aa3235d869c9956436c870893ae
  2. For each blob with track length >= 2 evaluate its GPS coordinates and time difference between last timestamps
  3. (Haversine distance between GPS) / (time delta) = estimated speed

Additional context
Also update gRPC struct: add velocity field of type float32.

[FEATURE REQUEST] User defined maximum points in track

Is your feature request related to a problem? Please describe.
Current maximum points in track is 10 (hard coded)
Would be great to configure this parameter in JSON configuration

Describe the solution you'd like
Add option to JSON configuration in 'tracker_settings'

Describe alternatives you've considered
Nope

Additional context
Nope

[FEATURE REQUEST] Try to reconnect for VideoCapture

Is your feature request related to a problem? Please describe.
When reading frames from RTSP or USB/Ethernet source sometime disconnects may occur.

Describe the solution you'd like
Add channel listener. When it receives a signal (disconnected from video source) it will try reestablish connection.
I guess, some kind of wrapper around gocv.VideoCapture is needed.

Describe alternatives you've considered
systemd/cron is an option.
But you always can disable reconnect option configuration JSON (context is below) and prepare systemd/cron by yourself.

Additional context
It's better to add reconnect option to configuration JSON also, eg '"reconnect_opts": {"num_of_attempts": 5, "sleep_time_between_attempts": "10sec"}'

[FEATURE REQUEST] Crop option for gRPC communication

Is your feature request related to a problem? Please describe.
Sometime we want to send only cropped object via gRPC, sometime - whole picture and BBox info

Describe the solution you'd like
Just option in JSON configuration for each virtual line (detection line)

Describe alternatives you've considered
Nope

Additional context
Nope

[FEATURE REQUEST] gRPC internal implementation

Is your feature request related to a problem? Please describe.
Currently gRPC server implementation is outside of this repository (located here: https://github.com/LdDl/license_plate_recognition). It's hard to figure it out how to use gRPC properly (may be no clear enough).

Describe the solution you'd like
Add folder 'server_example' inside of parent folder 'cmd' and add main.go file with simple code example which can be used as boilerplate.

Describe alternatives you've considered
Another repository with boilerplated gRPC server

Additional context
nope

[FEATURE REQUEST] Track info in gRPC

Is your feature request related to a problem? Please describe.
Would be useful to send information about track (set of points for single object) to gRPC server-side

Describe the solution you'd like
This should be done as another gRPC field

message TrackInfo{
    repeated PointInfo points = 1;
}
message PointInfo{
    int32 x = 1;
    int32 y = 2;
}

Describe alternatives you've considered
Nope

Additional context
Also it would be great to have option in configuration for each virtual line: "send_track": true/false.

[FEATURE REQUEST] Complete installation script

Is your feature request related to a problem? Please describe.
We need to make out-of-a-box installation script for dependencies: OpenCV 4.x.x / Darknet / CUDA / cuDNN

Describe the solution you'd like
It could be Makefile or even bash script.
Most difficult would be to implement NVidia CUDA setup due the authentication process (currently user should be logged in to Nvidia's site to download CUDA or cuDNN)

Describe alternatives you've considered
If we won't be able to handle CUDA / cuDNN setup, we can make another issue.

Additional context
Keep in mind to have a document with dependencies: OpenCV 4.x.x / Darknet (AlexeyAB's fork on certain commit) / CUDA / cuDNN.
Also we are not targeted for windows users since golang+cuda - is a pain (for current state 19.02.2021)

[FEATURE REQUEST] REST client-server model

Is your feature request related to a problem? Please describe.
Not that much people familiar with gRPC client-server model. Do we need simple REST example?

Describe the solution you'd like
Prepare JSON structure: same as gRPC's one, but instead of image bytes provide base64 encoded image.

Describe alternatives you've considered
nope

Additional context
nope

[FEATURE REQUEST] Pub/Sub event system

Is your feature request related to a problem? Please describe.
I would like to see pub/sub event system via gRPC
What is event in this context? Well, it just information about detected objects in certain moments of time.
Currently I see next possible events:

  • object has crossed virtual line;
  • object has entered virtual polygon;
  • object has left virtual polygon;

Describe the solution you'd like
We need to make minimum valuable pub/sub system for client-side.
So we need to:

  • improve the way protobuf files are used.
  • describe possible event (via interface+structs or just structs)?
  • implement pub/sub system (it will be gRPC as a wrapping, and channels as a core)

Describe alternatives you've considered

Additional context
Summary workflow for clients will be like:

  1. Client connects to software instance
  2. Client subscribes to events (may be with some filters turned on)
  3. ODaM sends events to every subscribed client.

Also it will be needed an example of client-side (may be even for different programming languages)

yolov5

I am new to this technology. Is it possible to use yolov5 instead of yolov4 ?

[FEATURE REQUEST] Remove go-darknet

Is your feature request related to a problem? Please describe.
go-darknet was good at beginning. But, since we are need to prepare OpenCV installation anyway, we can remove pure-ish go-darknet usage [which was leading us to more dependencies]

Describe the solution you'd like
Remove go-darknet usage.
Add OpenCV NMS + postprocessing stuff
Update installation instructions

Additional context
Would be great to make some tests also

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.