29 #include <opencv2/core/version.hpp>
30 #if CV_MAJOR_VERSION >= 3
31 # include <opencv2/imgcodecs.hpp>
32 # include <opencv2/videoio.hpp>
34 # include <opencv2/highgui/highgui.hpp>
37 #include <opencv2/imgproc/imgproc.hpp>
60 constexpr
int MAX_HARRIS_CORNERS = 8192;
63 constexpr
int MAX_KEYPOINTS = 100;
65 #define CHECK_STATUS(STMT) \
68 VPIStatus status__ = (STMT); \
69 if (status__ != VPI_SUCCESS) \
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()); \
79 static void SaveFileToDisk(
VPIImage img, cv::Mat cvMask, std::string baseFileName, int32_t frameCounter)
89 cvtColor(tmp, cvImage, cv::COLOR_GRAY2BGR);
99 add(cvImage, cvMask, cvImage);
102 std::string fname = baseFileName;
103 int ext = fname.rfind(
'.');
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());
110 if (!imwrite(buffer, cvImage, {cv::IMWRITE_JPEG_QUALITY, 70}))
112 throw std::runtime_error(
"Can't write to " + std::string(buffer));
126 std::vector<int> indices(*aosKeypoints.
sizePointer);
127 std::iota(indices.begin(), indices.end(), 0);
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];
135 indices.resize(std::min<size_t>(indices.size(), max));
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);
152 static int UpdateMask(cv::Mat &cvMask,
const std::vector<cv::Scalar> &trackColors,
VPIArray prevFeatures,
171 const uint8_t *pStatus = (uint8_t *)aosStatus.
data;
182 pPrevFeatures = NULL;
185 int numTrackedKeypoints = 0;
188 for (
int i = 0; i < totKeypoints; i++)
194 cv::Point curPoint{(int)round(pCurFeatures[i].x), (int)round(pCurFeatures[i].y)};
195 if (pPrevFeatures != NULL)
197 cv::Point2f prevPoint{pPrevFeatures[i].
x, pPrevFeatures[i].
y};
198 line(cvMask, prevPoint, curPoint, trackColors[i], 2);
201 circle(cvMask, curPoint, 5, trackColors[i], -1);
203 numTrackedKeypoints++;
215 return numTrackedKeypoints;
218 int main(
int argc,
char *argv[])
228 VPIPyramid pyrPrevFrame = NULL, pyrCurFrame = NULL;
229 VPIArray prevFeatures = NULL, curFeatures = NULL, status = NULL;
243 throw std::runtime_error(std::string(
"Usage: ") + argv[0] +
244 " <cpu|cuda|pva> <input_video> <pyramid_levels> <output>");
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];
255 if (strBackend ==
"cpu")
259 else if (strBackend ==
"cuda")
263 else if (strBackend ==
"pva")
269 throw std::runtime_error(
"Backend '" + strBackend +
270 "' not recognized, it must be either cpu, cuda or pva.");
274 int ext = strOutputFiles.rfind(
'.');
275 strOutputFiles = strOutputFiles.substr(0, ext) +
"_" + strBackend + strOutputFiles.substr(ext);
280 cv::VideoCapture invid;
281 if (!invid.open(strInputVideo))
283 throw std::runtime_error(
"Can't open '" + strInputVideo +
"'");
288 if (!invid.read(cvFrame))
290 throw std::runtime_error(
"Can't retrieve first frame from '" + strInputVideo +
"'");
324 cv::Mat cvMask = cv::Mat::zeros(cvFrame.size(), CV_8UC3);
345 SortKeypoints(curFeatures, scores, MAX_KEYPOINTS);
349 std::vector<cv::Scalar> trackColors;
351 std::vector<cv::Vec3b> tmpTrackColors;
360 for (
int i = 0; i < *aosKeypoints.
sizePointer; i++)
363 int hue = ((int)pts[i].x ^ (
int)pts[i].
y) % 180;
365 tmpTrackColors.push_back(cv::Vec3b(hue, 255, 255));
369 cvtColor(tmpTrackColors, tmpTrackColors, cv::COLOR_HSV2BGR);
371 for (
size_t i = 0; i < tmpTrackColors.size(); i++)
373 trackColors.push_back(cv::Scalar(tmpTrackColors[i]));
378 int numTrackedKeypoints = UpdateMask(cvMask, trackColors, NULL, curFeatures, status);
392 SaveFileToDisk(imgFrame, cvMask, strOutputFiles, idxFrame);
394 printf(
"Frame id=%d: %d points tracked. \n", idxFrame, numTrackedKeypoints);
398 std::swap(prevFeatures, curFeatures);
399 std::swap(pyrPrevFrame, pyrCurFrame);
402 if (!invid.read(cvFrame))
404 printf(
"Video ended.\n");
421 curFeatures, status, &lkParams));
427 numTrackedKeypoints = UpdateMask(cvMask, trackColors, prevFeatures, curFeatures, status);
430 if (numTrackedKeypoints == 0)
432 printf(
"No keypoints to track.\n");
437 catch (std::exception &e)
439 std::cerr << e.what() << std::endl;
Functions and structures for dealing with VPI arrays.
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.
void * data
Points to the first element of the array.
VPIArrayBuffer buffer
Stores the array contents.
int32_t * sizePointer
Points to the number of elements in the array.
VPIArrayBufferAOS aos
Array stored in array-of-structures layout.
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.
@ VPI_ARRAY_TYPE_U32
Unsigned 32-bit.
@ VPI_ARRAY_TYPE_KEYPOINT_F32
VPIKeypointF32 element.
@ VPI_ARRAY_TYPE_U8
Unsigned 8-bit.
@ VPI_ARRAY_BUFFER_HOST_AOS
Host-accessible array-of-structures.
Stores information about array characteristics and content.
Stores information about array characteristics and contents.
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.
float sensitivity
Specifies sensitivity threshold from the Harris-Stephens equation.
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.
void vpiImageDestroy(VPIImage img)
Destroy an image instance.
struct VPIImageImpl * VPIImage
A handle to an image.
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.
Stores information about image characteristics and content.
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.
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.
void vpiPyramidDestroy(VPIPyramid pyr)
Destroy an image pyramid instance as well as all resources it owns.
struct VPIStreamImpl * VPIStream
A handle to a stream.
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.
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.
@ VPI_BACKEND_PVA
PVA backend.
@ VPI_BACKEND_CPU
CPU backend.
float x
Keypoint's x coordinate.
float y
Keypoint's y coordinate.
@ VPI_BORDER_CLAMP
Border pixels are repeated indefinitely.
@ VPI_LOCK_READ_WRITE
Lock memory for reading and writing.
@ VPI_LOCK_READ
Lock memory only for reading.
Stores a float32 keypoint coordinate The coordinate is relative to the top-left corner of an image.