Merge remote-tracking branch 'upstream/3.4' into merge-3.4

This commit is contained in:
Alexander Alekhin 2020-05-22 19:06:42 +00:00
commit 21e28adb87
79 changed files with 1054 additions and 46 deletions

View File

@ -32,8 +32,10 @@
#define QUIRC_PERSPECTIVE_PARAMS 8
#if QUIRC_MAX_REGIONS < UINT8_MAX
#define QUIRC_PIXEL_ALIAS_IMAGE 1
typedef uint8_t quirc_pixel_t;
#elif QUIRC_MAX_REGIONS < UINT16_MAX
#define QUIRC_PIXEL_ALIAS_IMAGE 0
typedef uint16_t quirc_pixel_t;
#else
#error "QUIRC_MAX_REGIONS > 65534 is not supported"
@ -77,7 +79,6 @@ struct quirc_grid {
struct quirc {
uint8_t *image;
quirc_pixel_t *pixels;
int *row_average; /* used by threshold() */
int w;
int h;

View File

@ -874,7 +874,7 @@ static quirc_decode_error_t decode_payload(struct quirc_data *data,
done:
/* Add nul terminator to all payloads */
if ((unsigned)data->payload_len >= sizeof(data->payload))
if (data->payload_len >= (int) sizeof(data->payload))
data->payload_len--;
data->payload[data->payload_len] = 0;

View File

@ -27,10 +27,7 @@ struct quirc *quirc_new(void)
{
struct quirc *q = malloc(sizeof(*q));
if (!q)
return NULL;
memset(q, 0, sizeof(*q));
memset(q, 0, sizeof(*q));
return q;
}
@ -39,9 +36,8 @@ void quirc_destroy(struct quirc *q)
free(q->image);
/* q->pixels may alias q->image when their type representation is of the
same size, so we need to be careful here to avoid a double free */
if (sizeof(*q->image) != sizeof(*q->pixels))
if (!QUIRC_PIXEL_ALIAS_IMAGE)
free(q->pixels);
free(q->row_average);
free(q);
}
@ -49,7 +45,6 @@ int quirc_resize(struct quirc *q, int w, int h)
{
uint8_t *image = NULL;
quirc_pixel_t *pixels = NULL;
int *row_average = NULL;
/*
* XXX: w and h should be size_t (or at least unsigned) as negatives
@ -82,35 +77,27 @@ int quirc_resize(struct quirc *q, int w, int h)
(void)memcpy(image, q->image, min);
/* alloc a new buffer for q->pixels if needed */
if (sizeof(*q->image) != sizeof(*q->pixels)) {
if (!QUIRC_PIXEL_ALIAS_IMAGE) {
pixels = calloc(newdim, sizeof(quirc_pixel_t));
if (!pixels)
goto fail;
}
/* alloc a new buffer for q->row_average */
row_average = calloc(w, sizeof(int));
if (!row_average)
goto fail;
/* alloc succeeded, update `q` with the new size and buffers */
q->w = w;
q->h = h;
free(q->image);
q->image = image;
if (sizeof(*q->image) != sizeof(*q->pixels)) {
if (!QUIRC_PIXEL_ALIAS_IMAGE) {
free(q->pixels);
q->pixels = pixels;
}
free(q->row_average);
q->row_average = row_average;
return 0;
/* NOTREACHED */
fail:
free(image);
free(pixels);
free(row_average);
return -1;
}
@ -133,6 +120,10 @@ static const char *const error_table[] = {
const char *quirc_strerror(quirc_decode_error_t err)
{
if ((int)err < 8) { return error_table[err]; }
else { return "Unknown error"; }
if ((int) err >= 0) {
if ((unsigned long) err < (unsigned long) (sizeof(error_table) / sizeof(error_table[0])))
return error_table[err];
}
return "Unknown error";
}

View File

@ -17,16 +17,7 @@
#include <quirc_internal.h>
const struct quirc_version_info quirc_version_db[QUIRC_MAX_VERSION + 1] = {
{ /* 0 */
.data_bytes = 0,
.apat = {0},
.ecc = {
{.bs = 0, .dw = 0, .ns = 0},
{.bs = 0, .dw = 0, .ns = 0},
{.bs = 0, .dw = 0, .ns = 0},
{.bs = 0, .dw = 0, .ns = 0}
}
},
{0},
{ /* Version 1 */
.data_bytes = 26,
.apat = {0},

View File

@ -1,6 +1,10 @@
Camera calibration With OpenCV {#tutorial_camera_calibration}
==============================
@prev_tutorial{tutorial_camera_calibration_square_chess}
@next_tutorial{tutorial_real_time_pose}
Cameras have been around for a long-long time. However, with the introduction of the cheap *pinhole*
cameras in the late 20th century, they became a common occurrence in our everyday life.
Unfortunately, this cheapness comes with its price: significant distortion. Luckily, these are

View File

@ -1,6 +1,9 @@
Create calibration pattern {#tutorial_camera_calibration_pattern}
=========================================
@next_tutorial{tutorial_camera_calibration_square_chess}
The goal of this tutorial is to learn how to create calibration pattern.
You can find a chessboard pattern in https://github.com/opencv/opencv/blob/master/doc/pattern.png

View File

@ -1,6 +1,10 @@
Camera calibration with square chessboard {#tutorial_camera_calibration_square_chess}
=========================================
@prev_tutorial{tutorial_camera_calibration_pattern}
@next_tutorial{tutorial_camera_calibration}
The goal of this tutorial is to learn how to calibrate a camera given a set of chessboard images.
*Test data*: use images in your data/chess folder.

View File

@ -1,6 +1,9 @@
Interactive camera calibration application {#tutorial_interactive_calibration}
==============================
@prev_tutorial{tutorial_real_time_pose}
According to classical calibration technique user must collect all data first and when run @ref cv::calibrateCamera function
to obtain camera parameters. If average re-projection error is huge or if estimated parameters seems to be wrong, process of
selection or collecting data and starting of @ref cv::calibrateCamera repeats.

View File

@ -1,6 +1,10 @@
Real Time pose estimation of a textured object {#tutorial_real_time_pose}
==============================================
@prev_tutorial{tutorial_camera_calibration}
@next_tutorial{tutorial_interactive_calibration}
Nowadays, augmented reality is one of the top research topic in computer vision and robotics fields.
The most elemental problem in augmented reality is the estimation of the camera pose respect of an
object in the case of computer vision area to do later some 3D rendering or in the case of robotics

View File

@ -1,5 +1,8 @@
# How to run deep networks on Android device {#tutorial_dnn_android}
@prev_tutorial{tutorial_dnn_halide_scheduling}
@next_tutorial{tutorial_dnn_yolo}
## Introduction
In this tutorial you'll know how to run deep learning networks on Android device
using OpenCV deep learning module.

View File

@ -1,5 +1,7 @@
# Custom deep learning layers support {#tutorial_dnn_custom_layers}
@prev_tutorial{tutorial_dnn_javascript}
## Introduction
Deep learning is a fast growing area. The new approaches to build neural networks
usually introduce new types of layers. They could be modifications of existing

View File

@ -1,6 +1,8 @@
Load Caffe framework models {#tutorial_dnn_googlenet}
===========================
@next_tutorial{tutorial_dnn_halide}
Introduction
------------

View File

@ -1,5 +1,8 @@
# How to enable Halide backend for improve efficiency {#tutorial_dnn_halide}
@prev_tutorial{tutorial_dnn_googlenet}
@next_tutorial{tutorial_dnn_halide_scheduling}
## Introduction
This tutorial guidelines how to run your models in OpenCV deep learning module
using Halide language backend. Halide is an open-source project that let us

View File

@ -1,5 +1,8 @@
# How to schedule your network for Halide backend {#tutorial_dnn_halide_scheduling}
@prev_tutorial{tutorial_dnn_halide}
@next_tutorial{tutorial_dnn_android}
## Introduction
Halide code is the same for every device we use. But for achieving the satisfied
efficiency we should schedule computations properly. In this tutorial we describe

View File

@ -1,5 +1,8 @@
# How to run deep networks in browser {#tutorial_dnn_javascript}
@prev_tutorial{tutorial_dnn_yolo}
@next_tutorial{tutorial_dnn_custom_layers}
## Introduction
This tutorial will show us how to run deep learning models using OpenCV.js right
in a browser. Tutorial refers a sample of face detection and face recognition

View File

@ -1,6 +1,9 @@
YOLO DNNs {#tutorial_dnn_yolo}
===============================
@prev_tutorial{tutorial_dnn_android}
@next_tutorial{tutorial_dnn_javascript}
Introduction
------------

View File

@ -1,6 +1,9 @@
AKAZE local features matching {#tutorial_akaze_matching}
=============================
@prev_tutorial{tutorial_detection_of_planar_objects}
@next_tutorial{tutorial_akaze_tracking}
Introduction
------------

View File

@ -1,6 +1,9 @@
AKAZE and ORB planar tracking {#tutorial_akaze_tracking}
=============================
@prev_tutorial{tutorial_akaze_matching}
@next_tutorial{tutorial_homography}
Introduction
------------

View File

@ -1,6 +1,10 @@
Detection of planar objects {#tutorial_detection_of_planar_objects}
===========================
@prev_tutorial{tutorial_feature_homography}
@next_tutorial{tutorial_akaze_matching}
The goal of this tutorial is to learn how to use *features2d* and *calib3d* modules for detecting
known planar objects in scenes.

View File

@ -1,6 +1,9 @@
Feature Description {#tutorial_feature_description}
===================
@prev_tutorial{tutorial_feature_detection}
@next_tutorial{tutorial_feature_flann_matcher}
Goal
----

View File

@ -1,6 +1,9 @@
Feature Detection {#tutorial_feature_detection}
=================
@prev_tutorial{tutorial_corner_subpixels}
@next_tutorial{tutorial_feature_description}
Goal
----

View File

@ -1,6 +1,9 @@
Feature Matching with FLANN {#tutorial_feature_flann_matcher}
===========================
@prev_tutorial{tutorial_feature_description}
@next_tutorial{tutorial_feature_homography}
Goal
----

View File

@ -1,6 +1,9 @@
Features2D + Homography to find a known object {#tutorial_feature_homography}
==============================================
@prev_tutorial{tutorial_feature_flann_matcher}
@next_tutorial{tutorial_detection_of_planar_objects}
Goal
----

View File

@ -1,6 +1,8 @@
Basic concepts of the homography explained with code {#tutorial_homography}
====================================================
@prev_tutorial{tutorial_akaze_tracking}
@tableofcontents
Introduction {#tutorial_homography_Introduction}

View File

@ -1,6 +1,9 @@
Detecting corners location in subpixels {#tutorial_corner_subpixels}
=======================================
@prev_tutorial{tutorial_generic_corner_detector}
@next_tutorial{tutorial_feature_detection}
Goal
----

View File

@ -1,6 +1,10 @@
Creating your own corner detector {#tutorial_generic_corner_detector}
=================================
@prev_tutorial{tutorial_good_features_to_track}
@next_tutorial{tutorial_corner_subpixels}
Goal
----

View File

@ -1,6 +1,9 @@
Shi-Tomasi corner detector {#tutorial_good_features_to_track}
==========================
@prev_tutorial{tutorial_harris_detector}
@next_tutorial{tutorial_generic_corner_detector}
Goal
----

View File

@ -1,6 +1,8 @@
Harris corner detector {#tutorial_harris_detector}
======================
@next_tutorial{tutorial_good_features_to_track}
Goal
----

View File

@ -3,6 +3,8 @@ Similarity check (PNSR and SSIM) on the GPU {#tutorial_gpu_basics_similarity}
===========================================
@todo update this tutorial
@next_tutorial{tutorial_gpu_thrust_interop}
Goal
----

View File

@ -2,6 +2,8 @@
Using a cv::cuda::GpuMat with thrust {#tutorial_gpu_thrust_interop}
===========================================
@prev_tutorial{tutorial_gpu_basics_similarity}
Goal
----

View File

@ -1,6 +1,10 @@
OpenCV4Android SDK {#tutorial_O4A_SDK}
==================
@prev_tutorial{tutorial_android_dev_intro}
@next_tutorial{tutorial_dev_with_OCV_on_Android}
This tutorial was designed to help you with installation and configuration of OpenCV4Android SDK.
This guide was written with MS Windows 7 in mind, though it should work with GNU Linux and Apple Mac

View File

@ -1,6 +1,10 @@
Introduction into Android Development {#tutorial_android_dev_intro}
=====================================
@prev_tutorial{tutorial_clojure_dev_intro}
@next_tutorial{tutorial_O4A_SDK}
This guide was designed to help you in learning Android development basics and setting up your
working environment quickly. It was written with Windows 7 in mind, though it would work with Linux
(Ubuntu), Mac OS X and any other OS supported by Android SDK.

View File

@ -1,6 +1,10 @@
Use OpenCL in Android camera preview based CV application {#tutorial_android_ocl_intro}
=====================================
@prev_tutorial{tutorial_dev_with_OCV_on_Android}
@next_tutorial{tutorial_macos_install}
This guide was designed to help you in use of [OpenCL &trade;](https://www.khronos.org/opencl/) in Android camera preview based CV application.
It was written for [Eclipse-based ADT tools](http://developer.android.com/tools/help/adt.html)
(deprecated by Google now), but it easily can be reproduced with [Android Studio](http://developer.android.com/tools/studio/index.html).

View File

@ -1,6 +1,10 @@
Android Development with OpenCV {#tutorial_dev_with_OCV_on_Android}
===============================
@prev_tutorial{tutorial_O4A_SDK}
@next_tutorial{tutorial_android_ocl_intro}
This tutorial has been created to help you use OpenCV library within your Android project.
This guide was written with Windows 7 in mind, though it should work with any other OS supported by

View File

@ -1,6 +1,10 @@
Building OpenCV for Tegra with CUDA {#tutorial_building_tegra_cuda}
===================================
@prev_tutorial{tutorial_arm_crosscompile_with_cmake}
@next_tutorial{tutorial_display_image}
@tableofcontents
OpenCV with CUDA for Tegra

View File

@ -1,6 +1,10 @@
Introduction to OpenCV Development with Clojure {#tutorial_clojure_dev_intro}
===============================================
@prev_tutorial{tutorial_java_eclipse}
@next_tutorial{tutorial_android_dev_intro}
As of OpenCV 2.4.4, OpenCV supports desktop Java development using nearly the same interface as for
Android development.

View File

@ -1,6 +1,9 @@
Cross referencing OpenCV from other Doxygen projects {#tutorial_cross_referencing}
====================================================
@prev_tutorial{tutorial_transition_guide}
Cross referencing OpenCV
------------------------

View File

@ -1,6 +1,10 @@
Cross compilation for ARM based Linux systems {#tutorial_arm_crosscompile_with_cmake}
=============================================
@prev_tutorial{tutorial_ios_install}
@next_tutorial{tutorial_building_tegra_cuda}
This steps are tested on Ubuntu Linux 12.04, but should work for other Linux distributions. I case
of other distributions package names and names of cross compilation tools may differ. There are
several popular EABI versions that are used on ARM platform. This tutorial is written for *gnueabi*

View File

@ -1,6 +1,10 @@
Introduction to Java Development {#tutorial_java_dev_intro}
================================
@prev_tutorial{tutorial_windows_visual_studio_image_watch}
@next_tutorial{tutorial_java_eclipse}
As of OpenCV 2.4.4, OpenCV supports desktop Java development using nearly the same interface as for
Android development. This guide will help you to create your first Java (or Scala) application using
OpenCV. We will use either [Apache Ant](http://ant.apache.org/) or [Simple Build Tool

View File

@ -1,6 +1,9 @@
Getting Started with Images {#tutorial_display_image}
===========================
@prev_tutorial{tutorial_building_tegra_cuda}
@next_tutorial{tutorial_documentation}
Goal
----

View File

@ -1,6 +1,10 @@
Writing documentation for OpenCV {#tutorial_documentation}
================================
@prev_tutorial{tutorial_display_image}
@next_tutorial{tutorial_transition_guide}
@tableofcontents
Doxygen overview {#tutorial_documentation_overview}
@ -47,6 +51,9 @@ Generate documentation {#tutorial_documentation_generate}
@code{.sh}
make check_pylint
@endcode
@note [Pylint](https://www.pylint.org/#install) must be installed before running cmake to be
able to test Python code. You can install using your system's package manager, or with pip:
@code{.sh} pip install pylint @endcode
Quick start {#tutorial_documentation_quick_start}
===========

View File

@ -1,6 +1,9 @@
Installation in iOS {#tutorial_ios_install}
===================
@prev_tutorial{tutorial_macos_install}
@next_tutorial{tutorial_arm_crosscompile_with_cmake}
Required Packages
-----------------

View File

@ -1,6 +1,10 @@
Using OpenCV Java with Eclipse {#tutorial_java_eclipse}
==============================
@prev_tutorial{tutorial_java_dev_intro}
@next_tutorial{tutorial_clojure_dev_intro}
Since version 2.4.4 [OpenCV supports Java](http://opencv.org/opencv-java-api.html). In this tutorial
I will explain how to setup development environment for using OpenCV Java with Eclipse in
**Windows**, so you can enjoy the benefits of garbage collected, very refactorable (rename variable,

View File

@ -1,6 +1,9 @@
Using OpenCV with Eclipse (plugin CDT) {#tutorial_linux_eclipse}
======================================
@prev_tutorial{tutorial_linux_gcc_cmake}
@next_tutorial{tutorial_windows_install}
Prerequisites
-------------
Two ways, one by forming a project directly, and another by CMake Prerequisites

View File

@ -1,6 +1,10 @@
Using OpenCV with gcc and CMake {#tutorial_linux_gcc_cmake}
===============================
@prev_tutorial{tutorial_linux_install}
@next_tutorial{tutorial_linux_eclipse}
@note We assume that you have successfully installed OpenCV in your workstation.
- The easiest way of using OpenCV in your code is to use [CMake](http://www.cmake.org/). A few

View File

@ -1,6 +1,9 @@
Installation in Linux {#tutorial_linux_install}
=====================
@next_tutorial{tutorial_linux_gcc_cmake}
The following steps have been tested for Ubuntu 10.04 but should work with other distros as well.
Required Packages

View File

@ -1,6 +1,10 @@
Installation in MacOS {#tutorial_macos_install}
=====================
@prev_tutorial{tutorial_android_ocl_intro}
@next_tutorial{tutorial_ios_install}
The following steps have been tested for MacOSX (Mavericks) but should work with other versions as well.
Required Packages
@ -35,6 +39,8 @@ Installing CMake
cmake --version
@endcode
@note You can use [Homebrew](https://brew.sh/) to install CMake with @code{.bash} brew install cmake @endcode
Getting OpenCV Source Code
--------------------------

View File

@ -1,6 +1,10 @@
Transition guide {#tutorial_transition_guide}
================
@prev_tutorial{tutorial_documentation}
@next_tutorial{tutorial_cross_referencing}
@tableofcontents
Changes overview {#tutorial_transition_overview}

View File

@ -1,6 +1,10 @@
Installation in Windows {#tutorial_windows_install}
=======================
@prev_tutorial{tutorial_linux_eclipse}
@next_tutorial{tutorial_windows_visual_studio_opencv}
The description here was tested on Windows 7 SP1. Nevertheless, it should also work on any other
relatively modern version of Windows OS. If you encounter errors after following the steps described
below, feel free to contact us via our [OpenCV Q&A forum](http://answers.opencv.org). We'll do our

View File

@ -1,6 +1,10 @@
Image Watch: viewing in-memory images in the Visual Studio debugger {#tutorial_windows_visual_studio_image_watch}
===================================================================
@prev_tutorial{tutorial_windows_visual_studio_opencv}
@next_tutorial{tutorial_java_dev_intro}
Image Watch is a plug-in for Microsoft Visual Studio that lets you to visualize in-memory images
(*cv::Mat* or *IplImage_* objects, for example) while debugging an application. This can be helpful
for tracking down bugs, or for simply understanding what a given piece of code is doing.

View File

@ -1,6 +1,10 @@
How to build applications with OpenCV inside the "Microsoft Visual Studio" {#tutorial_windows_visual_studio_opencv}
==========================================================================
@prev_tutorial{tutorial_windows_install}
@next_tutorial{tutorial_windows_visual_studio_image_watch}
Everything I describe here will apply to the `C\C++` interface of OpenCV. I start out from the
assumption that you have read and completed with success the @ref tutorial_windows_install tutorial.
Therefore, before you go any further make sure you have an OpenCV directory that contains the OpenCV

View File

@ -1,6 +1,8 @@
OpenCV iOS Hello {#tutorial_hello}
================
@next_tutorial{tutorial_image_manipulation}
Goal
----

View File

@ -1,6 +1,9 @@
OpenCV iOS - Image Processing {#tutorial_image_manipulation}
=============================
@prev_tutorial{tutorial_hello}
@next_tutorial{tutorial_video_processing}
Goal
----

View File

@ -1,6 +1,9 @@
OpenCV iOS - Video Processing {#tutorial_video_processing}
=============================
@prev_tutorial{tutorial_image_manipulation}
This tutorial explains how to process video frames using the iPhone's camera and OpenCV.
Prerequisites:

View File

@ -1,6 +1,8 @@
Introduction to Principal Component Analysis (PCA) {#tutorial_introduction_to_pca}
=======================================
@prev_tutorial{tutorial_non_linear_svms}
Goal
----

View File

@ -1,6 +1,8 @@
Introduction to Support Vector Machines {#tutorial_introduction_to_svm}
=======================================
@next_tutorial{tutorial_non_linear_svms}
Goal
----

View File

@ -1,6 +1,9 @@
Support Vector Machines for Non-Linearly Separable Data {#tutorial_non_linear_svms}
=======================================================
@prev_tutorial{tutorial_introduction_to_svm}
@next_tutorial{tutorial_introduction_to_pca}
Goal
----

View File

@ -1,6 +1,8 @@
Cascade Classifier {#tutorial_cascade_classifier}
==================
@next_tutorial{tutorial_traincascade}
Goal
----

View File

@ -1,6 +1,8 @@
Cascade Classifier Training {#tutorial_traincascade}
===========================
@prev_tutorial{tutorial_cascade_classifier}
Introduction
------------

View File

@ -1,6 +1,8 @@
How to Use Background Subtraction Methods {#tutorial_background_subtraction}
=========================================
@next_tutorial{tutorial_meanshift}
- Background subtraction (BS) is a common and widely used technique for generating a foreground
mask (namely, a binary image containing the pixels belonging to moving objects in the scene) by
using static cameras.

View File

@ -1,6 +1,9 @@
Meanshift and Camshift {#tutorial_meanshift}
======================
@prev_tutorial{tutorial_background_subtraction}
@next_tutorial{tutorial_optical_flow}
Goal
----

View File

@ -1,6 +1,8 @@
Optical Flow {#tutorial_optical_flow}
============
@prev_tutorial{tutorial_meanshift}
Goal
----

View File

@ -1,6 +1,8 @@
Using Creative Senz3D and other Intel Perceptual Computing SDK compatible depth sensors {#tutorial_intelperc}
=======================================================================================
@prev_tutorial{tutorial_kinect_openni}
**Note**: this tutorial is partially obsolete since PerC SDK has been replaced with RealSense SDK
Depth sensors compatible with Intel Perceptual Computing SDK are supported through VideoCapture

View File

@ -1,6 +1,10 @@
Using Kinect and other OpenNI compatible depth sensors {#tutorial_kinect_openni}
======================================================
@prev_tutorial{tutorial_video_write}
@next_tutorial{tutorial_intelperc}
Depth sensors compatible with OpenNI (Kinect, XtionPRO, ...) are supported through VideoCapture
class. Depth map, BGR image and some other formats of output can be retrieved by using familiar
interface of VideoCapture.

View File

@ -1,6 +1,8 @@
Video Input with OpenCV and similarity measurement {#tutorial_video_input_psnr_ssim}
==================================================
@next_tutorial{tutorial_video_write}
Goal
----

View File

@ -1,6 +1,9 @@
Creating a video with OpenCV {#tutorial_video_write}
============================
@prev_tutorial{tutorial_video_input_psnr_ssim}
@next_tutorial{tutorial_kinect_openni}
Goal
----

View File

@ -556,6 +556,30 @@ CV__DNN_INLINE_NS_BEGIN
static Ptr<Layer> create(const LayerParams& params);
};
class CV_EXPORTS DataAugmentationLayer : public Layer
{
public:
static Ptr<DataAugmentationLayer> create(const LayerParams& params);
};
class CV_EXPORTS CorrelationLayer : public Layer
{
public:
static Ptr<CorrelationLayer> create(const LayerParams& params);
};
class CV_EXPORTS AccumLayer : public Layer
{
public:
static Ptr<AccumLayer> create(const LayerParams& params);
};
class CV_EXPORTS FlowWarpLayer : public Layer
{
public:
static Ptr<FlowWarpLayer> create(const LayerParams& params);
};
class CV_EXPORTS PriorBoxLayer : public Layer
{
public:

View File

@ -465,6 +465,35 @@ public:
net.mutable_layer(li)->mutable_bottom()->RemoveLast();
type = "Eltwise";
}
else if (type == "Resample")
{
CV_Assert(layer.bottom_size() == 1 || layer.bottom_size() == 2);
type = "Resize";
String interp = toLowerCase(layerParams.get<String>("type"));
layerParams.set("interpolation", interp == "linear" ? "bilinear" : interp);
if (layerParams.has("factor"))
{
float factor = layerParams.get<float>("factor");
CV_Assert(layer.bottom_size() != 2 || factor == 1.0);
layerParams.set("zoom_factor", factor);
if ((interp == "linear" && factor != 1.0) ||
(interp == "nearest" && factor < 1.0))
CV_Error(Error::StsNotImplemented, "Unsupported Resample mode");
}
}
else if ("Convolution" == type)
{
CV_Assert(layer.bottom_size() == layer.top_size());
for (int i = 0; i < layer.bottom_size(); i++)
{
int conv_id = dstNet.addLayer(layer.top(i), type, layerParams);
addInput(layer.bottom(i), conv_id, 0, dstNet);
addedBlobs.push_back(BlobNote(layer.top(i), conv_id, 0));
}
continue;
}
else if ("ConvolutionDepthwise" == type)
{
type = "Convolution";

View File

@ -132,6 +132,10 @@ void initializeLayerFactory()
CV_DNN_REGISTER_LAYER_CLASS(Padding, PaddingLayer);
CV_DNN_REGISTER_LAYER_CLASS(Proposal, ProposalLayer);
CV_DNN_REGISTER_LAYER_CLASS(Scale, ScaleLayer);
CV_DNN_REGISTER_LAYER_CLASS(DataAugmentation, DataAugmentationLayer);
CV_DNN_REGISTER_LAYER_CLASS(Correlation, CorrelationLayer);
CV_DNN_REGISTER_LAYER_CLASS(Accum, AccumLayer);
CV_DNN_REGISTER_LAYER_CLASS(FlowWarp, FlowWarpLayer);
CV_DNN_REGISTER_LAYER_CLASS(LSTM, LSTMLayer);
}

View File

@ -0,0 +1,141 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright (C) 2020, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "../precomp.hpp"
#include "layers_common.hpp"
namespace cv { namespace dnn {
class AccumLayerImpl CV_FINAL : public AccumLayer
{
public:
AccumLayerImpl(const LayerParams& params)
{
setParamsFrom(params);
top_height = params.get<int>("top_height", 0);
top_width = params.get<int>("top_width", 0);
divisor = params.get<int>("size_divisible_by", 0);
have_reference = params.get<String>("have_reference", "false") == "true";
}
virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
const int requiredOutputs,
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const CV_OVERRIDE
{
std::vector<int> outShape;
int batch = inputs[0][0];
outShape.push_back(batch);
if (have_reference)
{
CV_Assert(inputs.size() >= 2);
int totalchannels = 0;
for (int i = 0; i < inputs.size() - 1; i++) {
CV_Assert(inputs[i][0] == batch);
totalchannels += inputs[i][1];
}
outShape.push_back(totalchannels);
int height = inputs.back()[2];
int width = inputs.back()[3];
outShape.push_back(height);
outShape.push_back(width);
}
else
{
int maxwidth = -1;
int maxheight = -1;
int totalchannels = 0;
// Find largest blob size and count total channels
for (int i = 0; i < inputs.size(); ++i)
{
totalchannels += inputs[i][1];
maxheight = std::max(maxheight, inputs[i][2]);
maxwidth = std::max(maxwidth, inputs[i][3]);
CV_Assert(inputs[i][0] == batch);
}
outShape.push_back(totalchannels);
int out_h = divisor ? static_cast<int>(ceil(maxheight / divisor) * divisor) : top_height;
int out_w = divisor ? static_cast<int>(ceil(maxwidth / divisor) * divisor) : top_width;
// Layer can specify custom top size which is larger than default
if (out_h <= maxheight || out_w <= maxwidth)
{
out_h = maxheight;
out_w = maxwidth;
}
outShape.push_back(out_h);
outShape.push_back(out_w);
}
outputs.assign(1, outShape);
return false;
}
virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
{
LayerParams resizeParams;
resizeParams.set("interpolation", "bilinear");
resizeParams.set("align_corners", true);
resize = ResizeLayer::create(resizeParams);
}
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
std::vector<Mat> inputs, outputs;
inputs_arr.getMatVector(inputs);
outputs_arr.getMatVector(outputs);
const int out_h = outputs[0].size[2];
const int out_w = outputs[0].size[3];
float* out_data = outputs[0].ptr<float>();
std::vector<int> sizes(&outputs[0].size[0], &outputs[0].size[0] + outputs[0].size.dims());
for (int i = 0; i < inputs.size() - have_reference; i++)
{
sizes[1] = inputs[i].size[1];
Mat outSlice(sizes, CV_32F, out_data);
if (out_h == inputs[i].size[2] && out_w == inputs[i].size[3])
{
inputs[i].copyTo(outSlice);
}
else
{
std::vector<Mat> inp_slices, out_slices;
inp_slices.push_back(inputs[i]);
out_slices.push_back(outSlice);
resize->finalize(inp_slices, out_slices);
resize->forward(inp_slices, out_slices, internals_arr);
}
out_data += outSlice.total(1);
}
}
private:
int top_height;
int top_width;
int divisor;
bool have_reference;
Ptr<ResizeLayer> resize;
};
Ptr<AccumLayer> AccumLayer::create(const LayerParams& params)
{
return Ptr<AccumLayer>(new AccumLayerImpl(params));
}
}} // namespace cv::dnn

View File

@ -1389,6 +1389,13 @@ public:
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
#if CV_TRY_SSE
uint32_t ftzMode = _MM_GET_FLUSH_ZERO_MODE();
uint32_t dazMode = _MM_GET_DENORMALS_ZERO_MODE();
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
#endif
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
@ -1471,6 +1478,10 @@ public:
ParallelConv::run(inputs[0], outputs[0], weightsMat, biasvec, reluslope,
kernel_size, strides, pads_begin, pads_end, dilations, activ.get(), ngroups, nstripes);
}
#if CV_TRY_SSE
_MM_SET_FLUSH_ZERO_MODE(ftzMode);
_MM_SET_DENORMALS_ZERO_MODE(dazMode);
#endif
}
#ifdef HAVE_CUDA

View File

@ -0,0 +1,207 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright (C) 2020, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "../precomp.hpp"
#include "layers_common.hpp"
namespace cv { namespace dnn {
class CorrelationLayerImpl CV_FINAL : public CorrelationLayer
{
public:
CorrelationLayerImpl(const LayerParams& params)
{
setParamsFrom(params);
pad = params.get<int>("pad", 0);
CV_Assert_N(params.has("kernel_size"), params.has("max_displacement"));
max_displacement = params.get<int>("max_displacement");
kernel = params.get<int>("kernel_size");
if (kernel % 2 == 0)
CV_Error(Error::StsNotImplemented, "Odd kernel size required.");
stride_1 = params.get<int>("stride_1", 1);
stride_2 = params.get<int>("stride_2", 1);
}
virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
const int requiredOutputs,
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const CV_OVERRIDE
{
CV_Assert_N(inputs.size() == 2, inputs[0].size() == 4, inputs[1].size() == 4);
int padded_height = inputs[0][2] + 2 * pad;
int padded_width = inputs[0][3] + 2 * pad;
int kernel_radius = (kernel - 1) / 2;
int border_size = max_displacement + kernel_radius;
int neighborhood_grid_radius = max_displacement / stride_2;
int neighborhood_grid_width = neighborhood_grid_radius * 2 + 1;
std::vector<int> outShape;
int num = inputs[0][0];
outShape.push_back(num);
int out_c = neighborhood_grid_width * neighborhood_grid_width;
outShape.push_back(out_c);
int out_h = ceil(static_cast<float>(padded_height - border_size * 2) / stride_1);
int out_w = ceil(static_cast<float>(padded_width - border_size * 2) / stride_1);
CV_Assert_N(out_h >= 1, out_w >= 1);
outShape.push_back(out_h);
outShape.push_back(out_w);
outputs.assign(1, outShape);
return false;
}
virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays) CV_OVERRIDE
{
std::vector<Mat> inputs;
inputs_arr.getMatVector(inputs);
int padded_height = inputs[0].size[2] + 2 * pad;
int padded_width = inputs[0].size[3] + 2 * pad;
int size[] = {inputs[0].size[0], padded_height, padded_width, inputs[0].size[1]};
rbot0 = Mat(4, &size[0], CV_32F, float(0));
rbot1 = Mat(4, &size[0], CV_32F, float(0));
}
void blobRearrangeKernel2(const Mat& input, Mat& output)
{
const int num = input.size[0];
const int channels = input.size[1];
const int height = input.size[2];
const int width = input.size[3];
const int area = height * width;
const int pad_area = (width + 2 * pad) * (height + 2 * pad);
const float* in = input.ptr<float>();
float* out = output.ptr<float>();
for (int n = 0; n < num; n++)
{
for (int ch = 0; ch < channels; ch++)
{
for (int xy = 0; xy < area; xy++)
{
float value = in[(n * channels + ch) * area + xy];
int xpad = (xy % width + pad);
int ypad = (xy / width + pad);
int xypad = ypad * (width + 2 * pad) + xpad;
out[(n * pad_area + xypad) * channels + ch] = value;
}
}
}
}
void correlationKernelSubtraction(const Mat& input0, const Mat& input1, Mat& output, int item)
{
const int inp_h = input0.size[1];
const int inp_w = input0.size[2];
const int inp_c = input0.size[3];
const int out_c = output.size[1];
const int out_h = output.size[2];
const int out_w = output.size[3];
int topcount = output.total(1);
int neighborhood_grid_radius = max_displacement / stride_2;
int neighborhood_grid_width = neighborhood_grid_radius * 2 + 1;
const float* inp0_data = input0.ptr<float>();
const float* inp1_data = input1.ptr<float>();
float* out_data = output.ptr<float>();
int sumelems = kernel * kernel * inp_c;
std::vector<float> patch_data(sumelems, 0);
for (int y = 0; y < out_h; y++)
{
for (int x = 0; x < out_w; x++)
{
int x1 = x * stride_1 + max_displacement;
int y1 = y * stride_1 + max_displacement;
for (int j = 0; j < kernel; j++)
{
for (int i = 0; i < kernel; i++)
{
int ji_off = ((j * kernel) + i) * inp_c;
for (int ch = 0; ch < inp_c; ch++)
{
int idx1 = ((item * inp_h + y1 + j) * inp_w + x1 + i) * inp_c + ch;
int idxPatchData = ji_off + ch;
patch_data[idxPatchData] = inp0_data[idx1];
}
}
}
for (int out_ch = 0; out_ch < out_c; out_ch++)
{
float sum = 0;
int s2o = (out_ch % neighborhood_grid_width - neighborhood_grid_radius) * stride_2;
int s2p = (out_ch / neighborhood_grid_width - neighborhood_grid_radius) * stride_2;
int x2 = x1 + s2o;
int y2 = y1 + s2p;
for (int j = 0; j < kernel; j++)
{
for (int i = 0; i < kernel; i++)
{
int ji_off = ((j * kernel) + i) * inp_c;
for (int ch = 0; ch < inp_c; ch++)
{
int idxPatchData = ji_off + ch;
int idx2 = ((item * inp_h + y2 + j) * inp_w + x2 + i) * inp_c + ch;
sum += patch_data[idxPatchData] * inp1_data[idx2];
}
}
}
int index = ((out_ch * out_h + y) * out_w) + x;
out_data[index + item * topcount] = static_cast<float>(sum) / sumelems;
}
}
}
}
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
std::vector<Mat> inputs, outputs, internals;
inputs_arr.getMatVector(inputs);
outputs_arr.getMatVector(outputs);
internals_arr.getMatVector(internals);
blobRearrangeKernel2(inputs[0], rbot0);
blobRearrangeKernel2(inputs[1], rbot1);
for (int i = 0; i < inputs[0].size[0]; i++)
{
correlationKernelSubtraction(rbot0, rbot1, outputs[0], i);
}
}
private:
int pad;
int kernel;
int max_displacement;
int stride_1;
int stride_2;
Mat rbot0;
Mat rbot1;
};
Ptr<CorrelationLayer> CorrelationLayer::create(const LayerParams& params)
{
return Ptr<CorrelationLayer>(new CorrelationLayerImpl(params));
}
}} // namespace cv::dnn

View File

@ -0,0 +1,117 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright (C) 2020, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "../precomp.hpp"
#include "layers_common.hpp"
namespace cv { namespace dnn {
class FlowWarpLayerImpl CV_FINAL : public FlowWarpLayer
{
public:
FlowWarpLayerImpl(const LayerParams& params)
{
setParamsFrom(params);
String fill_string = toLowerCase(params.get<String>("FillParameter", "ZERO"));
if (fill_string != "zero")
CV_Error(Error::StsNotImplemented, "Only zero filling supported.");
fill_value = 0;
}
virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
const int requiredOutputs,
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const CV_OVERRIDE
{
CV_Assert(inputs.size() == 2);
CV_Assert_N(inputs[0][0] == inputs[1][0], inputs[1][1] == 2,
inputs[0][2] == inputs[1][2], inputs[0][3] == inputs[1][3]);
outputs.assign(1, inputs[0]);
return false;
}
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
std::vector<Mat> inputs, outputs;
inputs_arr.getMatVector(inputs);
outputs_arr.getMatVector(outputs);
const int out_n = outputs[0].size[0];
const int out_c = outputs[0].size[1];
const int out_h = outputs[0].size[2];
const int out_w = outputs[0].size[3];
const int area = out_w * out_h;
const int total = area * out_c;
const float* image_data = inputs[0].ptr<float>();
const float* flow_data = inputs[1].ptr<float>();
float* out_data = outputs[0].ptr<float>();
for (int n = 0; n < out_n; n++)
{
int off = total * n;
for (int x = 0; x < out_w; x++)
{
for (int y = 0; y < out_h; y++)
{
int idx = 2 * area * n + y * out_w + x;
float fx = flow_data[idx];
float fy = flow_data[idx + area];
float x2 = x + fx;
float y2 = y + fy;
if (x2 >= 0 && y2 >= 0 && x2 < out_w && y2 < out_h)
{
int ix2_L = x2;
float alpha = x2 - ix2_L;
int iy2_T = y2;
float beta = y2 - iy2_T;
int ix2_R = std::min(ix2_L + 1, out_w - 1);
int iy2_B = std::min(iy2_T + 1, out_h - 1);
for (int c = 0; c < out_c; c++)
{
float TL = image_data[off + c * area + iy2_T * out_w + ix2_L];
float TR = image_data[off + c * area + iy2_T * out_w + ix2_R];
float BL = image_data[off + c * area + iy2_B * out_w + ix2_L];
float BR = image_data[off + c * area + iy2_B * out_w + ix2_R];
out_data[off + c * area + y * out_w + x] = (1 - alpha) * (1 - beta) * TL +
(1 - alpha) * beta * BL +
alpha * (1 - beta) * TR +
alpha * beta * BR;
}
}
else
{
for (int c = 0; c < out_c; c++)
out_data[off + c * area + y * out_w + x] = fill_value;
}
}
}
}
}
private:
float fill_value;
};
Ptr<FlowWarpLayer> FlowWarpLayer::create(const LayerParams& params)
{
return Ptr<FlowWarpLayer>(new FlowWarpLayerImpl(params));
}
}} // namespace cv::dnn

View File

@ -51,10 +51,15 @@ public:
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const CV_OVERRIDE
{
CV_Assert_N(inputs.size() == 1, inputs[0].size() == 4);
CV_Assert_N(inputs.size() == 1 || inputs.size() == 2, inputs[0].size() == 4);
outputs.resize(1, inputs[0]);
outputs[0][2] = zoomFactorHeight > 0 ? (outputs[0][2] * zoomFactorHeight) : outHeight;
outputs[0][3] = zoomFactorWidth > 0 ? (outputs[0][3] * zoomFactorWidth) : outWidth;
if (inputs.size() == 1) {
outputs[0][2] = zoomFactorHeight > 0 ? (outputs[0][2] * zoomFactorHeight) : outHeight;
outputs[0][3] = zoomFactorWidth > 0 ? (outputs[0][3] * zoomFactorWidth) : outWidth;
} else {
outputs[0][2] = inputs[1][2];
outputs[0][3] = inputs[1][3];
}
// We can work in-place (do nothing) if input shape == output shape.
return (outputs[0][2] == inputs[0][2]) && (outputs[0][3] == inputs[0][3]);
}

View File

@ -372,5 +372,118 @@ Ptr<Layer> ShiftLayer::create(const LayerParams& params)
return Ptr<ScaleLayer>(new ScaleLayerImpl(scaleParams));
}
class DataAugmentationLayerImpl CV_FINAL : public DataAugmentationLayer
{
public:
DataAugmentationLayerImpl(const LayerParams& params)
{
setParamsFrom(params);
recompute_mean = params.get<int>("recompute_mean", 1);
CV_CheckGT(recompute_mean, 0, "");
mean_per_pixel = params.get<bool>("mean_per_pixel", false);
}
bool getMemoryShapes(const std::vector<MatShape> &inputs,
const int requiredOutputs,
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const CV_OVERRIDE
{
CV_Assert_N(inputs.size() == 1, blobs.size() == 3);
CV_Assert_N(blobs[0].total() == 1, blobs[1].total() == total(inputs[0], 1),
blobs[2].total() == inputs[0][1]);
outputs.assign(1, inputs[0]);
return true;
}
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
std::vector<Mat> inputs, outputs;
inputs_arr.getMatVector(inputs);
outputs_arr.getMatVector(outputs);
CV_Assert_N(outputs.size() == 1, blobs.size() == 3, inputs.size() == 1);
int num_iter = 0;
float* inpData = inputs[0].ptr<float>();
float* outData = outputs[0].ptr<float>();
Mat data_mean_cpu = blobs[1].clone();
Mat data_mean_per_channel_cpu = blobs[2].clone();
const int numWeights = data_mean_cpu.total();
CV_Assert(numWeights != 0);
++num_iter;
if (num_iter <= recompute_mean)
{
data_mean_cpu *= (num_iter - 1);
const int batch = inputs[0].size[0];
float alpha = 1.0 / batch;
for (int i = 0; i < batch; ++i)
{
Mat inpSlice(1, numWeights, CV_32F, inpData);
inpSlice = alpha * inpSlice;
add(data_mean_cpu.reshape(1, 1), inpSlice, data_mean_cpu.reshape(1, 1));
inpData += numWeights;
}
data_mean_cpu *= (1.0 / num_iter);
int newsize[] = {blobs[1].size[1], (int)blobs[1].total(2)};
reduce(data_mean_cpu.reshape(1, 2, &newsize[0]), data_mean_per_channel_cpu, 1, REDUCE_SUM, CV_32F);
int area = blobs[1].total(2);
data_mean_per_channel_cpu *= (1.0 / area);
}
MatShape inpShape = shape(inputs[0]);
inpData = inputs[0].ptr<float>();
if (mean_per_pixel)
{
int numSlices = inputs[0].size[0];
for (int i = 0; i < numSlices; ++i)
{
Mat inpSlice(1, numWeights, CV_32F, inpData);
Mat outSlice(1, numWeights, CV_32F, outData);
add(inpSlice, (-1) * data_mean_cpu, outSlice);
inpData += numWeights;
outData += numWeights;
}
}
else
{
int numSlices = inpShape[1];
int count = numWeights / numSlices;
for (int i = 0; i < numSlices; ++i)
{
Mat inpSlice(1, count, CV_32F, inpData);
Mat outSlice(1, count, CV_32F, outData);
float coeff = data_mean_per_channel_cpu.reshape(1, 1).at<float>(0, i);
outSlice = inpSlice - coeff;
inpData += count;
outData += count;
}
}
}
private:
int recompute_mean;
bool mean_per_pixel;
};
Ptr<DataAugmentationLayer> DataAugmentationLayer::create(const LayerParams& params)
{
return Ptr<DataAugmentationLayer>(new DataAugmentationLayerImpl(params));
}
} // namespace dnn
} // namespace cv

View File

@ -97,29 +97,68 @@ class Test_Caffe_layers : public DNNTestLayer
{
public:
void testLayerUsingCaffeModels(const String& basename, bool useCaffeModel = false,
bool useCommonInputBlob = true, double l1 = 0.0,
double lInf = 0.0)
bool useCommonInputBlob = true, double l1 = 0.0, double lInf = 0.0,
int numInps = 1, int numOuts = 1)
{
CV_Assert_N(numInps >= 1, numInps <= 10, numOuts >= 1, numOuts <= 10);
String prototxt = _tf(basename + ".prototxt");
String caffemodel = _tf(basename + ".caffemodel");
String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy");
String outfile = _tf(basename + ".npy");
std::vector<Mat> inps, refs, outs;
Mat inp = blobFromNPY(inpfile);
Mat ref = blobFromNPY(outfile);
checkBackend(&inp, &ref);
if (numInps > 1)
{
for (int i = 0; i < numInps; i++)
{
String inpfile = _tf(basename + cv::format(".input_%d.npy", i));
inps.push_back(blobFromNPY(inpfile));
}
}
else
{
String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy");
inps.push_back(blobFromNPY(inpfile));
}
if (numOuts > 1)
{
for (int i = 0; i < numOuts; i++)
{
String outfile = _tf(basename + cv::format("_%d.npy", i));
refs.push_back(blobFromNPY(outfile));
}
}
else
{
String outfile = _tf(basename + ".npy");
refs.push_back(blobFromNPY(outfile));
}
Net net = readNetFromCaffe(prototxt, (useCaffeModel) ? caffemodel : String());
ASSERT_FALSE(net.empty());
checkBackend(&inps[0], &refs[0]);
net.setPreferableBackend(backend);
net.setPreferableTarget(target);
net.setInput(inp, "input");
Mat out = net.forward("output");
String inp_name = "input";
if (numInps > 1)
{
for (int i = 0; i < numInps; i++)
{
net.setInput(inps[i], inp_name + cv::format("_%d", i));
}
}
else
{
net.setInput(inps.back(), inp_name);
}
normAssert(ref, out, "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf);
net.forward(outs);
for (int i = 0; i < refs.size(); i++)
{
normAssert(refs[i], outs[i], "", l1 ? l1 : default_l1, lInf ? lInf : default_lInf);
}
}
};
@ -579,6 +618,58 @@ TEST_F(Layer_RNN_Test, get_set_test)
EXPECT_EQ(shape(outputs[1]), shape(nT, nS, nH));
}
TEST_P(Test_Caffe_layers, Accum)
{
if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL, CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
testLayerUsingCaffeModels("accum", false, false, 0.0, 0.0, 2);
testLayerUsingCaffeModels("accum_ref", false, false, 0.0, 0.0, 2);
}
TEST_P(Test_Caffe_layers, FlowWarp)
{
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
testLayerUsingCaffeModels("flow_warp", false, false, 0.0, 0.0, 2);
}
TEST_P(Test_Caffe_layers, ChannelNorm)
{
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
testLayerUsingCaffeModels("channel_norm", false, false);
}
TEST_P(Test_Caffe_layers, DataAugmentation)
{
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
testLayerUsingCaffeModels("data_augmentation", true, false);
}
TEST_P(Test_Caffe_layers, Resample)
{
if (backend != DNN_BACKEND_OPENCV)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
testLayerUsingCaffeModels("nearest_2inps", false, false, 0.0, 0.0, 2);
testLayerUsingCaffeModels("nearest", false, false);
}
TEST_P(Test_Caffe_layers, Correlation)
{
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER,
CV_TEST_TAG_DNN_SKIP_OPENCL, CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
testLayerUsingCaffeModels("correlation", false, false, 0.0, 0.0, 2);
}
TEST_P(Test_Caffe_layers, Convolution2Inputs)
{
testLayerUsingCaffeModels("conv_2_inps", true, false, 0.0, 0.0, 2);
}
TEST_P(Test_Caffe_layers, ROIPooling_Accuracy)
{
Net net = readNetFromCaffe(_tf("net_roi_pooling.prototxt"));

View File

@ -392,7 +392,7 @@ int CvCaptureCAM::startCaptureDevice(int cameraNum) {
[mCaptureDecompressedVideoOutput setVideoSettings:pixelBufferOptions];
mCaptureDecompressedVideoOutput.alwaysDiscardsLateVideoFrames = YES;
#if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) && !TARGET_OS_MACCATALYST
#if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) && (!defined(TARGET_OS_MACCATALYST) || !TARGET_OS_MACCATALYST)
mCaptureDecompressedVideoOutput.minFrameDuration = CMTimeMake(1, 30);
#endif

View File

@ -299,7 +299,7 @@
}
else
{
#if !TARGET_OS_MACCATALYST
#if (!defined(TARGET_OS_MACCATALYST) || !TARGET_OS_MACCATALYST)
// Deprecated in 6.0; here for backward compatibility
if ([self.captureVideoPreviewLayer isOrientationSupported])
{

View File

@ -0,0 +1,85 @@
#!/usr/bin/env python
'''
This sample using FlowNet v2 model to calculate optical flow.
Original paper: https://arxiv.org/abs/1612.01925.
Original repo: https://github.com/lmb-freiburg/flownet2.
Download the converted .caffemodel model from https://drive.google.com/open?id=16qvE9VNmU39NttpZwZs81Ga8VYQJDaWZ
and .prototxt from https://drive.google.com/open?id=19bo6SWU2p8ZKvjXqMKiCPdK8mghwDy9b.
Otherwise download original model from https://lmb.informatik.uni-freiburg.de/resources/binaries/flownet2/flownet2-models.tar.gz,
convert .h5 model to .caffemodel and modify original .prototxt using .prototxt from link above.
'''
import argparse
import os.path
import numpy as np
import cv2 as cv
class OpticalFlow(object):
def __init__(self, proto, model, height, width):
self.net = cv.dnn.readNet(proto, model)
self.net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
self.height = height
self.width = width
def compute_flow(self, first_img, second_img):
inp0 = cv.dnn.blobFromImage(first_img, size=(self.width, self.height))
inp1 = cv.dnn.blobFromImage(second_img, size=(self.width, self.height))
self.net.setInput(inp0, "img0")
self.net.setInput(inp1, "img1")
flow = self.net.forward()
output = self.motion_to_color(flow)
return output
def motion_to_color(self, flow):
arr = np.arange(0, 255, dtype=np.uint8)
colormap = cv.applyColorMap(arr, cv.COLORMAP_HSV)
colormap = colormap.squeeze(1)
flow = flow.squeeze(0)
fx, fy = flow[0, ...], flow[1, ...]
rad = np.sqrt(fx**2 + fy**2)
maxrad = rad.max() if rad.max() != 0 else 1
ncols = arr.size
rad = rad[..., np.newaxis] / maxrad
a = np.arctan2(-fy / maxrad, -fx / maxrad) / np.pi
fk = (a + 1) / 2.0 * (ncols - 1)
k0 = fk.astype(np.int)
k1 = (k0 + 1) % ncols
f = fk[..., np.newaxis] - k0[..., np.newaxis]
col0 = colormap[k0] / 255.0
col1 = colormap[k1] / 255.0
col = (1 - f) * col0 + f * col1
col = np.where(rad <= 1, 1 - rad * (1 - col), col * 0.75)
output = (255.0 * col).astype(np.uint8)
return output
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Use this script to calculate optical flow using FlowNetv2',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-input', '-i', required=True, help='Path to input video file. Skip this argument to capture frames from a camera.')
parser.add_argument('--height', default=320, help='Input height')
parser.add_argument('--width', default=448, help='Input width')
parser.add_argument('--proto', '-p', default='FlowNet2_deploy.prototxt', help='Path to prototxt.')
parser.add_argument('--model', '-m', default='FlowNet2_weights.caffemodel', help='Path to caffemodel.')
args, _ = parser.parse_known_args()
if not os.path.isfile(args.model) or not os.path.isfile(args.proto):
raise OSError("Prototxt or caffemodel not exist")
winName = 'Calculation optical flow in OpenCV'
cv.namedWindow(winName, cv.WINDOW_NORMAL)
cap = cv.VideoCapture(args.input if args.input else 0)
hasFrame, first_frame = cap.read()
opt_flow = OpticalFlow(args.proto, args.model, args.height, args.width)
while cv.waitKey(1) < 0:
hasFrame, second_frame = cap.read()
if not hasFrame:
break
flow = opt_flow.compute_flow(first_frame, second_frame)
first_frame = second_frame
cv.imshow(winName, flow)