Browse Source

Implemented NvidiaOpticalFlow_1_0

pull/348/head
Canming Huang 5 years ago
parent
commit
9bfddeae6b
  1. 76
      Emgu.CV.Cuda/Optflow/INvidiaOpticalFlow.cs
  2. 131
      Emgu.CV.Cuda/Optflow/NvidiaOpticalFlow_1_0.cs
  3. 104
      Emgu.CV.Extern/cudaoptflow/cudaoptflow_c.cpp
  4. 40
      Emgu.CV.Extern/cudaoptflow/cudaoptflow_c.h

76
Emgu.CV.Cuda/Optflow/INvidiaOpticalFlow.cs

@ -0,0 +1,76 @@
//----------------------------------------------------------------------------
// Copyright (C) 2004-2020 by EMGU Corporation. All rights reserved.
//----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using Emgu.CV.Structure;
using Emgu.Util;
namespace Emgu.CV.Cuda
{
/// <summary>
/// Base Interface for optical flow algorithms using NVIDIA Optical Flow SDK
/// </summary>
public interface INvidiaOpticalFlow : IAlgorithm
{
/// <summary>
/// Pointer the the native cv::cuda::NvidiaOpticalFlow object.
/// </summary>
IntPtr NvidiaOpticalFlowPtr { get; }
}
public static partial class CudaInvoke
{
/// <summary>
/// Calculates Optical Flow using NVIDIA Optical Flow SDK.
/// NVIDIA GPUs starting with Turing contain a dedicated hardware accelerator for computing optical flow vectors between pairs of images.
/// The optical flow hardware accelerator generates block-based optical flow vectors.
/// The size of the block depends on hardware in use, and can be queried using the function getGridSize().
/// The block-based flow vectors generated by the hardware can be converted to dense representation(i.e.per-pixel flow vectors) using upSampler() helper function, if needed.
/// The flow vectors are stored in CV_16SC2 format with x and y components of each flow vector in 16-bit signed fixed point representation S10.5.
/// </summary>
/// <param name="nvidiaOpticalFlow">The nvidia optical flow object</param>
/// <param name="inputImage">Input image</param>
/// <param name="referenceImage">Reference image of the same size and the same type as input image.</param>
/// <param name="flow">A buffer consisting of inputImage.Size() / getGridSize() flow vectors in CV_16SC2 format.</param>
/// <param name="stream">Stream for the asynchronous version.</param>
/// <param name="hint">Hint buffer if client provides external hints. Must have same size as flow buffer. Caller can provide flow vectors as hints for optical flow calculation.</param>
/// <param name="cost">Cost buffer contains numbers indicating the confidence associated with each of the generated flow vectors. Higher the cost, lower the confidence. Cost buffer is of type CV_32SC1.</param>
public static void Calc(
this INvidiaOpticalFlow nvidiaOpticalFlow,
IInputArray inputImage,
IInputArray referenceImage,
IInputOutputArray flow,
Stream stream = null,
IInputArray hint = null,
IOutputArray cost = null)
{
using (InputArray iaInputImage = inputImage.GetInputArray())
using (InputArray iaReferenceImage = referenceImage.GetInputArray())
using (InputOutputArray ioaFlow = flow.GetInputOutputArray())
using (InputArray iaHint = (hint == null ? InputArray.GetEmpty() : hint.GetInputArray()))
using (OutputArray oaCost = (cost == null ? OutputArray.GetEmpty() : cost.GetOutputArray()))
cudaNvidiaOpticalFlowCalc(
nvidiaOpticalFlow.NvidiaOpticalFlowPtr,
iaInputImage,
iaReferenceImage,
ioaFlow,
(stream == null) ? IntPtr.Zero : stream.Ptr,
iaHint,
oaCost);
}
[DllImport(CvInvoke.ExternCudaLibrary, CallingConvention = CvInvoke.CvCallingConvention)]
private static extern void cudaNvidiaOpticalFlowCalc(
IntPtr nHWOpticalFlow,
IntPtr inputImage,
IntPtr referenceImage,
IntPtr flow,
IntPtr stream,
IntPtr hint,
IntPtr cost);
}
}

