SDK Core ML Corner Detection API
functions to compute homography reprojection error from Manderscheid, J., Sironi, A., Bourdis, N., Migliore, D., & Lepetit, V. Speed invariant time surface for learning to detect corner points with event-based cameras. CVPR 2019.
- class metavision_core_ml.corner_detection.compute_homography_reprojection_error.ComputeKPI(npy_folder_path)
Computes reprojection error for planar scenes (eg: Atis dataset)
- Parameters
npy_folder_path – npy_folder_path is the path of the folder containing a .npy file for each sequence to
type (evaluate. Each file is a list of corners of) – {‘names’: [‘x’, ‘y’, ‘id’, ‘t’], ‘formats’: [‘<u2’, ‘<u2’, ‘<i4’, ‘<i8’], ‘offsets’: [0, 2, 4, 8], ‘itemsize’: 16}
above. (.npy files can be easily created using the function convert_csv_to_npy) –
- metavision_core_ml.corner_detection.compute_homography_reprojection_error.convert_csv_to_npy(csv_path, overwrite=False)
Converts csv files to npy enable use of EventNpyReader class :param csv_path: path of csv :param overwrite: if csv exists overwrite or not
- metavision_core_ml.corner_detection.compute_homography_reprojection_error.homography_error(src_pts, dst_pts)
compute reprojection error between two set of corresponding points by estimating an homography between them :param src_pts: numpy array of 2d corners coordinates in source scene (Nx2) :param dst_pts: numpy array of 2d corners coordinates corresponding supposedly to src_pts in destination scene (Nx2)
- Returns
The number of points matched, the reprojection error [0, -1] if no homography was found
- metavision_core_ml.corner_detection.compute_homography_reprojection_error.project_coordinates(coordinates, homography)
Using the homography, projects coordinates :param coordinates: 2d numpy array of shape Nx2 :param homography: 3x3 homography matrix
- Returns
Projected and normalized coordinates
class to create tracks from corners based on distance in space and time
Image and Corner stream data loader
- class metavision_core_ml.corner_detection.corner_video_stream_dataset.CornerVideoDatasetIterator(metadata, height, width, rgb, number_of_heatmaps=10, batch_times=1)
Dataset Iterator streaming images, timestamps and corners
- Parameters
metadata (object) – path to picture or video
height (int) – height of input images / video clip
width (int) – width of input images / video clip
rgb (bool) – stream rgb videos
number_of_heatmaps (int) – The number of heatmaps containing corner locations
batch_times (int) – number of timesteps of training sequences
- metavision_core_ml.corner_detection.corner_video_stream_dataset.make_corner_video_dataset(path, num_workers, batch_size, height, width, min_length, max_length, number_of_heatmaps=10, rgb=False, seed=None, batch_times=1)
Makes a video/ moving picture dataset.
- Parameters
path (str) – folder to dataset
batch_size (int) – number of video clips / batch
height (int) – height
width (int) – width
min_length (int) – min length of video
max_length (int) – max length of video
mode (str) – ‘frames’ or ‘delta_t’
num_tbins (int) – number of bins in event volume
number_of_heatmaps (int) – number of corner heatmaps predicted by the network
rgb (bool) – retrieve frames in rgb
seed (int) – seed for randomness
batch_times (int) – number of time steps in training sequence
- metavision_core_ml.corner_detection.corner_video_stream_dataset.pad_collate_fn(data_list)
Here we pad with last image/ timestamp to get a contiguous batch
Here we reuse the GPUSimulator from OpenEB to stream synthetic events.
- class metavision_core_ml.corner_detection.data_module.EventToCornerDataModule(hparams)
Simulation gives events + frames + corners
- prepare_data_per_node
If True, each LOCAL_RANK=0 will call prepare data. Otherwise only NODE_RANK=0, LOCAL_RANK=0 will prepare data.
- allow_zero_length_dataloader_with_multiple_devices
If True, dataloader with zero length within local rank is allowed. Default value is False.
- test_dataloader()
An iterable or collection of iterables specifying test samples.
For more information about multiple dataloaders, see this section.
For data processing use the following pattern:
download in
prepare_data()
process and split in
setup()
However, the above are only necessary for distributed processing.
Warning
do not assign state in prepare_data
test()
prepare_data()
setup()
Note
Lightning tries to add the correct sampler for distributed and arbitrary hardware. There is no need to set it yourself.
Note
If you don’t need a test dataset and a
test_step()
, you don’t need to implement this method.
- train_dataloader()
An iterable or collection of iterables specifying training samples.
For more information about multiple dataloaders, see this section.
The dataloader you return will not be reloaded unless you set :paramref:`~pytorch_lightning.trainer.trainer.Trainer.reload_dataloaders_every_n_epochs` to a positive integer.
For data processing use the following pattern:
download in
prepare_data()
process and split in
setup()
However, the above are only necessary for distributed processing.
Warning
do not assign state in prepare_data
fit()
prepare_data()
setup()
Note
Lightning tries to add the correct sampler for distributed and arbitrary hardware. There is no need to set it yourself.
- val_dataloader()
An iterable or collection of iterables specifying validation samples.
For more information about multiple dataloaders, see this section.
The dataloader you return will not be reloaded unless you set :paramref:`~pytorch_lightning.trainer.trainer.Trainer.reload_dataloaders_every_n_epochs` to a positive integer.
It’s recommended that all data downloads and preparation happen in
prepare_data()
.fit()
validate()
prepare_data()
setup()
Note
Lightning tries to add the correct sampler for distributed and arbitrary hardware There is no need to set it yourself.
Note
If you don’t need a validation dataset and a
validation_step()
, you don’t need to implement this method.
Defines the network’s architecture used in Detecting Stable Keypoints from Events through Image Gradient Prediction and Long-Lived Accurate Keypoints in Event Streams inspired from Fast Image Reconstruction with an Event Camera
- class metavision_core_ml.corner_detection.firenet.FireNet(cin=1, cout=1, base=12)
Initialize internal Module state, shared by both nn.Module and ScriptModule.
- forward(x, mask=None)
Define the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the
Module
instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.
Here we reuse the GPUSimulator from OpenEB to stream synthetic events and corners.
- class metavision_core_ml.corner_detection.gpu_corner_esim.GPUEBSimCorners(dataloader, simulator, batch_times, event_volume_depth, randomize_noises, device, number_of_heatmaps, height, width, batch_size)
Simulated Events on GPU returns events, images and corners
- Parameters
dataloader – video-clips dataloader
simulator – gpu-simulator
batch_times – number of rounds per batch
event_volume_depth – number of timesteps per round
device – hardware to run simulation on
- classmethod from_params(folder, num_workers, batch_size, batch_times, event_volume_depth, height, width, min_frames_per_video, max_frames_per_video, number_of_heatmaps, randomize_noises=False, device='cuda:0')
Creates the simulator from parameters :param folder: folder of images :param num_workers: number of workers :param batch_size: size of batch :param batch_times: time dimension per batch :param event_volume_depth: number of channels in event volume :param height: height of images :param width: width of images :param min_frames_per_video: minimum number of frames per video :param max_frames_per_video: maximum number of frames per video :param number_of_heatmaps: number of heatmaps of corners locations returned :param randomize_noises: whether or not to randomize the noise of the simulator :param device: location of data
- Returns
GPUEBSimCorners class instantiated
- randomize_noises(first_times)
Randomizes noise in the simulator consistent with the batches :param first_times: whether or not the video in the batch is new
- metavision_core_ml.corner_detection.gpu_corner_esim.collect_target_images(gray_images, timestamps, video_len, target_indices, num_heatmaps)
Collect target frames + timestamps at target indices and rearranges them into T,B,C,H,W tensor
- Parameters
gray_images (tensor) – H,W,T format (videos are concatenated along 3rd dimension
timestamps (tensor) – B,T
video_len (tensor) – B lengths
target_indices (tensor) – B,M indices
num_heatmaps (int) – number of heatmaps
Pytorch Lightning module
- class metavision_core_ml.corner_detection.lightning_model.CornerDetectionCallback(data_module, video_result_every_n_epochs=2)
callbacks to our model
- on_train_epoch_end(trainer, pl_module)
Called when the train epoch ends.
To access all batch outputs at the end of the epoch, you can cache step outputs as an attribute of the
pytorch_lightning.core.LightningModule
and access them in this hook:class MyLightningModule(L.LightningModule): def __init__(self): super().__init__() self.training_step_outputs = [] def training_step(self): loss = ... self.training_step_outputs.append(loss) return loss class MyCallback(L.Callback): def on_train_epoch_end(self, trainer, pl_module): # do something with all training_step outputs, for example: epoch_mean = torch.stack(pl_module.training_step_outputs).mean() pl_module.log("training_epoch_mean", epoch_mean) # free up the memory pl_module.training_step_outputs.clear()
- class metavision_core_ml.corner_detection.lightning_model.CornerDetectionLightningModel(hparams: argparse.Namespace)
Corner Detection: Train your FireNet model to predict corners as a heatmap
- configure_optimizers()
Choose what optimizers and learning-rate schedulers to use in your optimization. Normally you’d need one. But in the case of GANs or similar you might have multiple. Optimization with multiple optimizers only works in the manual optimization mode.
- Returns
Any of these 6 options.
Single optimizer.
List or Tuple of optimizers.
Two lists - The first list has multiple optimizers, and the second has multiple LR schedulers (or multiple
lr_scheduler_config
).Dictionary, with an
"optimizer"
key, and (optionally) a"lr_scheduler"
key whose value is a single LR scheduler orlr_scheduler_config
.None - Fit will run without any optimizer.
The
lr_scheduler_config
is a dictionary which contains the scheduler and its associated configuration. The default configuration is shown below.lr_scheduler_config = { # REQUIRED: The scheduler instance "scheduler": lr_scheduler, # The unit of the scheduler's step size, could also be 'step'. # 'epoch' updates the scheduler on epoch end whereas 'step' # updates it after a optimizer update. "interval": "epoch", # How many epochs/steps should pass between calls to # `scheduler.step()`. 1 corresponds to updating the learning # rate after every epoch/step. "frequency": 1, # Metric to to monitor for schedulers like `ReduceLROnPlateau` "monitor": "val_loss", # If set to `True`, will enforce that the value specified 'monitor' # is available when the scheduler is updated, thus stopping # training if not found. If set to `False`, it will only produce a warning "strict": True, # If using the `LearningRateMonitor` callback to monitor the # learning rate progress, this keyword can be used to specify # a custom logged name "name": None, }
When there are schedulers in which the
.step()
method is conditioned on a value, such as thetorch.optim.lr_scheduler.ReduceLROnPlateau
scheduler, Lightning requires that thelr_scheduler_config
contains the keyword"monitor"
set to the metric name that the scheduler should be conditioned on.Metrics can be made available to monitor by simply logging it using
self.log('metric_to_track', metric_val)
in yourLightningModule
.Note
Some things to know:
Lightning calls
.backward()
and.step()
automatically in case of automatic optimization.If a learning rate scheduler is specified in
configure_optimizers()
with key"interval"
(default “epoch”) in the scheduler configuration, Lightning will call the scheduler’s.step()
method automatically in case of automatic optimization.If you use 16-bit precision (
precision=16
), Lightning will automatically handle the optimizer.If you use
torch.optim.LBFGS
, Lightning handles the closure function automatically for you.If you use multiple optimizers, you will have to switch to ‘manual optimization’ mode and step them yourself.
If you need to control how often the optimizer steps, override the
optimizer_step()
hook.
- classmethod load_from_checkpoint(checkpoint_path)
Primary way of loading a model from a checkpoint. When Lightning saves a checkpoint it stores the arguments passed to
__init__
in the checkpoint under"hyper_parameters"
.Any arguments specified through **kwargs will override args stored in
"hyper_parameters"
.- Parameters
checkpoint_path – Path to checkpoint. This can also be a URL, or file-like object
map_location – If your checkpoint saved a GPU model and you now load on CPUs or a different number of GPUs, use this to map to the new setup. The behaviour is the same as in
torch.load()
.hparams_file –
Optional path to a
.yaml
or.csv
file with hierarchical structure as in this example:drop_prob: 0.2 dataloader: batch_size: 32
You most likely won’t need this since Lightning will always save the hyperparameters to the checkpoint. However, if your checkpoint weights don’t have the hyperparameters saved, use this method to pass in a
.yaml
file with the hparams you’d like to use. These will be converted into adict
and passed into yourLightningModule
for use.If your model’s
hparams
argument isNamespace
and.yaml
file has hierarchical structure, you need to refactor your model to treathparams
asdict
.strict – Whether to strictly enforce that the keys in
checkpoint_path
match the keys returned by this module’s state dict. Defaults toTrue
unlessLightningModule.strict_loading
is set, in which case it defaults to the value ofLightningModule.strict_loading
.**kwargs – Any extra keyword args needed to init the model. Can also be used to override saved hyperparameter values.
- Returns
LightningModule
instance with loaded weights and hyperparameters (if available).
Note
load_from_checkpoint
is a class method. You should use yourLightningModule
class to call it instead of theLightningModule
instance, or aTypeError
will be raised.Note
To ensure all layers can be loaded from the checkpoint, this function will call
configure_model()
directly after instantiating the model if this hook is overridden in your LightningModule. However, note thatload_from_checkpoint
does not support loading sharded checkpoints, and you may run out of memory if the model is too large. In this case, consider loading through the Trainer via.fit(ckpt_path=...)
.Example:
# load weights without mapping ... model = MyLightningModule.load_from_checkpoint('path/to/checkpoint.ckpt') # or load weights mapping all weights from GPU 1 to GPU 0 ... map_location = {'cuda:1':'cuda:0'} model = MyLightningModule.load_from_checkpoint( 'path/to/checkpoint.ckpt', map_location=map_location ) # or load weights and hyperparameters from separate files. model = MyLightningModule.load_from_checkpoint( 'path/to/checkpoint.ckpt', hparams_file='/path/to/hparams_file.yaml' ) # override some of the params with new values model = MyLightningModule.load_from_checkpoint( PATH, num_layers=128, pretrained_ckpt_path=NEW_PATH, ) # predict pretrained_model.eval() pretrained_model.freeze() y_hat = pretrained_model(x)
- training_step(batch, batch_nb)
Here you compute and return the training loss and some additional metrics for e.g. the progress bar or logger.
- Parameters
batch – The output of your data iterable, normally a
DataLoader
.batch_idx – The index of this batch.
dataloader_idx – The index of the dataloader that produced this batch. (only if multiple dataloaders used)
- Returns
Tensor
- The loss tensordict
- A dictionary which can include any keys, but must include the key'loss'
in the case of automatic optimization.None
- In automatic optimization, this will skip to the next batch (but is not supported for multi-GPU, TPU, or DeepSpeed). For manual optimization, this has no special meaning, as returning the loss is not required.
In this step you’d normally do the forward pass and calculate the loss for a batch. You can also do fancier things like multiple forward passes or something model specific.
Example:
def training_step(self, batch, batch_idx): x, y, z = batch out = self.encoder(x) loss = self.loss(out, x) return loss
To use multiple optimizers, you can switch to ‘manual optimization’ and control their stepping:
def __init__(self): super().__init__() self.automatic_optimization = False # Multiple optimizers (e.g.: GANs) def training_step(self, batch, batch_idx): opt1, opt2 = self.optimizers() # do training_step with encoder ... opt1.step() # do training_step with decoder ... opt2.step()
Note
When
accumulate_grad_batches
> 1, the loss returned here will be automatically normalized byaccumulate_grad_batches
internally.
- video(dataloader, epoch=0, set='val')
- Parameters
dataloader – data loader from train or val set
epoch – epoch
set – can be either train or val
Returns:
Help function for corner detection
- metavision_core_ml.corner_detection.utils.clean_pred(pred, threshold=0.3)
Create a binary mask from a prediction between 0 and 1 after removal of local maximas :param pred: prediction of the network after the sigmoid layer TxBxCxHxW :param threshold: Value of local maximas to consider corners
Returns: Binary mask of corners locations.
- metavision_core_ml.corner_detection.utils.events_as_pol(events, frame)
From events creates an image :param events: events psee format :param frame: numpy array to show events on
- Returns
updated frame
- metavision_core_ml.corner_detection.utils.get_harris_corners_from_image(img, return_mask=False)
takes an image as input and outputs harris corners
- Parameters
img – opencv image
return_mask – returns a binary heatmap instead of corners positions
- Returns
harris corners in 3d with constant depth of one or a binary heatmap
- metavision_core_ml.corner_detection.utils.numpy_nms(input_array, size=7)
runs non maximal suppression on square patches of size x size on the two last dimension :param input_tensor: numpy array of shape B, C, H, W :param size: size of the side of the square patch for NMS :type size: int
- Returns
numpy array where local maximas are unchanged and all other values are -10e5
- metavision_core_ml.corner_detection.utils.project_points(points, homography, width, height, original_width, original_height, return_z=False, return_mask=False, filter_correct_corners=True)
projects 2d points given an homography and resize new points to new dimension.
- Parameters
points – 2d points in the form [x, y, 1] numpy array shape Nx3
homography – 3*3 homography numpy array
width – desired new dimension
height – desired new dimension
original_width – original dimension in which homography is given
original_height – original dimension in which homography is given
return_z – boolean to return points as 2d or 3d
return_mask – boolean to return mask of out-of-bounds projected points
filter_correct_corners – boolean whether to filter out-of-bounds projected points or not
- Returns
points projected in the new space and filtered by default to output only correct points
- Return type
projected points
- metavision_core_ml.corner_detection.utils.save_ccl_corners(tracker, csv_writer, ts)
Extract corners from the tracker and writes them to a csv :param tracker: ccl tracker class instance :param csv_writer: csv writer :param ts: timestamp of corners
- metavision_core_ml.corner_detection.utils.save_nn_corners(tracker, csv_writer, ts)
Extract corners from the tracker and writes them to a csv :param tracker: nearest neighbors tracker class instance :param csv_writer: csv writer :param ts: timestamp of corners
- metavision_core_ml.corner_detection.utils.torch_nms(input_tensor, kernel_size=7)
runs non maximal suppression on square patches of size x size on the two last dimension :param input_tensor: torch tensor of shape B, C, H, W :param kernel_size: size of the side of the square patch for NMS :type kernel_size: int
- Returns
torch tensor where local maximas are unchanged and all other values are -inf
- metavision_core_ml.corner_detection.utils.update_ccl_tracker(tracker, y, x, events_dtype, ts)
Update ccl tracker from torch tensors :param tracker: ccl tracker class instance :param y: torch tensor of corners y positions :param x: torch tensor of corners x positions :param events_dtype: dtype of events :param ts: timestamp of corners
- Returns
updated tracker instance
- metavision_core_ml.corner_detection.utils.update_nn_tracker(tracker, x, y, ts)
Update nearest neighbors tracker from torch tensors :param tracker: nearest neighbor tracker class instance :param y: torch tensor of corners y positions :param x: torch tensor of corners x positions :param ts: timestamp of corners
- Returns
updated tracker instance