VPI - Vision Programming Interface

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