131
Emgu.CV.Cuda/Optflow/NvidiaOpticalFlow_1_0.cs

@ -0,0 +1,131 @@
//----------------------------------------------------------------------------
// Copyright (C) 2004-2020 by EMGU Corporation. All rights reserved.
//----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using Emgu.Util;
namespace Emgu.CV.Cuda
{
/// <summary>
/// Class for computing the optical flow vectors between two images using NVIDIA Optical Flow hardware and Optical Flow SDK 1.0.
/// </summary>
public class NvidiaOpticalFlow_1_0 : SharedPtrObject, INvidiaOpticalFlow
{
/// <summary>
/// Supported optical flow performance levels.
/// </summary>
public enum PerfLevel
{
/// <summary>
/// Undefined
/// </summary>
Undefined,
/// <summary>
/// Slow perf level results in lowest performance and best quality
/// </summary>
Slow = 5,
/// <summary>
/// Medium perf level results in low performance and medium quality
/// </summary>
Medium = 10,
/// <summary>
/// Fast perf level results in high performance and low quality
/// </summary>
Fast = 20,
/// <summary>
/// Max
/// </summary>
Max
};
private IntPtr _nvidiaHWOpticalFlow;
private IntPtr _algorithm;
/// <summary>
/// Instantiate NVIDIA Optical Flow
/// </summary>
/// <param name="width">Width of input image in pixels.</param>
/// <param name="height">Height of input image in pixels.</param>
/// <param name="perfPreset">Optional parameter. Refer https://developer.nvidia.com/opticalflow-sdk for details about presets. Defaults to Slow.</param>
/// <param name="enableTemporalHints">Optional Parameter. Flag to enable passing external hints buffer to calc(). Defaults to false.</param>
/// <param name="enableExternalHints">Optional Parameter. Flag to enable passing external hints buffer to calc(). Defaults to false.</param>
/// <param name="enableCostBuffer">Optional Parameter. Flag to enable cost buffer output from calc(). Defaults to false.</param>
/// <param name="gpuId">Optional parameter to select the GPU ID on which the optical flow should be computed. Useful in multi-GPU systems. Defaults to 0.</param>
public NvidiaOpticalFlow_1_0(
int width,
int height,
NvidiaOpticalFlow_1_0.PerfLevel perfPreset = PerfLevel.Slow,
bool enableTemporalHints = false,
bool enableExternalHints = false,
bool enableCostBuffer = false,
int gpuId = 0)
{
_ptr = CudaInvoke.cudaNvidiaOpticalFlow_1_0_Create(
width,
height,
perfPreset,
enableTemporalHints,
enableExternalHints,
enableCostBuffer,
gpuId,
ref _nvidiaHWOpticalFlow,
ref _algorithm,
ref _sharedPtr);
}
/// <summary>
/// Release all the unmanaged memory associated with this optical flow solver.
/// </summary>
protected override void DisposeObject()
{
if (_sharedPtr != IntPtr.Zero)
{
CudaInvoke.cudaNvidiaOpticalFlow_1_0_Release(ref _sharedPtr);
_nvidiaHWOpticalFlow = IntPtr.Zero;
_algorithm = IntPtr.Zero;
_ptr = IntPtr.Zero;
}
}
/// <summary>
/// Pointer to the NvidiaOpticalFlow object
/// </summary>
public IntPtr NvidiaOpticalFlowPtr
{
get { return _nvidiaHWOpticalFlow; }
}
/// <summary>
/// Pointer to the algorithm object
/// </summary>
public IntPtr AlgorithmPtr { get { return _algorithm; } }
}
public static partial class CudaInvoke
{
[DllImport(CvInvoke.ExternCudaLibrary, CallingConvention = CvInvoke.CvCallingConvention)]
internal static extern IntPtr cudaNvidiaOpticalFlow_1_0_Create(
int width,
int height,
NvidiaOpticalFlow_1_0.PerfLevel perfPreset,
[MarshalAs(CvInvoke.BoolMarshalType)]
bool enableTemporalHints,
[MarshalAs(CvInvoke.BoolMarshalType)]
bool enableExternalHints,
[MarshalAs(CvInvoke.BoolMarshalType)]
bool enableCostBuffer,
int gpuId,
ref IntPtr nHWOpticalFlow,
ref IntPtr algorithm,
ref IntPtr sharedPtr);
[DllImport(CvInvoke.ExternCudaLibrary, CallingConvention = CvInvoke.CvCallingConvention)]
internal extern static void cudaNvidiaOpticalFlow_1_0_Release(ref IntPtr flow);
}
}

