VPI - Vision Programming Interface

3.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 as an image file to disk. If available, it'll also output the corresponding confidence map.

Instructions

The command line parameters are:

<backend> <left image> <right image>

where

  • backend: either cuda, ofa or ofa-pva-vic; it defines the backend that will perform the processing. ofa-pva-vic and cuda allow output of the confidence map in addition to the disparity.
  • left image: left input image of a rectified stereo pair, it accepts png, jpeg and possibly others.
  • right image: right input image of a stereo pair.

Here's one example:

  • C++
    ./vpi_sample_02_stereo_disparity cuda ../assets/chair_stereo_left.png ../assets/chair_stereo_right.png
  • Python
    python3 main.py 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.

The Python version of this sample also allow for setting various additional parameters, as well as additional input image extensions and to turn on verbose mode. The following command-line arguments can be passed to the Python sample:

  • Python
    python3 main.py <backend> <left image> <right image> --width W --height H --downscale D --window_size WIN
    --skip_confidence --conf_threshold T --conf_type absolute/relative -p1 P1 -p2 P2 --p2_alpha P2alpha
    --uniqueness U --skip_diagonal --num_passes N --min_disparity MIN --max_disparity MAX --output_mode 0/1/2
    -v/--verbose
    where the additional optional arguments are:
  • width: set the width W when passing ".raw" input images
  • height: set the height H when passing ".raw" input images
  • downscale: to set the output downscale factor as D
  • window_size: to set the median filter window size as WIN
  • skip_confidence: to avoid calculating confidence and applying it as a mask
  • conf_threshold: set the confidence threshold as T
  • conf_type: set the confidence type as either absolute or relative
  • p1: set p1 penalty as P1
  • p2: set p2 penalty as P2
  • p2_alpha: set p2Alpha adaptive penalty as P2alpha
  • uniqueness: set uniqueness as U
  • skip_diagonal: to avoid using diagonal paths in CUDA or OFA backends
  • num_passes: to set the number of passes N in OFA backends
  • min_disparity: to set the minimum disparity MIN in CUDA backend
  • max_disparity: to set the maximum disparity MAX in backends
  • output_mode: 0 for colored output, 1 for grayscale and 2 for raw binary
  • verbose: to turn on verbose mode To understand in detail each of these aditional arguments related to the stereo disparity algorithm, please read the corresponding documentation.

Results

Left input image Right input image
Stereo disparity Confidence map

Source Code

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

