VPI - Vision Programming Interface

0.1.0 Release

Stereo Disparity

Overview

The Stereo Disparity application receives left and right stereo pair images and returns the disparity between them, which is a function of image depth. The result is saved into disparity.png.

This sample shows the following VPI features:

  • Creating and destroying a VPI device.
  • Wrapping an image hosted on CPU (the input) to be used by VPI.
  • Creating a VPI-managed 2D image where output will be written to
  • Create a properly-configured StereoProcess algorithm and submit it to the device.
  • Simple device synchronization.
  • Image locking to access its contents from CPU side.
  • Error handling.
  • Environment clean up.

Instructions

The usage is:

./vpi_sample_02_stereo_disparity <backend> <input image>

where

  • backend: either cpu, cuda or pva; it defines the backend that will perform the processing.
  • left image: left input image of a stereo pair, it accepts png, jpeg and possibly others.
  • right image: right input image of a stereo pair.

Here's one example:

./vpi_sample_02_stereo_disparity cuda ../assets/chair_stereo_left.png ../assets/chair_stereo_right.png

This is using the CUDA backend and the provided sample images. You can try with other stereo pair images, respecting the constraints imposed by the algorithm.

Source code

For convenience, here's the code that is also installed in the samples directory.

/*
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of NVIDIA CORPORATION nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <vpi/Image.h>
#include <vpi/Stream.h>
#include <cstring> // for memset
#include <iostream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#define CHECK_STATUS(STMT) \
do \
{ \
VPIStatus status = (STMT); \
if (status != VPI_SUCCESS) \
{ \
throw std::runtime_error(vpiStatusGetName(status)); \
} \
} while (0);
int main(int argc, char *argv[])
{
VPIImage left = nullptr;
VPIImage right = nullptr;
VPIImage disparity = nullptr;
VPIStream stream = nullptr;
VPIPayload stereo = nullptr;
int retval = 0;
try
{
if (argc != 4)
{
throw std::runtime_error(std::string("Usage: ") + argv[0] + " <cpu|pva|cuda> <left image> <right image>");
}
std::string strDevType = argv[1];
std::string strLeftFileName = argv[2];
std::string strRightFileName = argv[3];
// Load the input images
cv::Mat cvImageLeft = cv::imread(strLeftFileName, cv::IMREAD_GRAYSCALE);
if (cvImageLeft.empty())
{
throw std::runtime_error("Can't open '" + strLeftFileName + "'");
}
cv::Mat cvImageRight = cv::imread(strRightFileName, cv::IMREAD_GRAYSCALE);
if (cvImageRight.empty())
{
throw std::runtime_error("Can't open '" + strRightFileName + "'");
}
// Currently we only accept unsigned 16bpp inputs.
cvImageLeft.convertTo(cvImageLeft, CV_16UC1);
cvImageRight.convertTo(cvImageRight, CV_16UC1);
// Now process the device type
VPIDeviceType devType;
if(strDevType == "cpu")
{
}
else if(strDevType == "cuda")
{
}
else if(strDevType == "pva")
{
}
else
{
throw std::runtime_error("Backend '" + strDevType + "' not recognized, it must be either cpu, cuda or pva.");
}
// Create the stream for the given backend.
CHECK_STATUS(vpiStreamCreate(devType, &stream));
// We now wrap the loaded images into a VPIImage object to be used by VPI.
{
// First fill VPIImageData with the, well, image data...
VPIImageData imgData;
memset(&imgData, 0, sizeof(imgData));
imgData.numPlanes = 1;
imgData.planes[0].width = cvImageLeft.cols;
imgData.planes[0].height = cvImageLeft.rows;
imgData.planes[0].rowStride = cvImageLeft.step[0];
imgData.planes[0].data = cvImageLeft.data;
// Wrap it into a VPIImage. VPI won't make a copy of it, so the original
// image must be in scope at all times.
CHECK_STATUS(vpiImageWrapHostMem(&imgData, 0, &left));
imgData.planes[0].width = cvImageRight.cols;
imgData.planes[0].height = cvImageRight.rows;
imgData.planes[0].rowStride = cvImageRight.step[0];
imgData.planes[0].data = cvImageRight.data;
CHECK_STATUS(vpiImageWrapHostMem(&imgData, 0, &right));
}
// Create the image where the disparity map will be stored.
CHECK_STATUS(vpiImageCreate(cvImageLeft.cols, cvImageLeft.rows, VPI_IMAGE_TYPE_Y16, 0, &disparity));
// Create the payload for Harris Corners Detector algorithm
params.windowSize = 5;
params.maxDisparity = 64;
CHECK_STATUS(vpiCreateStereoDisparityEstimator(stream, cvImageLeft.cols, cvImageLeft.rows, VPI_IMAGE_TYPE_Y16,
params.maxDisparity, &stereo));
// Submit it with the input and output images
CHECK_STATUS(vpiSubmitStereoDisparityEstimator(stereo, left, right, disparity, &params));
// Wait until the algorithm finishes processing
CHECK_STATUS(vpiStreamSync(stream));
// Now let's retrieve the output
{
// Lock output to retrieve its data on cpu memory
CHECK_STATUS(vpiImageLock(disparity, VPI_LOCK_READ, &data));
// Make an OpenCV matrix out of this image
cv::Mat cvOut(data.planes[0].height, data.planes[0].width, CV_16UC1, data.planes[0].data,
data.planes[0].rowStride);
// Scale result and write it to disk
double min, max;
minMaxLoc(cvOut, &min, &max);
cvOut.convertTo(cvOut, CV_8UC1, 255.0 / (max - min), -min);
imwrite("disparity_"+strDevType+".png", cvOut);
// Done handling output, don't forget to unlock it.
CHECK_STATUS(vpiImageUnlock(disparity));
}
}
catch (std::exception &e)
{
std::cerr << e.what() << std::endl;
retval = 1;
}
// Clean up
vpiImageDestroy(disparity);
return retval;
}

Results

Left input image Right input image
Stereo disparity
VPIImagePlane::height
uint32_t height
Height of this plane in pixels.
Definition: Image.h:126
VPIDeviceType
VPIDeviceType
Device types.
Definition: Types.h:431
VPIImagePlane::width
uint32_t width
Width of this plane in pixels.
Definition: Image.h:125
vpiCreateStereoDisparityEstimator
VPIStatus vpiCreateStereoDisparityEstimator(VPIStream stream, uint32_t imageWidth, uint32_t imageHeight, const VPIImageType inputType, const uint32_t maxDisparity, VPIPayload *payload)
Creates payload for vpiSubmitStereoDisparityEstimator.
VPIImagePlane::rowStride
uint32_t rowStride
Difference in bytes of beginning of one row and the beginning of the previous.
Definition: Image.h:127
vpiImageUnlock
VPIStatus vpiImageUnlock(VPIImage img)
Releases the lock on an image object.
vpiStreamCreate
VPIStatus vpiStreamCreate(VPIDeviceType devType, VPIStream *stream)
Create a stream instance.
vpiStreamSync
VPIStatus vpiStreamSync(VPIStream stream)
Blocks the calling thread until all submitted commands in this stream queue are done (queue is empty)...
VPIImageData
Stores information about image characteristics and content.
Definition: Image.h:143
vpiSubmitStereoDisparityEstimator
VPIStatus vpiSubmitStereoDisparityEstimator(VPIPayload payload, VPIImage left, VPIImage right, VPIImage disparity, const VPIStereoDisparityEstimatorParams *params)
Runs stereo processing on a pair of images, outputs a disparity map.
StereoDisparityEstimator.h
vpiStreamDestroy
void vpiStreamDestroy(VPIStream stream)
Destroy a stream instance and deallocate all HW resources.
VPI_LOCK_READ
Lock memory only for reading.
Definition: Types.h:386
VPIImageData::planes
VPIImagePlane planes[VPI_MAX_PLANE_COUNT]
Data of all image planes.
Definition: Image.h:151
vpiImageDestroy
void vpiImageDestroy(VPIImage img)
Destroy an image instance as well as all resources it owns.
Image.h
VPI_IMAGE_TYPE_Y16
unsigned 16-bit grayscale/luma.
Definition: Types.h:176
VPIStereoDisparityEstimatorParams::windowSize
uint32_t windowSize
width of Census Transform window for disparity features.
Definition: StereoDisparityEstimator.h:82
VPIImage
struct VPIImageImpl * VPIImage
Definition: Types.h:153
VPIImageData::numPlanes
int32_t numPlanes
Number of planes.
Definition: Image.h:146
vpiImageLock
VPIStatus vpiImageLock(VPIImage img, VPILockMode mode, VPIImageData *hostData)
Acquires the lock on an image object and returns a pointer to the image planes Depending on the inter...
VPIImageData::type
VPIImageType type
Image type.
Definition: Image.h:145
vpiImageCreate
VPIStatus vpiImageCreate(uint32_t width, uint32_t height, VPIImageType type, uint32_t flags, VPIImage *img)
Create an empty image instance with the specified flags.
vpiImageWrapHostMem
VPIStatus vpiImageWrapHostMem(const VPIImageData *hostData, uint32_t flags, VPIImage *img)
Create an image object by wrapping around an existing host-memory block.
VPI_DEVICE_TYPE_PVA
PVA backend.
Definition: Types.h:435
VPIStereoDisparityEstimatorParams::maxDisparity
uint32_t maxDisparity
Maximum disparity for matching search.
Definition: StereoDisparityEstimator.h:83
VPIStereoDisparityEstimatorParams
Structure that defines the parameters for vpiCreateStereoDisparityEstimator.
Definition: StereoDisparityEstimator.h:80
VPIPayload
struct VPIPayloadImpl * VPIPayload
A handle to an algorithm payload.
Definition: Types.h:164
vpiPayloadDestroy
void vpiPayloadDestroy(VPIPayload payload)
Deallocates the payload object and all associated resources.
Stream.h
VPIImagePlane::data
void * data
Pointer to the first row of this plane.
Definition: Image.h:135
VPIStream
struct VPIStreamImpl * VPIStream
Definition: Types.h:147
VPI_DEVICE_TYPE_CUDA
CUDA backend.
Definition: Types.h:434
VPI_DEVICE_TYPE_CPU
CPU backend.
Definition: Types.h:433