Repository: opencv
Issue: Convolutional-LSTM models for object Detection on Video with much higher accuracy
Labels: priority: normal,feature,GSoC,category: dnn

##### System information (version)
<!-- Example
- OpenCV => 4.1.0 - master-branch
- Operating System / Platform => Windows 64 Bit
- Compiler => Visual Studio 2015
-->

- OpenCV =>  4.1.0 - master-branch
- Operating System / Platform => Win/Linux
- Compiler => g++ 5.4.0

##### Detailed description

Required implementation of Convolutional-LSTM layer which seems to give a huge increase in accuracy for Detection on Video: https://github.com/AlexeyAB/darknet/issues/3114

It seems that there is already some LSTM implementation: https://github.com/opencv/opencv/blob/22dbcf98c5fc1358bcb4660fe15a9ef8d2b4b388/modules/dnn/src/layers/recurrent_layers.cpp#L83-L349

It should allow to use this **Yolov3-SPP-LSTM** model with new layer `[conv-lstm]` for object detection on Video
* cfg: https://github.com/AlexeyAB/darknet/files/3199654/yolo_v3_spp_lstm.cfg.txt
* weights: https://drive.google.com/open?id=1-lFybALcypqTRtT3pzrrVuCRtDeWjsog

```
[conv_lstm]
batch_normalize=1
size=3
pad=1
output=256
peephole=0
state_constrain=512
activation=leaky
```

Implementation is got from this paper - page 4: https://arxiv.org/pdf/1506.04214v1.pdf

Just:
* `peephole=0` - disables Peephole `W * C`
* `peephole=1` - enables Peephole, but Peephole uses `*` - Convolution instead of `o` - Element-wise-product (Hadamard product), so the weights-file doesn't depend on network resolution (we can change width= and height= in [net]-section without retraining the model) - it seems it is implemented there: https://github.com/opencv/opencv/blob/22dbcf98c5fc1358bcb4660fe15a9ef8d2b4b388/modules/dnn/src/layers/recurrent_layers.cpp#L333-L337

* `state_constrain=512` - the maximum absolute value of `C`-state: https://github.com/AlexeyAB/darknet/blob/5a6afe96d3aa8aed19405577db7dba0ff173c848/src/conv_lstm_layer.c#L523 By default `state_constrain = time_steps * 32` (time_steps param from cfg-file that is used for training only, but state_constrain is used for both Training and Detection), it seems this is `useCellClip`: https://github.com/opencv/opencv/blob/22dbcf98c5fc1358bcb4660fe15a9ef8d2b4b388/modules/dnn/src/layers/recurrent_layers.cpp#L328-L332

There is the same proposal for Pytorch: https://github.com/pytorch/pytorch/issues/1706

![58437703-cc90b080-80d3-11e9-9aa1-e2451c601398](https://user-images.githubusercontent.com/4096485/61124814-9e630680-a4b0-11e9-9fce-042832210fff.png)

With this implementation: https://github.com/AlexeyAB/darknet/blob/5a6afe96d3aa8aed19405577db7dba0ff173c848/src/conv_lstm_layer.c#L852-L929

<!-- your description -->

##### Steps to reproduce

<!-- to add code example fence it with triple backticks and optional file extension
    ```.cpp
    // C++ code example
    ```
 or attach as .txt or .zip file
-->


You can run any of these models `cfg/weights`: https://github.com/AlexeyAB/darknet/issues/3114#issuecomment-494148968
by using this repository: https://github.com/AlexeyAB/darknet
and this command:
`./darknet detector demo data/self_driving.data yolov3-tiny_occlusion_track.cfg yolov3-tiny_occlusion_track_last.weights self_driving_valid.avi -out_filename out_self_driving_valid.avi`

* `self_driving.data` 
[self_driving.data.txt](https://github.com/opencv/opencv/files/3386250/self_driving.data.txt)

* `self_driving_valid.avi` file: https://drive.google.com/open?id=1rdxV1hYSQs6MNxBSIO9dNkAiBvb07aun

----

Weights of conv-lstm layer are saved in this order
```
            if (l.peephole) {
                save_convolutional_weights(*(l.vf), fp);
                save_convolutional_weights(*(l.vi), fp);
                save_convolutional_weights(*(l.vo), fp);
            }
            save_convolutional_weights(*(l.wf), fp);
            save_convolutional_weights(*(l.wi), fp);
            save_convolutional_weights(*(l.wg), fp);
            save_convolutional_weights(*(l.wo), fp);
            save_convolutional_weights(*(l.uf), fp);
            save_convolutional_weights(*(l.ui), fp);
            save_convolutional_weights(*(l.ug), fp);
            save_convolutional_weights(*(l.uo), fp);
```