| 74 | } |
| 75 | |
| 76 | Array<float> CvMatToOpOutput::createArray( |
| 77 | const Matrix& inputData, const double scaleInputToOutput, const Point<int>& outputResolution) |
| 78 | { |
| 79 | try |
| 80 | { |
| 81 | cv::Mat cvInputData = OP_OP2CVCONSTMAT(inputData); |
| 82 | // Sanity checks |
| 83 | if (cvInputData.empty()) |
| 84 | error("Wrong input element (empty cvInputData).", __LINE__, __FUNCTION__, __FILE__); |
| 85 | if (cvInputData.channels() != 3) |
| 86 | error("Input images must be 3-channel BGR.", __LINE__, __FUNCTION__, __FILE__); |
| 87 | if (cvInputData.cols <= 0 || cvInputData.rows <= 0) |
| 88 | error("Input images has 0 area.", __LINE__, __FUNCTION__, __FILE__); |
| 89 | if (outputResolution.x <= 0 || outputResolution.y <= 0) |
| 90 | error("Output resolution has 0 area.", __LINE__, __FUNCTION__, __FILE__); |
| 91 | // outputData - Reescale keeping aspect ratio and transform to float the output image |
| 92 | Array<float> outputData({outputResolution.y, outputResolution.x, 3}); // This size is used everywhere |
| 93 | // CPU version (faster if #Gpus <= 3 and relatively small images) |
| 94 | if (!mGpuResize) |
| 95 | { |
| 96 | cv::Mat frameWithOutputSize; |
| 97 | resizeFixedAspectRatio(frameWithOutputSize, cvInputData, scaleInputToOutput, outputResolution); |
| 98 | // Equivalent: frameWithOutputSize.convertTo(outputData.getCvMat(), CV_32FC3); |
| 99 | cv::Mat cvOutputData = OP_OP2CVMAT(outputData.getCvMat()); |
| 100 | frameWithOutputSize.convertTo(cvOutputData, CV_32FC3); |
| 101 | } |
| 102 | // CUDA version (if #Gpus > 3) |
| 103 | else |
| 104 | { |
| 105 | #ifdef USE_CUDA |
| 106 | // Input image can be shared between this one and cvMatToOpInput.hpp |
| 107 | // However, that version reduces the global accuracy a bit |
| 108 | // (Free and re-)Allocate temporary memory |
| 109 | const unsigned int inputImageSize = 3 * cvInputData.rows * cvInputData.cols; |
| 110 | if (pInputMaxSize < inputImageSize) |
| 111 | { |
| 112 | pInputMaxSize = inputImageSize; |
| 113 | cudaFree(pInputImageCuda); |
| 114 | cudaMalloc((void**)&pInputImageCuda, sizeof(unsigned char) * inputImageSize); |
| 115 | } |
| 116 | // (Free and re-)Allocate temporary memory |
| 117 | const unsigned int outputImageSize = 3 * outputResolution.x * outputResolution.y; |
| 118 | if (*spOutputMaxSize < outputImageSize) |
| 119 | { |
| 120 | *spOutputMaxSize = outputImageSize; |
| 121 | cudaFree(*spOutputImageCuda); |
| 122 | cudaMalloc((void**)spOutputImageCuda.get(), sizeof(float) * outputImageSize); |
| 123 | } |
| 124 | // Copy original image to GPU |
| 125 | cudaMemcpy( |
| 126 | pInputImageCuda, cvInputData.data, sizeof(unsigned char) * inputImageSize, cudaMemcpyHostToDevice); |
| 127 | // Resize output image on GPU |
| 128 | resizeAndPadRbgGpu( |
| 129 | *spOutputImageCuda, pInputImageCuda, cvInputData.cols, cvInputData.rows, outputResolution.x, |
| 130 | outputResolution.y, (float)scaleInputToOutput); |
| 131 | *spGpuMemoryAllocated = true; |
| 132 | // // No need to copy output image back to CPU |
| 133 | // cudaMemcpy( |