| 143 | } |
| 144 | |
| 145 | TupleTensor4 SIFTInto(Tensor &featCoords, Tensor &featMetadata, Tensor &featDescriptors, Tensor &numFeatures, |
| 146 | Tensor &in, int numOctaveLayers, float contrastThreshold, float edgeThreshold, float initSigma, |
| 147 | NVCVSIFTFlagType flags, std::optional<Stream> pstream) |
| 148 | { |
| 149 | if (!pstream) |
| 150 | { |
| 151 | pstream = Stream::Current(); |
| 152 | } |
| 153 | |
| 154 | auto inAccess = tensorAccess(in); |
| 155 | int3 inShape{(int)inAccess->numCols(), (int)inAccess->numRows(), (int)inAccess->numSamples()}; |
| 156 | if (flags == NVCV_SIFT_USE_EXPANDED_INPUT) |
| 157 | { |
| 158 | inShape.x *= 2; |
| 159 | inShape.y *= 2; |
| 160 | } |
| 161 | |
| 162 | auto op = CreateOperatorEx<PyOpSIFT>(inShape, numOctaveLayers); |
| 163 | |
| 164 | ResourceGuard guard(*pstream); |
| 165 | guard.add(LockMode::LOCK_MODE_READ, {in}); |
| 166 | guard.add(LockMode::LOCK_MODE_WRITE, {featCoords, featMetadata, featDescriptors, numFeatures}); |
| 167 | guard.add(LockMode::LOCK_MODE_READWRITE, {*op}); |
| 168 | |
| 169 | op->submit(pstream->cudaHandle(), in, featCoords, featMetadata, featDescriptors, numFeatures, numOctaveLayers, |
| 170 | contrastThreshold, edgeThreshold, initSigma, flags); |
| 171 | |
| 172 | return TupleTensor4(std::move(featCoords), std::move(featMetadata), std::move(featDescriptors), |
| 173 | std::move(numFeatures)); |
| 174 | } |
| 175 | |
| 176 | // Get default number of maximum features given width and height (5% of total pixels at a minimum of 1) |
| 177 | inline int GetDefaultMaxFeatures(int width, int height) |
no test coverage detected