DriveWorks SDK Reference
4.0.0 Release
For Test and Development only

src/dw/imageprocessing/features/docs/usecase1.md
Go to the documentation of this file.
1 # Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
2 
3 @page imageprocessing_features_usecase1 Single Camera Feature Tracking
4 
5 This tutorial shows how dwFeature2DDetector and dwFeature2DTracker modules are typically used. Note that error handling is left out for clarity.
6 
7 #### Initialize feature history array on both CPU and GPU
8 
9 ```{.cpp}
10 dwFeatureHistoryArray_create(&featureHistoryCPU, maxFeatureCount, maxHistoryCapacity,
11  DW_MEMORY_TYPE_CPU, contextHandle);
12 
13 dwFeatureHistoryArray_create(&featureHistoryGPU, maxFeatureCount, maxHistoryCapacity,
14  DW_MEMORY_TYPE_CUDA, contextHandle);
15 
16 ```
17 
18 #### Initialize feature array on GPU for detector
19 
20 ```{.cpp}
21 dwFeatureArray_create(&featuresDetected, maxFeatureCount, DW_MEMORY_TYPE_CUDA, contextHandle);
22 
23 ```
24 
25 #### Initialize feature detector and tracker parameters with default values
26 
27 ```{.cpp}
28  dwFeature2DDetectorConfig detectorConfig = {};
29  dwFeature2DDetector_initDefaultParams(&detectorConfig);
30 
31  dwFeature2DTrackerConfig trackerConfig = {};
32  dwFeature2DTracker_initDefaultParams(&trackerConfig);
33 ```
34 
35 Modify parameters according to input image and detection requirements, create detector.
36 Detector will first split the given WxH input image into cellSize x cellSize cells, detect Harris corner whose score is higher than scoreThreshold. Features with score >= scoreThreshold will be considered as high frequency details (red crosses). Detail features will be added to candidate list first, detector will then sort the rest features with score between (scoreThreshold, detailThreshold) from highest to lowest by cell, select the first numEvenDistributionPerCell features in each cell (blue crosses, here numEvenDistributionPerCell = 5, so there're 5 second-highest-score features in each cell). These second-highest-score features are distributed evenly across cells.
37 ![](feature_tracker.png)
38 Setting scoreThreshold >= detailThreshold means all features are high frequency details, numEvenDistributionPerCell will be invalid. Setting numEvenDistributionPerCell = 0 turns off the even distribution component. Both of the 2 cases will make detected features be clustered in high frequency regions, i.e. only red crosses will be left in above illustration.
39 `contextHandle` is assumed to be previously initialized dwContextHandle_t.
40 ```{.cpp}
41  detectorConfig.imageWidth = inputImageProps.width;
42  detectorConfig.imageHeight = inputImageProps.height;
43  detectorConfig.scoreThreshold = scoreThreshold;
44  detectorConfig.detailThreshold = detailThreshold;
45  detectorConfig.cellSize = cellSize;
46  detectorConfig.maxFeatureCount = maxFeatureCount;
47  detectorConfig.numEvenDistributionPerCell = numEvenDistributionPerCell;
48 
49  dwFeature2DDetector_initialize(&detector, &detectorConfig, 0, contextHandle);
50 ```
51 
52 Modify parameters to use PVA Harris feature detector, create detector.
53 The standard Harris corner detection process is applied. First detector computes the spatial gradient, using a separable gradient filter. Gradient filter size is 3x3, 5x5 or 7x7, correspond to gradientSize value 3,5,7. Then Computes a gradients covariance matrix (structure tensor) for each pixel within a block window, the block window size is 3x3, 5x5, or 7x7, correspond to blockSize value 3,5,7. Later Computes a Harris response score using a sensitivity factor, setting harrisK to modify the factor. Last applies a threshold-strength criterion, the threshold value is setted by scoreThreshold, it should be a uint32 value.
54 `contextHandle` is assumed to be previously initialized dwContextHandle_t.
55 ```{.cpp}
56  detectorConfig.type = DW_FEATURE2D_DETECTOR_TYPE_STD
57  detectorConfig.imageWidth = inputImageProps.width;
58  detectorConfig.imageHeight = inputImageProps.height;
59  detectorConfig.scoreThreshold = scoreThreshold;
60  detectorConfig.blockSize = blockSize;
61  detectorConfig.gradientSize = gradientSize;
62  detectorConfig.maxFeatureCount = maxFeatureCount;
63  detectorConfig.harrisK = harrisK;
64  detectorConfig.processorType = DW_PROCESSOR_TYPE_PVA_0;//or DW_PROCESSOR_TYPE_PVA_1
65  dwFeature2DDetector_initialize(&detector, &detectorConfig, 0, contextHandle);
66 ```
67 
68 Modify parameters to use Fast9 feature detector, create detector.
69 Fast9 Corner Detector will detect corner whose pixel vaule is larger or smaller than at least 9 continous pixels on the Bresenham circle around it by at least scoreThreshold. And non-maximum suppression can be choosen to apply to filter detected features.
70 `contextHandle` is assumed to be previously initialized dwContextHandle_t.
71 ```{.cpp}
72  detectorConfig.type = DW_FEATURE2D_DETECTOR_TYPE_FAST9
73  detectorConfig.imageWidth = inputImageProps.width;
74  detectorConfig.imageHeight = inputImageProps.height;
75  detectorConfig.scoreThreshold = scoreThreshold;
76  detectorConfig.maxFeatureCount = maxFeatureCount;
77  detectorConfig.NMSRadius = nmsRadius;
78  detectorConfig.processorType = DW_PROCESSOR_TYPE_GPU;//or DW_PROCESSOR_TYPE_PVA_0, DW_PROCESSOR_TYPE_PVA_1
79  dwFeature2DDetector_initialize(&detector, &detectorConfig, 0, contextHandle);
80 ```
81 
82 Modify parameters according to input image and tracking requirements, create tracker.
83 `trackerConfig.isInputCompact` must be read from detector.
84 `contextHandle` is assumed to be previously initialized dwContextHandle_t.
85 ```{.cpp}
86  trackerConfig.imageWidth = inputImageProps.width;
87  trackerConfig.imageHeight = inputImageProps.height;
88  trackerConfig.windowSizeLK = 10;
89  trackerConfig.iterationsLK = 10;
90  trackerConfig.detectorType = detectorConfig.type;
91 
92  dwFeature2DTracker_initialize(&tracker, &trackerConfig, 0, contextHandle);
93 ```
94 
95 Create 2 image pyramids as detection/tracking input: one is current, one is previous, the 2 pyramids work as a double buffer (or ping-pong buffer). They swap each other after each detection/tracking cycle. So new frame will always be read into pyrmaidCurrent and the previous frame will be stored to pyramidPrevious.
96 
97 `dwPyramid_create` only creates pyramid image and allocates memory, pyramid will be filled in `dwImageFilter_computePyramid`. Top level (level 0) in pyramid is always the same size as original input image.
98 
99 `inputImageProps.width`, `inputImageProps.height` are the same in tracker/detector initialization
100 
101 `imagePxlType` should be got from `dwImage_getPixelType(inputImageProps.format)`.
102 
103 `contextHandle` is assumed to be previously initialized dwContextHandle_t.
104 
105 ```{.cpp}
106  dwPyramid_create(&pyramidPrevious, levelCount,
107  inputImageProps.width, inputImageProps.height, pxlType, context);
108 
109  dwPyramid_create(&pyramidCurrent, levelCount,
110  inputImageProps.width, inputImageProps.height, pxlType,context);
111 ```
112 
113 #### Create nccScore array on GPU
114 ```{.cpp}
115  cudaMalloc(&d_nccScores, maxFeatureCount * sizeof(float32_t));
116 ```
117 
118 #### Start tracking the loop
119 
120 ```{.cpp}
121  while(true)
122  {
123  // ping-pong current/previous pyramid
124  // so new frame will always be built in pyramidCurrent
125  // and old pyramid will be stored in pyramidPrevious
126  std::swap(pyramidCurrent, pyramidPrevious);
127 
128  // CODE: Read image frame code
129  dwImageHandle_t image = ...;
130 
131  // compute pyramid based on the new read frame image
132  dwImageFilter_computePyramid(&pyramidCurrent, image, 0, contextHandle);
133 
134  // do tracking
135  dwFeatureArray featurePredicted;
136  dwFeature2DTracker_trackFeatures(&featureHistoryGPU, &featurePredicted,
137  d_nccScores, &featuresDetected,
138  &pyramidPrevious, &pyramidCurrent, tracker)
139 
140  // detect new features in the current frame
141  dwFeature2DDetector_detectFromImage(&featuresDetected, pyramidCurrent.levelImages[0],
142  &featurePredicted, d_nccScores, detector)
143 
144  // copy detected results to CPU
145  dwFeatureHistoryArray_copy(&featureHistoryCPU, &featureHistoryGPU, 0);
146 
147  // do some stuff in CPU
148  featureHistoryCPU.locationHistory[...];
149  featureHistoryCPU.statuses[...];
150  }
151 ```
152 
153 #### Finally, free previously allocated memory.
154 
155 ```{.cpp}
156  cudaFree(d_nccScores);
157 
158  dwPyramid_destroy(pyramidPrevious);
159  dwPyramid_destroy(pyramidCurrent);
160 
161  dwFeatureHistoryArray_destroy(featureHistoryCPU);
162  dwFeatureHistoryArray_destroy(featureHistoryGPU);
163  dwFeatureArray_destroy(featuresDetected);
164 
165  dwFeature2DDetector_release(detector);
166  dwFeature2DTracker_release(tracker);
167 ```
168 
169 For the full implementation refer to @ref dwx_feature_tracker_sample.