// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. #include "../precomp.hpp" #include "layers_common.hpp" namespace cv { namespace dnn { // Quantize FP32/FP16 Inputs to INT8 class QuantizeLayerImpl CV_FINAL : public QuantizeLayer { public: QuantizeLayerImpl(const LayerParams& params) { scale = params.get("scales", 1.0f); zeropoint = params.get("zeropoints", 0); setParamsFrom(params); } virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV; } bool getMemoryShapes(const std::vector &inputs, const int requiredOutputs, std::vector &outputs, std::vector &internals) const CV_OVERRIDE { CV_Assert(inputs.size() == 1); Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals); return false; } virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE { std::vector inputs, outputs; inputs_arr.getMatVector(inputs); outputs_arr.getMatVector(outputs); } #ifdef HAVE_OPENCL bool forward_ocl(InputArrayOfArrays inputs_, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_) { std::vector inputs, outputs; inputs_.getUMatVector(inputs); outputs_.getUMatVector(outputs); if (inputs_.depth() == CV_16S) { UMat inputFp32(shape(inputs[0]), CV_32F); convertFp16(inputs[0], inputFp32); inputFp32.copyTo(inputs[0]); } inputs[0].convertTo(outputs[0], CV_8S, 1.f/scale, zeropoint); return true; } #endif void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE { CV_TRACE_FUNCTION(); CV_TRACE_ARG_VALUE(name, "name", name.c_str()); CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget), forward_ocl(inputs_arr, outputs_arr, internals_arr)) std::vector inputs, outputs; inputs_arr.getMatVector(inputs); outputs_arr.getMatVector(outputs); inputs[0].convertTo(outputs[0], CV_8S, 1.f/scale, zeropoint); } }; // Dequantize INT8 Inputs to FP32/FP16 class DequantizeLayerImpl CV_FINAL : public DequantizeLayer { public: DequantizeLayerImpl(const LayerParams& params) { scale = params.get("scales", 1.0f); zeropoint = params.get("zeropoints", 0); setParamsFrom(params); } virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV; } bool getMemoryShapes(const std::vector &inputs, const int requiredOutputs, std::vector &outputs, std::vector &internals) const CV_OVERRIDE { CV_Assert(inputs.size() == 1); Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals); return false; } virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE { std::vector inputs, outputs; inputs_arr.getMatVector(inputs); outputs_arr.getMatVector(outputs); } #ifdef HAVE_OPENCL bool forward_ocl(InputArrayOfArrays inputs_, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_) { std::vector inputs, outputs; inputs_.getUMatVector(inputs); outputs_.getUMatVector(outputs); UMat outputFp32(shape(outputs[0]), CV_32F); inputs[0].convertTo(outputFp32, CV_32F, scale, -(scale*zeropoint)); if (outputs_.depth() == CV_16S) convertFp16(outputFp32, outputs[0]); else outputFp32.copyTo(outputs[0]); return true; } #endif void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE { CV_TRACE_FUNCTION(); CV_TRACE_ARG_VALUE(name, "name", name.c_str()); CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget), forward_ocl(inputs_arr, outputs_arr, internals_arr)) std::vector inputs, outputs; inputs_arr.getMatVector(inputs); outputs_arr.getMatVector(outputs); inputs[0].convertTo(outputs[0], CV_32F, scale, -(scale*zeropoint)); } }; // Rescale/Requantize INT8 Inputs from (scale1, zeropoint1) to (scale2, zeropoint2) class RequantizeLayerImpl CV_FINAL : public RequantizeLayer { public: RequantizeLayerImpl(const LayerParams& params) { scale = params.get("scale", 1.f); shift = params.get("shift", 0.f); setParamsFrom(params); } virtual bool supportBackend(int backendId) CV_OVERRIDE { return backendId == DNN_BACKEND_OPENCV; } bool getMemoryShapes(const std::vector &inputs, const int requiredOutputs, std::vector &outputs, std::vector &internals) const CV_OVERRIDE { CV_Assert(inputs.size() == 1); Layer::getMemoryShapes(inputs, requiredOutputs, outputs, internals); return false; } virtual void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE { std::vector inputs, outputs; inputs_arr.getMatVector(inputs); outputs_arr.getMatVector(outputs); } void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE { CV_TRACE_FUNCTION(); CV_TRACE_ARG_VALUE(name, "name", name.c_str()); std::vector inputs, outputs; inputs_arr.getMatVector(inputs); outputs_arr.getMatVector(outputs); inputs[0].convertTo(outputs[0], CV_8S, scale, shift); } }; Ptr QuantizeLayer::create(const LayerParams& params) { return Ptr(new QuantizeLayerImpl(params)); } Ptr DequantizeLayer::create(const LayerParams& params) { return Ptr(new DequantizeLayerImpl(params)); } Ptr RequantizeLayer::create(const LayerParams& params) { return Ptr(new RequantizeLayerImpl(params)); } } }