VPI - Vision Programming Interface

1.2 Release

Pyramidal LK Optical Flow

Overview

This application tracks feature points on an input video, draws the features on each frame and saves them to disk. The user can define what backend will be used for processing.

Note
The output will be in grayscale as the algorithm currently doesn't support color inputs.

Instructions

The command line parameters are:

<backend> <input video> <pyramid levels> <output frames>

where

  • backend: either cpu or cuda; it defines the backend that will perform the processing.
  • input video: input video file name, it accepts all video types that OpenCV's cv::VideoCapture accepts.
  • pyramid levels: specify the number of pyramid that used in the algorithm.
  • output frames: the file name that will be used for the output frames. Example: output.png will generate frames output_0000.png, output_0001.png, output_0002.png, and so on.

Here's one example:

  • C++
    ./vpi_sample_12_optflow_lk cuda ../assets/dashcam.mp4 5 frame.png
  • Python
    python main.py cuda ../assets/dashcam.mp4 5 frame.png

This is using the CUDA backend and one of the provided sample videos with pyramid level equals 5.

Results

Frame 0009

Source Code

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

Language:
27 import cv2
28 import sys
29 import vpi
30 import numpy as np
31 from os import path
32 from argparse import ArgumentParser
33 from contextlib import contextmanager
34 
35 # --------------------------------------
36 # Some definitions and utility functions
37 
38 # Maximum number of keypoints that will be tracked
39 MAX_KEYPOINTS = 100
40 
41 def update_mask(mask, trackColors, prevFeatures, curFeatures, status = None):
42  '''Draw keypoint path from previous frame to current one'''
43 
44  numTrackedKeypoints = 0
45 
46  def none_context(a=None): return contextmanager(lambda: (x for x in [a]))()
47 
48  with curFeatures.rlock(), \
49  (status.rlock() if status else none_context()), \
50  (prevFeatures.rlock() if prevFeatures else none_context()):
51 
52  for i in range(curFeatures.size):
53  # keypoint is being tracked?
54  if not status or status.cpu()[i] == 0:
55  color = tuple(trackColors[i,0].tolist())
56 
57  # draw the tracks
58  if prevFeatures:
59  cv2.line(mask, tuple(np.round(prevFeatures.cpu()[i])), tuple(curFeatures.cpu()[i]), color, 2)
60 
61  cv2.circle(mask, tuple(np.round(curFeatures.cpu()[i])), 5, color, -1)
62 
63  numTrackedKeypoints += 1
64 
65  return numTrackedKeypoints
66 
67 def save_file_to_disk(frame, mask, baseFileName, frameCounter):
68  '''Apply mask on frame and save it to disk'''
69 
70  frame = frame.convert(vpi.Format.BGR8, backend=vpi.Backend.CUDA)
71  with frame.rlock():
72  frame = cv2.add(frame.cpu(), mask)
73 
74  name, ext = path.splitext(baseFileName)
75  fname = "{}_{:04d}{}".format(name, frameCounter, ext)
76 
77  cv2.imwrite(fname, frame, [cv2.IMWRITE_JPEG_QUALITY, 70])
78 
79 # ----------------------------
80 # Parse command line arguments
81 
82 parser = ArgumentParser()
83 parser.add_argument('backend', choices=['cpu', 'cuda'],
84  help='Backend to be used for processing')
85 
86 parser.add_argument('input',
87  help='Input video to be processed')
88 
89 parser.add_argument('pyramid_levels', type=int,
90  help='Number of levels in the pyramid used with the algorithm')
91 
92 parser.add_argument('output',
93  help='Output file name')
94 
95 args = parser.parse_args();
96 
97 if args.backend == 'cuda':
98  backend = vpi.Backend.CUDA
99 else:
100  assert args.backend == 'cpu'
101  backend = vpi.Backend.CPU
102 
103 # adjust output file name to take into account backend used and python version
104 name, ext = path.splitext(args.output)
105 args.output = "{}_python{}_{}{}".format(name, sys.version_info[0], args.backend, ext)
106 
107 # ----------------
108 # Open input video
109 
110 inVideo = cv2.VideoCapture(args.input)
111 
112 # Read first input frame
113 ok, cvFrame = inVideo.read()
114 if not ok:
115  exit('Cannot read first input frame')
116 
117 # ---------------------------
118 # Perform some pre-processing
119 
120 # Retrieve features to be tracked from first frame using
121 # Harris Corners Detector
122 with vpi.Backend.CPU:
123  frame = vpi.asimage(cvFrame, vpi.Format.BGR8).convert(vpi.Format.U8)
124  curFeatures, scores = frame.harriscorners(strength=0.1, sensitivity=0.01)
125 
126 # Limit the number of features we'll track and calculate their colors on the
127 # output image
128 with curFeatures.lock(), scores.rlock():
129  # Sort features in descending scores order and keep the first MAX_KEYPOINTS
130  ind = np.argsort(scores.cpu(), kind='mergesort')[::-1]
131  curFeatures.cpu()[:] = np.take(curFeatures.cpu(), ind, axis=0)
132  curFeatures.size = min(curFeatures.size, MAX_KEYPOINTS)
133 
134  # Keypoints' have different hues, calculated from their position in the first frame
135  trackColors = np.array([[(int(p[0]) ^ int(p[1])) % 180,255,255] for p in curFeatures.cpu()], np.uint8).reshape(-1,1,3)
136  # Convert colors from HSV to RGB
137  trackColors = cv2.cvtColor(trackColors, cv2.COLOR_HSV2BGR).astype(int)
138 
139 with backend:
140  optflow = vpi.OpticalFlowPyrLK(frame, curFeatures, args.pyramid_levels)
141 
142 # Counter for the frames
143 idFrame = 0
144 
145 # Create mask with features' tracks over time
146 mask = np.zeros((frame.height, frame.width, 3), np.uint8)
147 numTrackedKeypoints = update_mask(mask, trackColors, None, curFeatures)
148 
149 while True:
150  # Apply mask to frame and save it to disk
151  save_file_to_disk(frame, mask, args.output, idFrame)
152 
153  print("Frame id={}: {} points tracked.".format(idFrame, numTrackedKeypoints))
154 
155  prevFeatures = curFeatures
156 
157  # Read one input frame
158  ret, cvFrame = inVideo.read()
159  if not ret:
160  print("Video ended.")
161  break
162  idFrame += 1
163 
164  # Convert frame to grayscale
165  with vpi.Backend.CUDA:
166  frame = vpi.asimage(cvFrame, vpi.Format.BGR8).convert(vpi.Format.U8);
167 
168  # Calculate where keypoints are in current frame
169  curFeatures, status = optflow(frame)
170 
171  # Update the mask with the current keypoints' position
172  numTrackedKeypoints = update_mask(mask, trackColors, prevFeatures, curFeatures, status)
173 
174  # No more keypoints to track?
175  if numTrackedKeypoints == 0:
176  print("No keypoints to track.")
177  break # nothing else to do
178 
179 # vim: ts=8:sw=4:sts=4:et:ai
29 #include <opencv2/core/version.hpp>
30 #if CV_MAJOR_VERSION >= 3
31 # include <opencv2/imgcodecs.hpp>
32 # include <opencv2/videoio.hpp>
33 #else
34 # include <opencv2/highgui/highgui.hpp>
35 #endif
36 
37 #include <opencv2/imgproc/imgproc.hpp>
38 #include <vpi/OpenCVInterop.hpp>
39 
40 #include <vpi/Array.h>
41 #include <vpi/Image.h>
42 #include <vpi/Pyramid.h>
43 #include <vpi/Status.h>
44 #include <vpi/Stream.h>
47 #include <vpi/algo/HarrisCorners.h>
49 
50 #include <algorithm>
51 #include <cstring> // for memset
52 #include <fstream>
53 #include <iostream>
54 #include <map>
55 #include <numeric>
56 #include <sstream>
57 #include <vector>
58 
59 // Max number of corners detected by harris corner algo
60 constexpr int MAX_HARRIS_CORNERS = 8192;
61 
62 // Max number of keypoints to be tracked
63 constexpr int MAX_KEYPOINTS = 100;
64 
65 #define CHECK_STATUS(STMT) \
66  do \
67  { \
68  VPIStatus status__ = (STMT); \
69  if (status__ != VPI_SUCCESS) \
70  { \
71  char buffer[VPI_MAX_STATUS_MESSAGE_LENGTH]; \
72  vpiGetLastStatusMessage(buffer, sizeof(buffer)); \
73  std::ostringstream ss; \
74  ss << vpiStatusGetName(status__) << ": " << buffer; \
75  throw std::runtime_error(ss.str()); \
76  } \
77  } while (0);
78 
79 static void SaveFileToDisk(VPIImage img, cv::Mat cvMask, std::string baseFileName, int32_t frameCounter)
80 {
81  VPIImageData imgData;
82  CHECK_STATUS(vpiImageLock(img, VPI_LOCK_READ, &imgData));
83 
84  cv::Mat cvImage;
85  try
86  {
87  cv::Mat tmp;
88  CHECK_STATUS(vpiImageDataExportOpenCVMat(imgData, &tmp));
89  cvtColor(tmp, cvImage, cv::COLOR_GRAY2BGR);
90 
91  CHECK_STATUS(vpiImageUnlock(img));
92  }
93  catch (...)
94  {
95  CHECK_STATUS(vpiImageUnlock(img));
96  throw;
97  }
98 
99  add(cvImage, cvMask, cvImage);
100 
101  // Create the output file name
102  std::string fname = baseFileName;
103  int ext = fname.rfind('.');
104 
105  char buffer[512] = {};
106  snprintf(buffer, sizeof(buffer) - 1, "%s_%04d%s", fname.substr(0, ext).c_str(), frameCounter,
107  fname.substr(ext).c_str());
108 
109  // Finally, write frame to disk
110  if (!imwrite(buffer, cvImage, {cv::IMWRITE_JPEG_QUALITY, 70}))
111  {
112  throw std::runtime_error("Can't write to " + std::string(buffer));
113  }
114 }
115 
116 // Sort keypoints by decreasing score, and retain only the first 'max'
117 static void SortKeypoints(VPIArray keypoints, VPIArray scores, int max)
118 {
119  VPIArrayData ptsData, scoresData;
120  CHECK_STATUS(vpiArrayLock(keypoints, VPI_LOCK_READ_WRITE, &ptsData));
121  CHECK_STATUS(vpiArrayLock(scores, VPI_LOCK_READ_WRITE, &scoresData));
122 
123  std::vector<int> indices(*ptsData.sizePointer);
124  std::iota(indices.begin(), indices.end(), 0);
125 
126  stable_sort(indices.begin(), indices.end(), [&scoresData](int a, int b) {
127  uint32_t *score = reinterpret_cast<uint32_t *>(scoresData.data);
128  return score[a] >= score[b]; // decreasing score order
129  });
130 
131  // keep the only 'max' indexes.
132  indices.resize(std::min<size_t>(indices.size(), max));
133 
134  VPIKeypoint *kptData = reinterpret_cast<VPIKeypoint *>(ptsData.data);
135 
136  // reorder the keypoints to keep the first 'max' with highest scores.
137  std::vector<VPIKeypoint> kpt;
138  std::transform(indices.begin(), indices.end(), std::back_inserter(kpt),
139  [kptData](int idx) { return kptData[idx]; });
140  std::copy(kpt.begin(), kpt.end(), kptData);
141 
142  // update keypoint array size.
143  *ptsData.sizePointer = kpt.size();
144 
145  vpiArrayUnlock(scores);
146  vpiArrayUnlock(keypoints);
147 }
148 
149 static int UpdateMask(cv::Mat &cvMask, const std::vector<cv::Scalar> &trackColors, VPIArray prevFeatures,
150  VPIArray curFeatures, VPIArray status)
151 {
152  // Now that optical flow is completed, there are usually two approaches to take:
153  // 1. Add new feature points from current frame using a feature detector such as
154  // \ref algo_harris_corners "Harris Corner Detector"
155  // 2. Keep using the points that are being tracked.
156  //
157  // The sample app uses the valid feature point and continue to do the tracking.
158 
159  // Lock the input and output arrays to draw the tracks to the output mask.
160  VPIArrayData curFeaturesData, statusData;
161  CHECK_STATUS(vpiArrayLock(curFeatures, VPI_LOCK_READ_WRITE, &curFeaturesData));
162  CHECK_STATUS(vpiArrayLock(status, VPI_LOCK_READ, &statusData));
163 
164  const VPIKeypoint *pCurFeatures = (VPIKeypoint *)curFeaturesData.data;
165  const uint8_t *pStatus = (uint8_t *)statusData.data;
166 
167  const VPIKeypoint *pPrevFeatures;
168  if (prevFeatures)
169  {
170  VPIArrayData prevFeaturesData;
171  CHECK_STATUS(vpiArrayLock(prevFeatures, VPI_LOCK_READ, &prevFeaturesData));
172  pPrevFeatures = (VPIKeypoint *)prevFeaturesData.data;
173  }
174  else
175  {
176  pPrevFeatures = NULL;
177  }
178 
179  int numTrackedKeypoints = 0;
180  int totKeypoints = *curFeaturesData.sizePointer;
181 
182  for (int i = 0; i < totKeypoints; i++)
183  {
184  // keypoint is being tracked?
185  if (pStatus[i] == 0)
186  {
187  // draw the tracks
188  cv::Point curPoint{(int)round(pCurFeatures[i].x), (int)round(pCurFeatures[i].y)};
189  if (pPrevFeatures != NULL)
190  {
191  cv::Point2f prevPoint{pPrevFeatures[i].x, pPrevFeatures[i].y};
192  line(cvMask, prevPoint, curPoint, trackColors[i], 2);
193  }
194 
195  circle(cvMask, curPoint, 5, trackColors[i], -1);
196 
197  numTrackedKeypoints++;
198  }
199  }
200 
201  // We're finished working with the arrays.
202  if (prevFeatures)
203  {
204  CHECK_STATUS(vpiArrayUnlock(prevFeatures));
205  }
206  CHECK_STATUS(vpiArrayUnlock(curFeatures));
207  CHECK_STATUS(vpiArrayUnlock(status));
208 
209  return numTrackedKeypoints;
210 }
211 
212 int main(int argc, char *argv[])
213 {
214  // OpenCV image that will be wrapped by a VPIImage.
215  // Define it here so that it's destroyed *after* wrapper is destroyed
216  cv::Mat cvFrame;
217 
218  // VPI objects that will be used
219  VPIStream stream = NULL;
220  VPIImage imgTempFrame = NULL;
221  VPIImage imgFrame = NULL;
222  VPIPyramid pyrPrevFrame = NULL, pyrCurFrame = NULL;
223  VPIArray prevFeatures = NULL, curFeatures = NULL, status = NULL;
224  VPIPayload optflow = NULL;
225  VPIArray scores = NULL;
226  VPIPayload harris = NULL;
227 
228  int retval = 0;
229 
230  try
231  {
232  // ============================
233  // Parse command line arguments
234 
235  if (argc != 5)
236  {
237  throw std::runtime_error(std::string("Usage: ") + argv[0] +
238  " <cpu|cuda> <input_video> <pyramid_levels> <output>");
239  }
240 
241  std::string strBackend = argv[1];
242  std::string strInputVideo = argv[2];
243  int32_t pyrLevel = std::stoi(argv[3]);
244  std::string strOutputFiles = argv[4];
245 
246  // Now parse the backend
247  VPIBackend backend;
248 
249  if (strBackend == "cpu")
250  {
251  backend = VPI_BACKEND_CPU;
252  }
253  else if (strBackend == "cuda")
254  {
255  backend = VPI_BACKEND_CUDA;
256  }
257  else
258  {
259  throw std::runtime_error("Backend '" + strBackend + "' not recognized, it must be either cpu or cuda.");
260  }
261 
262  {
263  int ext = strOutputFiles.rfind('.');
264  strOutputFiles = strOutputFiles.substr(0, ext) + "_" + strBackend + strOutputFiles.substr(ext);
265  }
266 
267  // ====================
268  // Load the input video
269  cv::VideoCapture invid;
270  if (!invid.open(strInputVideo))
271  {
272  throw std::runtime_error("Can't open '" + strInputVideo + "'");
273  }
274 
275  // Fetch the first frame and wrap it into a VPIImage.
276  // The points to be tracked will be gathered from this frame later on.
277  if (!invid.read(cvFrame))
278  {
279  throw std::runtime_error("Can't retrieve first frame from '" + strInputVideo + "'");
280  }
281 
282  // =================================================
283  // Allocate VPI resources and do some pre-processing
284 
285  // Create the stream where processing will happen.
286  CHECK_STATUS(vpiStreamCreate(0, &stream));
287 
288  CHECK_STATUS(vpiImageCreateOpenCVMatWrapper(cvFrame, 0, &imgTempFrame));
289 
290  // Create grayscale image representation of input.
291  CHECK_STATUS(vpiImageCreate(cvFrame.cols, cvFrame.rows, VPI_IMAGE_FORMAT_U8, 0, &imgFrame));
292 
293  // Create the image pyramids used by the algorithm
294  CHECK_STATUS(
295  vpiPyramidCreate(cvFrame.cols, cvFrame.rows, VPI_IMAGE_FORMAT_U8, pyrLevel, 0.5, 0, &pyrPrevFrame));
296  CHECK_STATUS(vpiPyramidCreate(cvFrame.cols, cvFrame.rows, VPI_IMAGE_FORMAT_U8, pyrLevel, 0.5, 0, &pyrCurFrame));
297 
298  // Create input and output arrays
299  CHECK_STATUS(vpiArrayCreate(MAX_HARRIS_CORNERS, VPI_ARRAY_TYPE_KEYPOINT, 0, &prevFeatures));
300  CHECK_STATUS(vpiArrayCreate(MAX_HARRIS_CORNERS, VPI_ARRAY_TYPE_KEYPOINT, 0, &curFeatures));
301  CHECK_STATUS(vpiArrayCreate(MAX_HARRIS_CORNERS, VPI_ARRAY_TYPE_U8, 0, &status));
302 
303  // Create Optical Flow payload
304  CHECK_STATUS(vpiCreateOpticalFlowPyrLK(backend, cvFrame.cols, cvFrame.rows, VPI_IMAGE_FORMAT_U8, pyrLevel, 0.5,
305  &optflow));
306 
307  // Parameters we'll use. No need to change them on the fly, so just define them here.
308  // We're using the default parameters.
309  VPIOpticalFlowPyrLKParams lkParams;
310  CHECK_STATUS(vpiInitOpticalFlowPyrLKParams(&lkParams));
311 
312  // Create a mask image for drawing purposes
313  cv::Mat cvMask = cv::Mat::zeros(cvFrame.size(), CV_8UC3);
314 
315  // Gather feature points from first frame using Harris Corners on CPU.
316  {
317  CHECK_STATUS(vpiArrayCreate(MAX_HARRIS_CORNERS, VPI_ARRAY_TYPE_U32, 0, &scores));
318 
319  VPIHarrisCornerDetectorParams harrisParams;
320  CHECK_STATUS(vpiInitHarrisCornerDetectorParams(&harrisParams));
321  harrisParams.strengthThresh = 0;
322  harrisParams.sensitivity = 0.01;
323 
324  CHECK_STATUS(vpiCreateHarrisCornerDetector(VPI_BACKEND_CPU, cvFrame.cols, cvFrame.rows, &harris));
325 
326  // Convert input to grayscale to conform with harris corner detector restrictions
327  CHECK_STATUS(vpiSubmitConvertImageFormat(stream, VPI_BACKEND_CUDA, imgTempFrame, imgFrame, NULL));
328 
329  CHECK_STATUS(vpiSubmitHarrisCornerDetector(stream, VPI_BACKEND_CPU, harris, imgFrame, curFeatures, scores,
330  &harrisParams));
331 
332  CHECK_STATUS(vpiStreamSync(stream));
333 
334  SortKeypoints(curFeatures, scores, MAX_KEYPOINTS);
335  }
336 
337  // Create some random colors
338  std::vector<cv::Scalar> trackColors;
339  {
340  std::vector<cv::Vec3b> tmpTrackColors;
341 
342  VPIArrayData ptsData;
343  CHECK_STATUS(vpiArrayLock(curFeatures, VPI_LOCK_READ, &ptsData));
344 
345  const VPIKeypoint *pts = (VPIKeypoint *)ptsData.data;
346 
347  for (int i = 0; i < *ptsData.sizePointer; i++)
348  {
349  // Track hue depends on its initial position
350  int hue = ((int)pts[i].x ^ (int)pts[i].y) % 180;
351 
352  tmpTrackColors.push_back(cv::Vec3b(hue, 255, 255));
353  }
354  CHECK_STATUS(vpiArrayUnlock(curFeatures));
355 
356  cvtColor(tmpTrackColors, tmpTrackColors, cv::COLOR_HSV2BGR);
357 
358  for (size_t i = 0; i < tmpTrackColors.size(); i++)
359  {
360  trackColors.push_back(cv::Scalar(tmpTrackColors[i]));
361  }
362  }
363 
364  // Update the mask with info from first frame.
365  int numTrackedKeypoints = UpdateMask(cvMask, trackColors, NULL, curFeatures, status);
366 
367  // =================================================
368  // Main processing stage
369 
370  // Generate pyramid for first frame.
371  CHECK_STATUS(vpiSubmitGaussianPyramidGenerator(stream, backend, imgFrame, pyrCurFrame));
372 
373  // Counter for the frames
374  int idxFrame = 0;
375 
376  while (true)
377  {
378  // Save frame to disk
379  SaveFileToDisk(imgFrame, cvMask, strOutputFiles, idxFrame);
380 
381  printf("Frame id=%d: %d points tracked. \n", idxFrame, numTrackedKeypoints);
382 
383  // Last iteration's current frame/features become this iteration's prev frame/features.
384  // The former will contain information gathered in this iteration.
385  std::swap(prevFeatures, curFeatures);
386  std::swap(pyrPrevFrame, pyrCurFrame);
387 
388  // Fetch a new frame
389  if (!invid.read(cvFrame))
390  {
391  printf("Video ended.\n");
392  break;
393  }
394 
395  ++idxFrame;
396 
397  // Wrap frame into a VPIImage, reusing the existing imgFrame.
398  CHECK_STATUS(vpiImageSetWrappedOpenCVMat(imgTempFrame, cvFrame));
399 
400  // Convert it to grayscale
401  CHECK_STATUS(vpiSubmitConvertImageFormat(stream, backend, imgTempFrame, imgFrame, NULL))
402 
403  // Generate a pyramid out of it
404  CHECK_STATUS(vpiSubmitGaussianPyramidGenerator(stream, backend, imgFrame, pyrCurFrame));
405 
406  // Estimate the features' position in current frame given their position in previous frame
407  CHECK_STATUS(vpiSubmitOpticalFlowPyrLK(stream, 0, optflow, pyrPrevFrame, pyrCurFrame, prevFeatures,
408  curFeatures, status, &lkParams));
409 
410  // Wait for processing to finish.
411  CHECK_STATUS(vpiStreamSync(stream));
412 
413  // Update the output mask
414  numTrackedKeypoints = UpdateMask(cvMask, trackColors, prevFeatures, curFeatures, status);
415 
416  // No more keypoints being tracked?
417  if (numTrackedKeypoints == 0)
418  {
419  printf("No keypoints to track.\n");
420  break; // we can finish procesing.
421  }
422  }
423  }
424  catch (std::exception &e)
425  {
426  std::cerr << e.what() << std::endl;
427  retval = 1;
428  }
429 
430  vpiStreamDestroy(stream);
431  vpiPayloadDestroy(harris);
432  vpiPayloadDestroy(optflow);
433 
434  vpiPyramidDestroy(pyrPrevFrame);
435  vpiImageDestroy(imgTempFrame);
436  vpiImageDestroy(imgFrame);
437  vpiArrayDestroy(prevFeatures);
438  vpiArrayDestroy(curFeatures);
439  vpiArrayDestroy(status);
440  vpiArrayDestroy(scores);
441 
442  return retval;
443 }
444 
445 // vim: ts=8:sw=4:sts=4:et:ai
Functions and structures for dealing with VPI arrays.
Declares functions that handle image format conversion.
Declares functions that handle gaussian pyramids.
Declares functions that implement the Harris Corner Detector algorithm.
Functions and structures for dealing with VPI images.
Functions for handling OpenCV interoperability with VPI.
Declares functions that implement the Pyramidal LK Optical Flow algorithm.
Functions and structures for dealing with VPI pyramids.
Declaration of VPI status codes handling functions.
Declares functions dealing with VPI streams.
int32_t * sizePointer
Points to the number of elements in the array.
Definition: Array.h:125
void * data
Points to the first element of the array.
Definition: Array.h:128
VPIStatus vpiArrayUnlock(VPIArray array)
Releases the lock on array object.
VPIStatus vpiArrayLock(VPIArray array, VPILockMode mode, VPIArrayData *arrayData)
Acquires the lock on array object and returns a pointer to array data.
void vpiArrayDestroy(VPIArray array)
Destroy an array instance.
VPIStatus vpiArrayCreate(int32_t capacity, VPIArrayType type, uint32_t flags, VPIArray *array)
Create an empty array instance.
struct VPIArrayImpl * VPIArray
A handle to an array.
Definition: Types.h:191
@ VPI_ARRAY_TYPE_U32
unsigned 32-bit.
Definition: ArrayType.h:75
@ VPI_ARRAY_TYPE_KEYPOINT
VPIKeypoint element.
Definition: ArrayType.h:76
@ VPI_ARRAY_TYPE_U8
unsigned 8-bit.
Definition: ArrayType.h:72
Stores information about array characteristics and content.
Definition: Array.h:119
VPIStatus vpiSubmitConvertImageFormat(VPIStream stream, uint32_t backend, VPIImage input, VPIImage output, const VPIConvertImageFormatParams *params)
Converts the image contents to the desired format, with optional scaling and offset.
VPIStatus vpiSubmitGaussianPyramidGenerator(VPIStream stream, uint32_t backend, VPIImage input, VPIPyramid output)
Computes the Gaussian pyramid from the input image.
float strengthThresh
Specifies the minimum threshold with which to eliminate Harris Corner scores.
Definition: HarrisCorners.h:88
float sensitivity
Specifies sensitivity threshold from the Harris-Stephens equation.
Definition: HarrisCorners.h:91
VPIStatus vpiInitHarrisCornerDetectorParams(VPIHarrisCornerDetectorParams *params)
Initializes VPIHarrisCornerDetectorParams with default values.
VPIStatus vpiCreateHarrisCornerDetector(uint32_t backends, int32_t inputWidth, int32_t inputHeight, VPIPayload *payload)
Creates a Harris Corner Detector payload.
VPIStatus vpiSubmitHarrisCornerDetector(VPIStream stream, uint32_t backend, VPIPayload payload, VPIImage input, VPIArray outFeatures, VPIArray outScores, const VPIHarrisCornerDetectorParams *params)
Submits Harris Corner Detector operation to the stream associated with the payload.
Structure that defines the parameters for vpiSubmitHarrisCornerDetector.
Definition: HarrisCorners.h:80
@ VPI_IMAGE_FORMAT_U8
Single plane with one 8-bit unsigned integer channel.
Definition: ImageFormat.h:104
VPIStatus vpiImageLock(VPIImage img, VPILockMode mode, VPIImageData *hostData)
Acquires the lock on an image object and returns a pointer to the image planes.
void vpiImageDestroy(VPIImage img)
Destroy an image instance.
struct VPIImageImpl * VPIImage
A handle to an image.
Definition: Types.h:215
VPIStatus vpiImageCreate(int32_t width, int32_t height, VPIImageFormat fmt, uint32_t flags, VPIImage *img)
Create an empty image instance with the specified flags.
VPIStatus vpiImageUnlock(VPIImage img)
Releases the lock on an image object.
Stores information about image characteristics and content.
Definition: Image.h:159
VPIStatus vpiImageDataExportOpenCVMat(const VPIImageData &imgData, cv::Mat *mat)
Fills an existing cv::Mat with data from VPIImageData coming from a locked VPIImage.
VPIStatus vpiImageSetWrappedOpenCVMat(VPIImage img, const cv::Mat &mat)
Redefines the wrapped cv::Mat of an existing VPIImage wrapper.
VPIStatus vpiImageCreateOpenCVMatWrapper(const cv::Mat &mat, VPIImageFormat fmt, uint32_t flags, VPIImage *img)
Wraps a cv::Mat in an VPIImage with the given image format.
VPIStatus vpiCreateOpticalFlowPyrLK(uint32_t backends, int32_t width, int32_t height, VPIImageFormat fmt, int32_t levels, float scale, VPIPayload *payload)
Creates payload for vpiSubmitOpticalFlowPyrLK.
VPIStatus vpiSubmitOpticalFlowPyrLK(VPIStream stream, uint32_t backend, VPIPayload payload, VPIPyramid prevPyr, VPIPyramid curPyr, VPIArray prevPts, VPIArray curPts, VPIArray trackingStatus, const VPIOpticalFlowPyrLKParams *params)
Runs Pyramidal LK Optical Flow on two frames.
VPIStatus vpiInitOpticalFlowPyrLKParams(VPIOpticalFlowPyrLKParams *params)
Initializes VPIOpticalFlowPyrLKParams with default values.
Structure that defines the parameters for vpiSubmitOpticalFlowPyrLK.
struct VPIPayloadImpl * VPIPayload
A handle to an algorithm payload.
Definition: Types.h:227
void vpiPayloadDestroy(VPIPayload payload)
Deallocates the payload object and all associated resources.
struct VPIPyramidImpl * VPIPyramid
A handle to an image pyramid.
Definition: Types.h:221
VPIStatus vpiPyramidCreate(int32_t width, int32_t height, VPIImageFormat fmt, int32_t numLevels, float scale, uint32_t flags, VPIPyramid *pyr)
Create an empty image pyramid instance with the specified flags.
void vpiPyramidDestroy(VPIPyramid pyr)
Destroy an image pyramid instance as well as all resources it owns.
struct VPIStreamImpl * VPIStream
A handle to a stream.
Definition: Types.h:209
VPIStatus vpiStreamSync(VPIStream stream)
Blocks the calling thread until all submitted commands in this stream queue are done (queue is empty)...
VPIBackend
VPI Backend types.
Definition: Types.h:91
void vpiStreamDestroy(VPIStream stream)
Destroy a stream instance and deallocate all HW resources.
VPIStatus vpiStreamCreate(uint32_t flags, VPIStream *stream)
Create a stream instance.
@ VPI_BACKEND_CUDA
CUDA backend.
Definition: Types.h:93
@ VPI_BACKEND_CPU
CPU backend.
Definition: Types.h:92
float y
Keypoint's y coordinate.
Definition: Types.h:276
float x
Keypoint's x coordinate.
Definition: Types.h:275
@ VPI_LOCK_READ_WRITE
Lock memory for reading and writing.
Definition: Types.h:397
@ VPI_LOCK_READ
Lock memory only for reading.
Definition: Types.h:383
Stores a keypoint coordinate.
Definition: Types.h:274