104
Emgu.CV.Extern/cudaoptflow/cudaoptflow_c.cpp

@ -256,4 +256,106 @@ void cudaDensePyrLKOpticalFlowRelease(cv::Ptr<cv::cuda::SparsePyrLKOpticalFlow>*
void cudaCreateOpticalFlowNeedleMap(const cv::cuda::GpuMat* u, const cv::cuda::GpuMat* v, cv::cuda::GpuMat* vertex, cv::cuda::GpuMat* colors)
{
cv::cuda:: ::createOpticalFlowNeedleMap(*u, *v, *vertex, *colors);
}*/
}*/
//----------------------------------------------------------------------------
//
// NvidiaOpticalFlow_1_0
//
//----------------------------------------------------------------------------
cv::cuda::NvidiaOpticalFlow_1_0* cudaNvidiaOpticalFlow_1_0_Create(
int width,
int height,
cv::cuda::NvidiaOpticalFlow_1_0::NVIDIA_OF_PERF_LEVEL perfPreset,
bool enableTemporalHints,
bool enableExternalHints,
bool enableCostBuffer,
int gpuId,
cv::cuda::NvidiaHWOpticalFlow** nHWOpticalFlow,
cv::Algorithm** algorithm,
cv::Ptr<cv::cuda::NvidiaOpticalFlow_1_0>** sharedPtr)
{
#ifdef HAVE_OPENCV_CUDAOPTFLOW
cv::Ptr<cv::cuda::NvidiaOpticalFlow_1_0> ptr = cv::cuda::NvidiaOpticalFlow_1_0::create(
width,
height,
perfPreset,
enableTemporalHints,
enableExternalHints,
enableCostBuffer,
gpuId);
*sharedPtr = new cv::Ptr<cv::cuda::NvidiaOpticalFlow_1_0>(ptr);
cv::cuda::NvidiaOpticalFlow_1_0* flow = ptr.get();
*nHWOpticalFlow = dynamic_cast<cv::cuda::NvidiaHWOpticalFlow*>(flow);
*algorithm = dynamic_cast<cv::Algorithm*>(flow);
return flow;
#else
throw_no_cudaoptflow();
#endif
}
void cudaNvidiaOpticalFlow_1_0_UpSampler(
cv::cuda::NvidiaOpticalFlow_1_0* nFlow,
cv::_InputArray* flow,
int width,
int height,
int gridSize,
cv::_InputOutputArray* upsampledFlow)
{
#ifdef HAVE_OPENCV_CUDAOPTFLOW
nFlow->upSampler(*flow, width, height, gridSize, *upsampledFlow);
#else
throw_no_cudaoptflow();
#endif
}
void cudaNvidiaOpticalFlowCalc(
cv::cuda::NvidiaHWOpticalFlow* nHWOpticalFlow,
cv::_InputArray* inputImage,
cv::_InputArray* referenceImage,
cv::_InputOutputArray* flow,
cv::cuda::Stream* stream,
cv::_InputArray* hint,
cv::_OutputArray* cost)
{
#ifdef HAVE_OPENCV_CUDAOPTFLOW
nHWOpticalFlow->calc(
*inputImage,
*referenceImage,
*flow,
stream ? *stream : cv::cuda::Stream::Null(),
hint ? *hint : (cv::InputArray) cv::noArray(),
cost ? *cost : (cv::OutputArray) cv::noArray()
);
#else
throw_no_cudaoptflow();
#endif
}
void cudaNvidiaOpticalFlowCollectGarbage(cv::cuda::NvidiaHWOpticalFlow* nHWOpticalFlow)
{
#ifdef HAVE_OPENCV_CUDAOPTFLOW
nHWOpticalFlow->collectGarbage();
#else
throw_no_cudaoptflow();
#endif
}
int cudaNvidiaOpticalFlowGetGridSize(cv::cuda::NvidiaHWOpticalFlow* nHWOpticalFlow)
{
#ifdef HAVE_OPENCV_CUDAOPTFLOW
return nHWOpticalFlow->getGridSize();
#else
throw_no_cudaoptflow();
#endif
}
void cudaNvidiaOpticalFlow_1_0_Release(cv::Ptr<cv::cuda::NvidiaOpticalFlow_1_0>** flow)
{
#ifdef HAVE_OPENCV_CUDAOPTFLOW
delete* flow;
*flow = 0;
#else
throw_no_cudaoptflow();
#endif
}

