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));
124 std::iota(indices.begin(), indices.end(), 0);
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];
132 indices.resize(std::min<size_t>(indices.size(), max));
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);
149 static int UpdateMask(cv::Mat &cvMask,
const std::vector<cv::Scalar> &trackColors,
VPIArray prevFeatures,
165 const uint8_t *pStatus = (uint8_t *)statusData.
data;
176 pPrevFeatures = NULL;
179 int numTrackedKeypoints = 0;
182 for (
int i = 0; i < totKeypoints; i++)
188 cv::Point curPoint{(int)round(pCurFeatures[i].x), (int)round(pCurFeatures[i].y)};
189 if (pPrevFeatures != NULL)
191 cv::Point2f prevPoint{pPrevFeatures[i].
x, pPrevFeatures[i].
y};
192 line(cvMask, prevPoint, curPoint, trackColors[i], 2);
195 circle(cvMask, curPoint, 5, trackColors[i], -1);
197 numTrackedKeypoints++;
209 return numTrackedKeypoints;
212 int main(
int argc,
char *argv[])
222 VPIPyramid pyrPrevFrame = NULL, pyrCurFrame = NULL;
223 VPIArray prevFeatures = NULL, curFeatures = NULL, status = NULL;
237 throw std::runtime_error(std::string(
"Usage: ") + argv[0] +
238 " <cpu|cuda> <input_video> <pyramid_levels> <output>");
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];
249 if (strBackend ==
"cpu")
253 else if (strBackend ==
"cuda")
259 throw std::runtime_error(
"Backend '" + strBackend +
"' not recognized, it must be either cpu or cuda.");
263 int ext = strOutputFiles.rfind(
'.');
264 strOutputFiles = strOutputFiles.substr(0, ext) +
"_" + strBackend + strOutputFiles.substr(ext);
269 cv::VideoCapture invid;
270 if (!invid.open(strInputVideo))
272 throw std::runtime_error(
"Can't open '" + strInputVideo +
"'");
277 if (!invid.read(cvFrame))
279 throw std::runtime_error(
"Can't retrieve first frame from '" + strInputVideo +
"'");
313 cv::Mat cvMask = cv::Mat::zeros(cvFrame.size(), CV_8UC3);
334 SortKeypoints(curFeatures, scores, MAX_KEYPOINTS);
338 std::vector<cv::Scalar> trackColors;
340 std::vector<cv::Vec3b> tmpTrackColors;
350 int hue = ((int)pts[i].x ^ (
int)pts[i].
y) % 180;
352 tmpTrackColors.push_back(cv::Vec3b(hue, 255, 255));
356 cvtColor(tmpTrackColors, tmpTrackColors, cv::COLOR_HSV2BGR);
358 for (
size_t i = 0; i < tmpTrackColors.size(); i++)
360 trackColors.push_back(cv::Scalar(tmpTrackColors[i]));
365 int numTrackedKeypoints = UpdateMask(cvMask, trackColors, NULL, curFeatures, status);
379 SaveFileToDisk(imgFrame, cvMask, strOutputFiles, idxFrame);
381 printf(
"Frame id=%d: %d points tracked. \n", idxFrame, numTrackedKeypoints);
385 std::swap(prevFeatures, curFeatures);
386 std::swap(pyrPrevFrame, pyrCurFrame);
389 if (!invid.read(cvFrame))
391 printf(
"Video ended.\n");
408 curFeatures, status, &lkParams));
414 numTrackedKeypoints = UpdateMask(cvMask, trackColors, prevFeatures, curFeatures, status);
417 if (numTrackedKeypoints == 0)
419 printf(
"No keypoints to track.\n");
424 catch (std::exception &e)
426 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.
int32_t * sizePointer
Points to the number of elements in the array.
void * data
Points to the first element of the array.
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.
@ VPI_ARRAY_TYPE_U32
unsigned 32-bit.
@ VPI_ARRAY_TYPE_KEYPOINT
VPIKeypoint element.
@ VPI_ARRAY_TYPE_U8
unsigned 8-bit.
Stores information about array characteristics and content.
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.
float sensitivity
Specifies sensitivity threshold from the Harris-Stephens equation.
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.
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.
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.
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.
void vpiPayloadDestroy(VPIPayload payload)
Deallocates the payload object and all associated resources.
struct VPIPyramidImpl * VPIPyramid
A handle to an image pyramid.
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.
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(uint32_t flags, VPIStream *stream)
Create a stream instance.
@ VPI_BACKEND_CUDA
CUDA backend.
@ VPI_BACKEND_CPU
CPU backend.
float y
Keypoint's y coordinate.
float x
Keypoint's x coordinate.
@ VPI_LOCK_READ_WRITE
Lock memory for reading and writing.
@ VPI_LOCK_READ
Lock memory only for reading.
Stores a keypoint coordinate.