Language:
27 import sys
28 import vpi
29 import numpy as np
30 from PIL import Image
31 from argparse import ArgumentParser
32 import cv2
33 
34 
35 def read_raw_file(fpath, resize_to=None, verbose=False):
36  try:
37  if verbose:
38  print(f'I Reading: {fpath}', end=' ', flush=True)
39  f = open(fpath, 'rb')
40  np_arr = np.fromfile(f, dtype=np.uint16, count=-1)
41  f.close()
42  if verbose:
43  print(f'done!\nI Raw array: shape: {np_arr.shape} dtype: {np_arr.dtype}')
44  if resize_to is not None:
45  np_arr = np_arr.reshape(resize_to, order='C')
46  if verbose:
47  print(f'I Reshaped array: shape: {np_arr.shape} dtype: {np_arr.dtype}')
48  pil_img = Image.fromarray(np_arr, mode="I;16L")
49  return pil_img
50  except:
51  raise ValueError(f'E Cannot process raw input: {fpath}')
52 
53 
54 def process_arguments():
55  parser = ArgumentParser()
56 
57  parser.add_argument('backend', choices=['cuda','ofa','ofa-pva-vic'],
58  help='Backend to be used for processing')
59  parser.add_argument('left', help='Rectified left input image from a stereo pair')
60  parser.add_argument('right', help='Rectified right input image from a stereo pair')
61  parser.add_argument('--width', default=-1, type=int, help='Input width for raw input files')
62  parser.add_argument('--height', default=-1, type=int, help='Input height for raw input files')
63  parser.add_argument('--downscale', default=1, type=int, help='Output downscale factor')
64  parser.add_argument('--window_size', default=5, type=int, help='Median filter window size')
65  parser.add_argument('--skip_confidence', default=False, action='store_true', help='Do not calculate confidence')
66  parser.add_argument('--conf_threshold', default=32767, type=int, help='Confidence threshold')
67  parser.add_argument('--conf_type', default='absolute', choices=['absolute', 'relative'],
68  help='Computation type to produce the confidence output')
69  parser.add_argument('-p1', default=3, type=int, help='Penalty P1 on small disparities')
70  parser.add_argument('-p2', default=48, type=int, help='Penalty P2 on large disparities')
71  parser.add_argument('--p2_alpha', default=0, type=int, help='Alpha for adaptive P2 Penalty')
72  parser.add_argument('--uniqueness', default=-1, type=float, help='Uniqueness ratio')
73  parser.add_argument('--skip_diagonal', default=False, action='store_true', help='Do not use diagonal paths')
74  parser.add_argument('--num_passes', default=3, type=int, help='Number of passes')
75  parser.add_argument('--min_disparity', default=0, type=int, help='Minimum disparity')
76  parser.add_argument('--max_disparity', default=256, type=int, help='Maximum disparity')
77  parser.add_argument('--output_mode', default=0, type=int, help='0: color; 1: grayscale; 2: raw binary')
78  parser.add_argument('-v', '--verbose', default=False, action='store_true', help='Verbose mode')
79 
80  return parser.parse_args()
81 
82 
83 def main():
84  args = process_arguments()
85 
86  scale = 1 # pixel value scaling factor when loading input
87 
88  if args.backend == 'cuda':
89  backend = vpi.Backend.CUDA
90  elif args.backend == 'ofa':
91  backend = vpi.Backend.OFA
92  elif args.backend == 'ofa-pva-vic':
93  backend = vpi.Backend.OFA|vpi.Backend.PVA|vpi.Backend.VIC
94  else:
95  raise ValueError(f'E Invalid backend: {args.backend}')
96 
97  conftype = None
98  if args.conf_type == 'absolute':
99  conftype = vpi.ConfidenceType.ABSOLUTE
100  elif args.conf_type == 'relative':
101  conftype = vpi.ConfidenceType.RELATIVE
102  else:
103  raise ValueError(f'E Invalid confidence type: {args.conf_type}')
104 
105  minDisparity = args.min_disparity
106  maxDisparity = args.max_disparity
107  includeDiagonals = not args.skip_diagonal
108  numPasses = args.num_passes
109  calcConf = not args.skip_confidence
110  downscale = args.downscale
111  windowSize = args.window_size
112  quality = 6
113 
114  if args.verbose:
115  print(f'I Backend: {backend}\nI Left image: {args.left}\nI Right image: {args.right}\n'
116  f'I Disparities (min, max): {(minDisparity, maxDisparity)}\n'
117  f'I Input scale factor: {scale}\nI Output downscale factor: {downscale}\n'
118  f'I Window size: {windowSize}\nI Quality: {quality}\n'
119  f'I Calculate confidence: {calcConf}\nI Confidence threshold: {args.conf_threshold}\n'
120  f'I Confidence type: {conftype}\nI Uniqueness ratio: {args.uniqueness}\n'
121  f'I Penalty P1: {args.p1}\nI Penalty P2: {args.p2}\nI Adaptive P2 alpha: {args.p2_alpha}\n'
122  f'I Include diagonals: {includeDiagonals}\nI Number of passes: {numPasses}\n'
123  f'I Output mode: {args.output_mode}\nI Verbose: {args.verbose}\n'
124  , end='', flush=True)
125 
126  if 'raw' in args.left:
127  pil_left = read_raw_file(args.left, resize_to=[args.height, args.width], verbose=args.verbose)
128  np_left = np.asarray(pil_left)
129  else:
130  try:
131  pil_left = Image.open(args.left)
132  if pil_left.mode == 'I':
133  np_left = np.asarray(pil_left).astype(np.int16)
134  else:
135  np_left = np.asarray(pil_left)
136  except:
137  raise ValueError(f'E Cannot open left input image: {args.left}')
138 
139  if 'raw' in args.right:
140  pil_right = read_raw_file(args.right, resize_to=[args.height, args.width], verbose=args.verbose)
141  np_right = np.asarray(pil_right)
142  else:
143  try:
144  pil_right = Image.open(args.right)
145  if pil_right.mode == 'I':
146  np_right = np.asarray(pil_right).astype(np.int16)
147  else:
148  np_right = np.asarray(pil_right)
149  except:
150  raise ValueError(f'E Cannot open right input image: {args.right}')
151 
152  # Streams for left and right independent pre-processing
153  streamLeft = vpi.Stream()
154  streamRight = vpi.Stream()
155 
156  # Load input into a vpi.Image and convert it to grayscale, 16bpp
157  with vpi.Backend.CUDA:
158  with streamLeft:
159  left = vpi.asimage(np_left).convert(vpi.Format.Y16_ER, scale=scale)
160  with streamRight:
161  right = vpi.asimage(np_right).convert(vpi.Format.Y16_ER, scale=scale)
162 
163  # Preprocess input
164  # Block linear format is needed for ofa backends
165  # Currently we can only convert to block-linear using VIC backend.
166  if args.backend in {'ofa-pva-vic', 'ofa'}:
167  if args.verbose:
168  print(f'W {args.backend} forces to convert input images to block linear', flush=True)
169  with vpi.Backend.VIC:
170  with streamLeft:
171  left = left.convert(vpi.Format.Y16_ER_BL)
172  with streamRight:
173  right = right.convert(vpi.Format.Y16_ER_BL)
174 
175  if args.verbose:
176  print(f'I Input left image: {left.size} {left.format}\n'
177  f'I Input right image: {right.size} {right.format}', flush=True)
178 
179  confidenceU16 = None
180 
181  if calcConf:
182  if args.backend not in {'cuda', 'ofa-pva-vic'}:
183  # Only CUDA and OFA-PVA-VIC have confidence map
184  calcConf = False
185  if args.verbose:
186  print(f'W {args.backend} does not allow to calculate confidence', flush=True)
187 
188 
189  outWidth = (left.size[0] + downscale - 1) // downscale
190  outHeight = (left.size[1] + downscale - 1) // downscale
191 
192  if calcConf:
193  confidenceU16 = vpi.Image((outWidth, outHeight), vpi.Format.U16)
194 
195  # Use stream left to consolidate actual stereo processing
196  streamStereo = streamLeft
197 
198  if args.backend == 'ofa-pva-vic' and maxDisparity not in {128, 256}:
199  maxDisparity = 256
200  if args.verbose:
201  print(f'W {args.backend} forces maxDisparity to {maxDisparity}', flush=True)
202 
203  if args.verbose:
204  if 'ofa' not in args.backend:
205  print('W Ignoring P2 alpha and number of passes since not an OFA backend', flush=True)
206  if args.backend != 'cuda':
207  print('W Ignoring uniqueness since not a CUDA backend', flush=True)
208  print('I Estimating stereo disparity ... ', end='', flush=True)
209 
210  # Estimate stereo disparity.
211  with streamStereo, backend:
212  disparityS16 = vpi.stereodisp(left, right, downscale=downscale, out_confmap=confidenceU16,
213  window=windowSize, maxdisp=maxDisparity, confthreshold=args.conf_threshold,
214  quality=quality, conftype=conftype, mindisp=minDisparity,
215  p1=args.p1, p2=args.p2, p2alpha=args.p2_alpha, uniqueness=args.uniqueness,
216  includediagonals=includeDiagonals, numpasses=numPasses)
217 
218  if args.verbose:
219  print('done!\nI Post-processing ... ', end='', flush=True)
220 
221  # Postprocess results and save them to disk
222  with streamStereo, vpi.Backend.CUDA:
223  # Some backends outputs disparities in block-linear format, we must convert them to
224  # pitch-linear for consistency with other backends.
225  if disparityS16.format == vpi.Format.S16_BL:
226  disparityS16 = disparityS16.convert(vpi.Format.S16, backend=vpi.Backend.VIC)
227 
228  # Scale disparity and confidence map so that values like between 0 and 255.
229 
230  # Disparities are in Q10.5 format, so to map it to float, it gets
231  # divided by 32. Then the resulting disparity range, from 0 to
232  # stereo.maxDisparity gets mapped to 0-255 for proper output.
233  # Copy disparity values back to the CPU.
234  disparityU8 = disparityS16.convert(vpi.Format.U8, scale=255.0/(32*maxDisparity)).cpu()
235 
236  # Apply JET colormap to turn the disparities into color, reddish hues
237  # represent objects closer to the camera, blueish are farther away.
238  disparityColor = cv2.applyColorMap(disparityU8, cv2.COLORMAP_JET)
239 
240  # Converts to RGB for output with PIL.
241  disparityColor = cv2.cvtColor(disparityColor, cv2.COLOR_BGR2RGB)
242 
243  if calcConf:
244  confidenceU8 = confidenceU16.convert(vpi.Format.U8, scale=255.0/65535).cpu()
245 
246  # When pixel confidence is 0, its color in the disparity is black.
247  mask = cv2.threshold(confidenceU8, 1, 255, cv2.THRESH_BINARY)[1]
248  mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
249  disparityColor = cv2.bitwise_and(disparityColor, mask)
250 
251  fext = '.raw' if args.output_mode == 2 else '.png'
252 
253  disparity_fname = f'disparity_python{sys.version_info[0]}_{args.backend}' + fext
254  confidence_fname = f'confidence_python{sys.version_info[0]}_{args.backend}' + fext
255 
256  if args.verbose:
257  print(f'done!\nI Disparity output: {disparity_fname}', flush=True)
258  if calcConf:
259  print(f'I Confidence output: {confidence_fname}', flush=True)
260 
261  # Save results to disk.
262  try:
263  if args.output_mode == 0:
264  Image.fromarray(disparityColor).save(disparity_fname)
265  if args.verbose:
266  print(f'I Output disparity image: {disparityColor.shape} '
267  f'{disparityColor.dtype}', flush=True)
268  elif args.output_mode == 1:
269  Image.fromarray(disparityU8).save(disparity_fname)
270  if args.verbose:
271  print(f'I Output disparity image: {disparityU8.shape} '
272  f'{disparityU8.dtype}', flush=True)
273  elif args.output_mode == 2:
274  disparityS16.cpu().tofile(disparity_fname)
275  if args.verbose:
276  print(f'I Output disparity image: {disparityS16.size} '
277  f'{disparityS16.format}', flush=True)
278 
279  if calcConf:
280  if args.output_mode == 0 or args.output_mode == 1:
281  Image.fromarray(confidenceU8).save(confidence_fname)
282  if args.verbose:
283  print(f'I Output confidence image: {confidenceU8.shape} '
284  f'{confidenceU8.dtype}', flush=True)
285  else:
286  confidenceU16.cpu().tofile(confidence_fname)
287  if args.verbose:
288  print(f'I Output confidence image: {confidenceU16.size} '
289  f'{confidenceU16.format}', flush=True)
290 
291  except:
292  raise ValueError(f'E Cannot write outputs: {disparity_fname}, {confidence_fname}\n'
293  f'E Using output mode: {args.output_mode}')
294 
295 
296 if __name__ == '__main__':
297  main()
29 #include <opencv2/core/version.hpp>
30 #if CV_MAJOR_VERSION >= 3
31 # include <opencv2/imgcodecs.hpp>
32 #else
33 # include <opencv2/contrib/contrib.hpp> // for colormap
34 # include <opencv2/highgui/highgui.hpp>
35 #endif
36 
37 #include <opencv2/imgproc/imgproc.hpp>
38 #include <vpi/OpenCVInterop.hpp>
39 
40 #include <vpi/Image.h>
41 #include <vpi/Status.h>
42 #include <vpi/Stream.h>
44 #include <vpi/algo/Rescale.h>
46 
47 #include <cstring>
48 #include <iostream>
49 #include <sstream>
50 
51 #define CHECK_STATUS(STMT) \
52  do \
53  { \
54  VPIStatus status = (STMT); \
55  if (status != VPI_SUCCESS) \
56  { \
57  char buffer[VPI_MAX_STATUS_MESSAGE_LENGTH]; \
58  vpiGetLastStatusMessage(buffer, sizeof(buffer)); \
59  std::ostringstream ss; \
60  ss << vpiStatusGetName(status) << ": " << buffer; \
61  throw std::runtime_error(ss.str()); \
62  } \
63  } while (0);
64 
65 int main(int argc, char *argv[])
66 {
67  // OpenCV image that will be wrapped by a VPIImage.
68  // Define it here so that it's destroyed *after* wrapper is destroyed
69  cv::Mat cvImageLeft, cvImageRight;
70 
71  // VPI objects that will be used
72  VPIImage inLeft = NULL;
73  VPIImage inRight = NULL;
74  VPIImage tmpLeft = NULL;
75  VPIImage tmpRight = NULL;
76  VPIImage stereoLeft = NULL;
77  VPIImage stereoRight = NULL;
78  VPIImage disparity = NULL;
79  VPIImage confidenceMap = NULL;
80  VPIStream stream = NULL;
81  VPIPayload stereo = NULL;
82 
83  int retval = 0;
84 
85  try
86  {
87  // =============================
88  // Parse command line parameters
89 
90  if (argc != 4)
91  {
92  throw std::runtime_error(std::string("Usage: ") + argv[0] +
93  " <cuda|ofa|ofa-pva-vic> <left image> <right image>");
94  }
95 
96  std::string strBackend = argv[1];
97  std::string strLeftFileName = argv[2];
98  std::string strRightFileName = argv[3];
99 
100  uint64_t backends;
101 
102  if (strBackend == "cuda")
103  {
104  backends = VPI_BACKEND_CUDA;
105  }
106  else if (strBackend == "ofa")
107  {
108  backends = VPI_BACKEND_OFA;
109  }
110  else if (strBackend == "ofa-pva-vic")
111  {
113  }
114  else
115  {
116  throw std::runtime_error("Backend '" + strBackend +
117  "' not recognized, it must be either cuda, ofa or ofa-pva-vic.");
118  }
119 
120  // =====================
121  // Load the input images
122  cvImageLeft = cv::imread(strLeftFileName);
123  if (cvImageLeft.empty())
124  {
125  throw std::runtime_error("Can't open '" + strLeftFileName + "'");
126  }
127 
128  cvImageRight = cv::imread(strRightFileName);
129  if (cvImageRight.empty())
130  {
131  throw std::runtime_error("Can't open '" + strRightFileName + "'");
132  }
133 
134  // =================================
135  // Allocate all VPI resources needed
136 
137  int32_t inputWidth = cvImageLeft.cols;
138  int32_t inputHeight = cvImageLeft.rows;
139 
140  // Create the stream that will be used for processing.
141  CHECK_STATUS(vpiStreamCreate(0, &stream));
142 
143  // We now wrap the loaded images into a VPIImage object to be used by VPI.
144  // VPI won't make a copy of it, so the original image must be in scope at all times.
145  CHECK_STATUS(vpiImageCreateWrapperOpenCVMat(cvImageLeft, 0, &inLeft));
146  CHECK_STATUS(vpiImageCreateWrapperOpenCVMat(cvImageRight, 0, &inRight));
147 
148  // Format conversion parameters needed for input pre-processing
149  VPIConvertImageFormatParams convParams;
150  CHECK_STATUS(vpiInitConvertImageFormatParams(&convParams));
151 
152  // Set algorithm parameters to be used. Only values what differs from defaults will be overwritten.
154  CHECK_STATUS(vpiInitStereoDisparityEstimatorCreationParams(&stereoParams));
155 
156  // Default format and size for inputs and outputs
158  VPIImageFormat disparityFormat = VPI_IMAGE_FORMAT_S16;
159 
160  int stereoWidth = inputWidth;
161  int stereoHeight = inputHeight;
162  int outputWidth = inputWidth;
163  int outputHeight = inputHeight;
164 
165  // Override some backend-dependent parameters
166  if (strBackend.find("ofa") != std::string::npos)
167  {
168  // Implementations using OFA require BL input
169  stereoFormat = VPI_IMAGE_FORMAT_Y16_ER_BL;
170 
171  if (strBackend == "ofa")
172  {
173  disparityFormat = VPI_IMAGE_FORMAT_S16_BL;
174  }
175 
176  // Output width including downscaleFactor must be at least max(64, maxDisparity/downscaleFactor) when OFA+PVA+VIC are used
177  if (strBackend.find("pva") != std::string::npos)
178  {
179  int downscaledWidth = (inputWidth + stereoParams.downscaleFactor - 1) / stereoParams.downscaleFactor;
180  int minWidth = std::max(stereoParams.maxDisparity / stereoParams.downscaleFactor, downscaledWidth);
181  outputWidth = std::max(64, minWidth);
182  outputHeight = (inputHeight * stereoWidth) / inputWidth;
183  stereoWidth = outputWidth * stereoParams.downscaleFactor;
184  stereoHeight = outputHeight * stereoParams.downscaleFactor;
185  }
186 
187  // Maximum disparity can be either 128 or 256
188  stereoParams.maxDisparity = 128;
189  }
190 
191  // Create the payload for Stereo Disparity algorithm.
192  // Payload is created before the image objects so that non-supported backends can be trapped with an error.
193  CHECK_STATUS(vpiCreateStereoDisparityEstimator(backends, stereoWidth, stereoHeight, stereoFormat, &stereoParams,
194  &stereo));
195 
196  // Create the image where the disparity map will be stored.
197  CHECK_STATUS(vpiImageCreate(outputWidth, outputHeight, disparityFormat, 0, &disparity));
198 
199  // Create the input stereo images
200  CHECK_STATUS(vpiImageCreate(stereoWidth, stereoHeight, stereoFormat, 0, &stereoLeft));
201  CHECK_STATUS(vpiImageCreate(stereoWidth, stereoHeight, stereoFormat, 0, &stereoRight));
202 
203  // Create some temporary images, and the confidence image if the backend can support it
204  if (strBackend.find("ofa") != std::string::npos)
205  {
206  // OFA also needs a temporary buffer for format conversion
207  CHECK_STATUS(vpiImageCreate(inputWidth, inputHeight, VPI_IMAGE_FORMAT_Y16_ER, 0, &tmpLeft));
208  CHECK_STATUS(vpiImageCreate(inputWidth, inputHeight, VPI_IMAGE_FORMAT_Y16_ER, 0, &tmpRight));
209 
210  if (strBackend.find("pva") != std::string::npos)
211  {
212  // confidence map is supported by OFA+PVA
213  CHECK_STATUS(vpiImageCreate(outputWidth, outputHeight, VPI_IMAGE_FORMAT_U16, 0, &confidenceMap));
214  }
215  }
216  else if (strBackend == "cuda")
217  {
218  CHECK_STATUS(vpiImageCreate(inputWidth, inputHeight, VPI_IMAGE_FORMAT_U16, 0, &confidenceMap));
219  }
220 
221  // ================
222  // Processing stage
223 
224  // -----------------
225  // Pre-process input
226  if (strBackend == "ofa" || strBackend == "ofa-pva-vic")
227  {
228  // Convert opencv input to temporary grayscale format using CUDA
229  CHECK_STATUS(vpiSubmitConvertImageFormat(stream, VPI_BACKEND_CUDA, inLeft, tmpLeft, &convParams));
230  CHECK_STATUS(vpiSubmitConvertImageFormat(stream, VPI_BACKEND_CUDA, inRight, tmpRight, &convParams));
231 
232  // Do both scale and final image format conversion on VIC.
233  CHECK_STATUS(
234  vpiSubmitRescale(stream, VPI_BACKEND_VIC, tmpLeft, stereoLeft, VPI_INTERP_LINEAR, VPI_BORDER_CLAMP, 0));
235  CHECK_STATUS(vpiSubmitRescale(stream, VPI_BACKEND_VIC, tmpRight, stereoRight, VPI_INTERP_LINEAR,
236  VPI_BORDER_CLAMP, 0));
237  }
238  else
239  {
240  // Convert opencv input to grayscale format using CUDA
241  CHECK_STATUS(vpiSubmitConvertImageFormat(stream, VPI_BACKEND_CUDA, inLeft, stereoLeft, &convParams));
242  CHECK_STATUS(vpiSubmitConvertImageFormat(stream, VPI_BACKEND_CUDA, inRight, stereoRight, &convParams));
243  }
244 
245  // ------------------------------
246  // Do stereo disparity estimation
247 
248  // Submit it with the input and output images
249  CHECK_STATUS(vpiSubmitStereoDisparityEstimator(stream, backends, stereo, stereoLeft, stereoRight, disparity,
250  confidenceMap, NULL));
251 
252  // Wait until the algorithm finishes processing
253  CHECK_STATUS(vpiStreamSync(stream));
254 
255  // ========================================
256  // Output pre-processing and saving to disk
257  // Lock output to retrieve its data on cpu memory
258  VPIImageData data;
259  CHECK_STATUS(vpiImageLockData(disparity, VPI_LOCK_READ, VPI_IMAGE_BUFFER_HOST_PITCH_LINEAR, &data));
260 
261  // Make an OpenCV matrix out of this image
262  cv::Mat cvDisparity;
263  CHECK_STATUS(vpiImageDataExportOpenCVMat(data, &cvDisparity));
264 
265  // Scale result and write it to disk. Disparities are in Q10.5 format,
266  // so to map it to float, it gets divided by 32. Then the resulting disparity range,
267  // from 0 to stereo.maxDisparity gets mapped to 0-255 for proper output.
268  cvDisparity.convertTo(cvDisparity, CV_8UC1, 255.0 / (32 * stereoParams.maxDisparity), 0);
269 
270  // Apply JET colormap to turn the disparities into color, reddish hues
271  // represent objects closer to the camera, blueish are farther away.
272  cv::Mat cvDisparityColor;
273  applyColorMap(cvDisparity, cvDisparityColor, cv::COLORMAP_JET);
274 
275  // Done handling output, don't forget to unlock it.
276  CHECK_STATUS(vpiImageUnlock(disparity));
277 
278  // If we have a confidence map,
279  if (confidenceMap)
280  {
281  // Write it to disk too.
282  //
283  VPIImageData data;
284  CHECK_STATUS(vpiImageLockData(confidenceMap, VPI_LOCK_READ, VPI_IMAGE_BUFFER_HOST_PITCH_LINEAR, &data));
285 
286  cv::Mat cvConfidence;
287  CHECK_STATUS(vpiImageDataExportOpenCVMat(data, &cvConfidence));
288 
289  // Confidence map varies from 0 to 65535, we scale it to
290  // [0-255].
291  cvConfidence.convertTo(cvConfidence, CV_8UC1, 255.0 / 65535, 0);
292  imwrite("confidence_" + strBackend + ".png", cvConfidence);
293 
294  CHECK_STATUS(vpiImageUnlock(confidenceMap));
295 
296  // When pixel confidence is 0, its color in the disparity
297  // output is black.
298  cv::Mat cvMask;
299  threshold(cvConfidence, cvMask, 1, 255, cv::THRESH_BINARY);
300  cvtColor(cvMask, cvMask, cv::COLOR_GRAY2BGR);
301  bitwise_and(cvDisparityColor, cvMask, cvDisparityColor);
302  }
303 
304  imwrite("disparity_" + strBackend + ".png", cvDisparityColor);
305  }
306  catch (std::exception &e)
307  {
308  std::cerr << e.what() << std::endl;
309  retval = 1;
310  }
311 
312  // ========
313  // Clean up
314 
315  // Destroying stream first makes sure that all work submitted to
316  // it is finished.
317  vpiStreamDestroy(stream);
318 
319  // Only then we can destroy the other objects, as we're sure they
320  // aren't being used anymore.
321 
322  vpiImageDestroy(inLeft);
323  vpiImageDestroy(inRight);
324  vpiImageDestroy(tmpLeft);
325  vpiImageDestroy(tmpRight);
326  vpiImageDestroy(stereoLeft);
327  vpiImageDestroy(stereoRight);
328  vpiImageDestroy(confidenceMap);
329  vpiImageDestroy(disparity);
330  vpiPayloadDestroy(stereo);
331 
332  return retval;
333 }
Declares functions that handle image format conversion.
#define VPI_IMAGE_FORMAT_S16_BL
Single plane with one block-linear 16-bit signed integer channel.
Definition: ImageFormat.h:121
#define VPI_IMAGE_FORMAT_U16
Single plane with one 16-bit unsigned integer channel.
Definition: ImageFormat.h:109
#define VPI_IMAGE_FORMAT_S16
Single plane with one 16-bit signed integer channel.
Definition: ImageFormat.h:118
#define VPI_IMAGE_FORMAT_Y16_ER_BL
Single plane with one block-linear 16-bit unsigned integer channel with full-range luma (grayscale) i...
Definition: ImageFormat.h:176
#define VPI_IMAGE_FORMAT_Y16_ER
Single plane with one pitch-linear 16-bit unsigned integer channel with full-range luma (grayscale) i...
Definition: ImageFormat.h:171
Functions and structures for dealing with VPI images.
Functions for handling OpenCV interoperability with VPI.
Declares functions that implement the Rescale algorithm.
Declaration of VPI status codes handling functions.
Declares functions that implement stereo disparity estimation algorithms.
Declares functions dealing with VPI streams.
VPIStatus vpiInitConvertImageFormatParams(VPIConvertImageFormatParams *params)
Initialize VPIConvertImageFormatParams with default values.
VPIStatus vpiSubmitConvertImageFormat(VPIStream stream, uint64_t backend, VPIImage input, VPIImage output, const VPIConvertImageFormatParams *params)
Converts the image contents to the desired format, with optional scaling and offset.
Parameters for customizing image format conversion.
uint64_t VPIImageFormat
Pre-defined image formats.
Definition: ImageFormat.h:94
void vpiImageDestroy(VPIImage img)
Destroy an image instance.
struct VPIImageImpl * VPIImage
A handle to an image.
Definition: Types.h:256
VPIStatus vpiImageLockData(VPIImage img, VPILockMode mode, VPIImageBufferType bufType, VPIImageData *data)
Acquires the lock on an image object and returns the image contents.
VPIStatus vpiImageCreate(int32_t width, int32_t height, VPIImageFormat fmt, uint64_t flags, VPIImage *img)
Create an empty image instance with the specified flags.
VPIStatus vpiImageUnlock(VPIImage img)
Releases the lock on an image object.
@ VPI_IMAGE_BUFFER_HOST_PITCH_LINEAR
Host-accessible with planes in pitch-linear memory layout.
Definition: Image.h:172
Stores information about image characteristics and content.
Definition: Image.h:234
VPIStatus vpiImageCreateWrapperOpenCVMat(const cv::Mat &mat, VPIImageFormat fmt, uint64_t flags, VPIImage *img)
Wraps a cv::Mat in an VPIImage with the given image format.
VPIStatus vpiImageDataExportOpenCVMat(const VPIImageData &imgData, cv::Mat *mat)
Fills an existing cv::Mat with data from VPIImageData coming from a locked VPIImage.
struct VPIPayloadImpl * VPIPayload
A handle to an algorithm payload.
Definition: Types.h:268
void vpiPayloadDestroy(VPIPayload payload)
Deallocates the payload object and all associated resources.
VPIStatus vpiSubmitRescale(VPIStream stream, uint64_t backend, VPIImage input, VPIImage output, VPIInterpolationType interpolationType, VPIBorderExtension border, uint64_t flags)
Changes the size and scale of a 2D image.
int32_t maxDisparity
Maximum disparity for matching search.
int32_t downscaleFactor
Output's downscale factor with respect to the input's resolution.
VPIStatus vpiInitStereoDisparityEstimatorCreationParams(VPIStereoDisparityEstimatorCreationParams *params)
Initializes VPIStereoDisparityEstimatorCreationParams with default values.
VPIStatus vpiCreateStereoDisparityEstimator(uint64_t backends, int32_t imageWidth, int32_t imageHeight, VPIImageFormat inputFormat, const VPIStereoDisparityEstimatorCreationParams *params, VPIPayload *payload)
Creates payload for vpiSubmitStereoDisparityEstimator.
VPIStatus vpiSubmitStereoDisparityEstimator(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage left, VPIImage right, VPIImage disparity, VPIImage confidenceMap, const VPIStereoDisparityEstimatorParams *params)
Runs stereo processing on a pair of images and outputs a disparity map.
Structure that defines the parameters for vpiCreateStereoDisparityEstimator.
struct VPIStreamImpl * VPIStream
A handle to a stream.
Definition: Types.h:250
VPIStatus vpiStreamSync(VPIStream stream)
Blocks the calling thread until all submitted commands in this stream queue are done (queue is empty)...
void vpiStreamDestroy(VPIStream stream)
Destroy a stream instance and deallocate all HW resources.
VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
Create a stream instance.
@ VPI_BACKEND_CUDA
CUDA backend.
Definition: Types.h:93
@ VPI_BACKEND_PVA
PVA backend.
Definition: Types.h:94
@ VPI_BACKEND_OFA
OFA backend.
Definition: Types.h:97
@ VPI_BACKEND_VIC
VIC backend.
Definition: Types.h:95
@ VPI_BORDER_CLAMP
Border pixels are repeated indefinitely.
Definition: Types.h:279
@ VPI_INTERP_LINEAR
Linear interpolation.
Definition: Interpolation.h:93
@ VPI_LOCK_READ
Lock memory only for reading.
Definition: Types.h:595