40
Emgu.CV.Extern/cudaoptflow/cudaoptflow_c.h

@ -167,4 +167,44 @@ CVAPI(void) cudaOpticalFlowDualTvl1Release(cv::Ptr<cv::cuda::OpticalFlowDual_TVL
//----------------------------------------------------------------------------
CVAPI(void) cudaCreateOpticalFlowNeedleMap(const cv::cuda::GpuMat* u, const cv::cuda::GpuMat* v, cv::cuda::GpuMat* vertex, cv::cuda::GpuMat* colors);
*/
//----------------------------------------------------------------------------
//
// NvidiaOpticalFlow_1_0
//
//----------------------------------------------------------------------------
CVAPI(cv::cuda::NvidiaOpticalFlow_1_0*) cudaNvidiaOpticalFlow_1_0_Create(
int width,
int height,
cv::cuda::NvidiaOpticalFlow_1_0::NVIDIA_OF_PERF_LEVEL perfPreset,
bool enableTemporalHints,
bool enableExternalHints,
bool enableCostBuffer,
int gpuId,
cv::cuda::NvidiaHWOpticalFlow** nHWOpticalFlow,
cv::Algorithm** algorithm,
cv::Ptr<cv::cuda::NvidiaOpticalFlow_1_0>** sharedPtr);
CVAPI(void) cudaNvidiaOpticalFlow_1_0_UpSampler(
cv::cuda::NvidiaOpticalFlow_1_0* nFlow,
cv::_InputArray* flow,
int width,
int height,
int gridSize,
cv::_InputOutputArray* upsampledFlow);
CVAPI(void) cudaNvidiaOpticalFlowCalc(
cv::cuda::NvidiaHWOpticalFlow* nHWOpticalFlow,
cv::_InputArray* inputImage,
cv::_InputArray* referenceImage,
cv::_InputOutputArray* flow,
cv::cuda::Stream* stream,
cv::_InputArray* hint,
cv::_OutputArray* cost);
CVAPI(void) cudaNvidiaOpticalFlowCollectGarbage(cv::cuda::NvidiaHWOpticalFlow* nHWOpticalFlow);
CVAPI(int) cudaNvidiaOpticalFlowGetGridSize(cv::cuda::NvidiaHWOpticalFlow* nHWOpticalFlow);
CVAPI(void) cudaNvidiaOpticalFlow_1_0_Release(cv::Ptr<cv::cuda::NvidiaOpticalFlow_1_0>** flow);
#endif
Loading…
Cancel
Save