Skip to content

Commit

Permalink
Ncars and rendering support (#4)
Browse files Browse the repository at this point in the history
* Refactored datasets and format
Added new Prohesee RAW DAT format
Added N-Cars dataset

* Added basic rendering functions. Adjusted README
  • Loading branch information
ffardo authored Sep 11, 2022
1 parent b29e344 commit 9fbd5d4
Show file tree
Hide file tree
Showing 9 changed files with 372 additions and 123 deletions.
70 changes: 65 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@ Also, Go is not the de facto language for scientific research, and I think new l
This package features the following functionality

* ATIS format support
* Prophesee DAT format support (Read only)
* Support to N-Caltech and N-MNIST datasets, including saccade stabilization
* Support to N-Cars dataset
* Spatio-temporal filtering
* Refraction
* Additive and degenerative noise generation
* Surface of Active Events (SAE) generation
* Basic rendering of event streams and SAE

# Installation instructions

Expand Down Expand Up @@ -83,9 +86,10 @@ type EventCapture struct {
}
```

# Code example
# Code examples

The following code example shows the basic functionality of the event vision library.
## Basic usage on Neuromorphic datasets
The following code example shows the basic functionality of the event vision library using N-Caltech100 dataset.

```
package main
Expand All @@ -100,7 +104,7 @@ import (
func main() {
//Adjust path to actual location
// Adjust path to actual location
reader := neuromorphic.NeuromorphicDataset{
FilePath: "Caltech101/accordion/image_0005.bin",
}
Expand All @@ -123,14 +127,70 @@ func main() {
}
```

## SAE creation and rendering for N-Cars

The following example reads an entry from N-Cars dataset, builds an additive SAE in map format and renders to an image pointer.
```
package main
import (
"fmt"
"image/png"
"log"
"os"
"github.com/ffardo/go-event-vision/datasets"
"github.com/ffardo/go-event-vision/datasets/ncars"
"github.com/ffardo/go-event-vision/render"
"github.com/ffardo/go-event-vision/sae"
)
func main() {
// Adjust path to actual location
reader := ncars.Ncars{
FilePath: "Prophesee_Dataset_n_cars/n-cars_train/cars/obj_004396_td.dat",
}
evCap, err := datasets.ReadDataset(reader)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Event capture\nWidht=%d\nHeight=%d\nTotal events=%d\n", evCap.Width, evCap.Height, len(evCap.Events))
s, err := sae.CreateMap(evCap.Events, "additive")
// Render SAE to image. Values are automatically normalized.
evImg := render.SaeMap(
s, evCap.Width, evCap.Height,
)
// Save resultin image to file
out, err := os.Create("./output.png")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = png.Encode(out, evImg)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
```
# Roadmap

This project is a work in progress and there is no tagged release yet. The following requirements and features are planned

* Full test coverage
* Additional formats such as Prophesee
* Additional dataset support such as N-Cars and DDD17
* Full support to Prophesee DAT format
* Additional dataset support such as DDD17 and N-ImageNet
* Feature extraction algorithms such as HATs
* Additional rendering styles for SAE


# Additional Information
Expand Down
25 changes: 25 additions & 0 deletions datasets/ncars/ncars.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ncars

import (
"github.com/ffardo/go-event-vision"
"github.com/ffardo/go-event-vision/format/prophesee"
)

// Ncars implements DatasetReader interface for N-CARS dataset
type Ncars struct {
FilePath string
}

// Read event capture for an entry in the dataset
func (n Ncars) Read() (event.EventCapture, error) {
atis := prophesee.Dat{FilePath: n.FilePath}

return atis.ReadEvents()
}

// Write capture to a dataset. Should be used only for data augmentation.
func (n Ncars) Write(evCap event.EventCapture) error {
atis := prophesee.Dat{FilePath: n.FilePath}

return atis.WriteEvents(evCap)
}
6 changes: 3 additions & 3 deletions datasets/neuromorphic/neuromorphic.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package neuromorphic

import (
"github.com/ffardo/go-event-vision"
"github.com/ffardo/go-event-vision/format"
"github.com/ffardo/go-event-vision/format/atis"
)

// NeuromorphicDataset implements DatasetReader interface for N-MNIST and N-Caltech100 datasets
Expand All @@ -12,14 +12,14 @@ type NeuromorphicDataset struct {

// Read event capture for an entry in the dataset
func (n NeuromorphicDataset) Read() (event.EventCapture, error) {
atis := format.Atis{FilePath: n.FilePath}
atis := atis.Aer{FilePath: n.FilePath}

return atis.ReadEvents()
}

// Write capture to a dataset. Should be used only for data augmentation.
func (n NeuromorphicDataset) Write(evCap event.EventCapture) error {
atis := format.Atis{FilePath: n.FilePath}
atis := atis.Aer{FilePath: n.FilePath}

return atis.WriteEvents(evCap)
}
Expand Down
12 changes: 6 additions & 6 deletions event.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ type Point2D struct {

// Event represents a discrete event with coordinates (X,Y), timestamp (Ts) and polarity (P)
type Event struct {
Coords Point2D
Ts int
P int
Coords Point2D // event Location
Ts int // timestamp, usually expressed in microsseconds. It might change depending on vendor
P int // polarity (1: Positive event, 0: Negative event)
}

// EventCapture represents a scene captured with event sensors
type EventCapture struct {
Events []Event
Width int
Height int
Events []Event // list of events
Width int // width of the captured scene
Height int // height of the captured scene
}
113 changes: 113 additions & 0 deletions format/atis/atis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package atis

import (
"math"
"os"

"github.com/ffardo/go-event-vision"
)

// Aer implements ATIS AER format reading and writing
type Aer struct {
FilePath string
}

func (a Aer) newEventFromBytes(data []byte) event.Event {
x := int(data[0])
y := int(data[1])
ts1 := (int(data[2]) & 127) << 16
ts2 := int(data[3]) << 8
ts3 := int(data[4])
ts := ts1 + ts2 + ts3
p := (int(data[2]) & 128) >> 7

if y == 240 {
ts += int(math.Pow(2, 13))
}

return event.Event{
Coords: event.Point2D{X: x, Y: y},
P: p,
Ts: ts,
}
}

func (a Aer) eventToBytes(ev event.Event) []byte {
x := ev.Coords.X
y := ev.Coords.Y

ts := ev.Ts

if y == 240 {
ts -= int(math.Pow(2, 13))
}

data := make([]byte, 5)

data[0] = byte(x)
data[1] = byte(y)

p := ev.P << 7
data[2] = byte(((ts >> 16) & 127) + p)
data[3] = byte((ts >> 8) & 255)
data[4] = byte(ts & 255)

return data
}

// ReadEvents read events in the ATIS AER format from file
func (a Aer) ReadEvents() (event.EventCapture, error) {
f, err := os.Open(a.FilePath)
if err != nil {
return event.EventCapture{}, err
}

defer f.Close()

ev := []event.Event{}

bb := make([]byte, 5)
bc := 5

mX, mY := 0, 0

for bc == 5 {
bc, err = f.Read(bb)
if bc == 5 && err == nil {
n := a.newEventFromBytes(bb)
if n.Coords.Y == 240 {
continue
}
if n.Coords.X > mX {
mX = n.Coords.X
}
if n.Coords.Y > mY {
mY = n.Coords.Y
}
ev = append(ev, n)
}
}

return event.EventCapture{
Events: ev,
Width: mX + 1,
Height: mY + 1,
}, nil
}

// WriteEvents will write events to file in the ATIS AER format
func (a Aer) WriteEvents(evCap event.EventCapture) error {
f, err := os.Create(a.FilePath)

defer f.Close()
if err != nil {
return err
}

for _, ev := range evCap.Events {

data := a.eventToBytes(ev)
f.Write(data)
}
return nil
}
Loading

0 comments on commit 9fbd5d4

Please sign in to comment.