예제 #1
0
    public static IOps CreateOps(WorkerFactory.Type type, bool verbose = false)
    {
        WorkerFactory.ValidateType(type);
        switch (type)
        {
            case WorkerFactory.Type.ComputePrecompiled:
                return new PrecompiledComputeOps(ComputeShaderSingleton.Instance.kernels,
                                                ComputeShaderSingleton.Instance.referenceKernels, verbose: verbose);

            case WorkerFactory.Type.Compute:
                return new ComputeOps(ComputeShaderSingleton.Instance.kernels,
                                     ComputeShaderSingleton.Instance.referenceKernels, verbose: verbose);

            case WorkerFactory.Type.ComputeRef:
                return new ReferenceComputeOps(ComputeShaderSingleton.Instance.referenceKernels);

            case WorkerFactory.Type.CSharp:
                return new UnsafeArrayCPUOps();

            default:
                return new ReferenceCPUOps();
        }
    }
    /// <summary>
    /// Updates the output layer names based on the selected model architecture
    /// and initializes the Barracuda inference engine witht the selected model.
    /// </summary>
    private void InitializeBarracuda()
    {
        // The compiled model used for performing inference
        Model m_RunTimeModel;

        if (modelType == ModelType.MobileNet)
        {
            preProcessFunction = Utils.PreprocessMobileNet;
            // Compile the model asset into an object oriented representation
            m_RunTimeModel       = ModelLoader.Load(mobileNetModelAsset);
            displacementFWDLayer = m_RunTimeModel.outputs[2];
            displacementBWDLayer = m_RunTimeModel.outputs[3];
        }
        else
        {
            preProcessFunction = Utils.PreprocessResNet;
            // Compile the model asset into an object oriented representation
            m_RunTimeModel       = ModelLoader.Load(resnetModelAsset);
            displacementFWDLayer = m_RunTimeModel.outputs[3];
            displacementBWDLayer = m_RunTimeModel.outputs[2];
        }

        heatmapLayer = m_RunTimeModel.outputs[0];
        offsetsLayer = m_RunTimeModel.outputs[1];

        // Create a model builder to modify the m_RunTimeModel
        ModelBuilder modelBuilder = new ModelBuilder(m_RunTimeModel);

        // Add a new Sigmoid layer that takes the output of the heatmap layer
        modelBuilder.Sigmoid(predictionLayer, heatmapLayer);

        // Validate if backend is supported, otherwise use fallback type.
        workerType = WorkerFactory.ValidateType(workerType);

        // Create a worker that will execute the model with the selected backend
        engine = new Engine(workerType, modelBuilder.model, modelType);
    }
예제 #3
0
        private void CreateBarracudaWorker()
        {
            if (_styleTexture == null || _predictionAlphasBetasData == null)
            {
                return;
            }
            int savedAlphaBetasIndex = 0;

            _layerNameToPatch = new List <string>();
            List <Layer> layerList = new List <Layer>(_model.layers);

            // Pre-process Network for run-time use
            Layer lastConv = null;

            for (int i = 0; i < layerList.Count; i++)
            {
                Layer layer = layerList[i];

                // Remove Style_Prediction_Network: constant with style, executed once in Setup()
                if (layer.name.Contains("Style_Prediction_Network/"))
                {
                    layerList.RemoveAt(i);
                    i--;
                    continue;
                }

                // Fix Upsample2D size parameters
                if (layer.type == Layer.Type.Upsample2D)
                {
                    layer.pool = new[] { 2, 2 };
                    //ref model is supposed to be nearest sampling but bilinear scale better when network is applied at lower resoltions
                    bool useBilinearUpsampling = forceBilinearUpsample2DInModel.value || (modelType.value != ModelType.Reference);
                    layer.axis = useBilinearUpsampling ? 1 : -1;
                }

                // Remove Mirror padding layers (not supported, TODO)
                if (layer.name.Contains("reflect_padding"))
                {
                    layerList[i + 1].inputs = layer.inputs;
                    layerList[i + 1].pad    = layer.pad.ToArray();
                    layerList.RemoveAt(i);
                    i--;
                }
                else if (layer.type == Layer.Type.Conv2D || layer.type == Layer.Type.Conv2DTrans)
                {
                    lastConv = layer;
                }
                else if (layer.type == Layer.Type.Normalization)
                {
                    // Manually set alpha/betas from Style_Prediction_Network as scale/bias tensors for InstanceNormalization
                    if (layerList[i - 1].type == Layer.Type.StridedSlice)
                    {
                        int channels = _predictionAlphasBetasData[savedAlphaBetasIndex].Length;
                        layer.datasets = new Layer.DataSet[2];

                        layer.datasets[0].shape  = new TensorShape(1, 1, 1, channels);
                        layer.datasets[0].offset = 0;
                        layer.datasets[0].length = channels;

                        layer.datasets[1].shape  = new TensorShape(1, 1, 1, channels);
                        layer.datasets[1].offset = channels;
                        layer.datasets[1].length = channels;

                        _layerNameToPatch.Add(layer.name);

                        float[] data = new float[channels * 2];
                        for (int j = 0; j < data.Length / 2; j++)
                        {
                            data[j] = _predictionAlphasBetasData[savedAlphaBetasIndex][j];
                        }
                        for (int j = data.Length / 2; j < data.Length; j++)
                        {
                            data[j] = _predictionAlphasBetasData[savedAlphaBetasIndex + 1][j - data.Length / 2];
                        }

                        layer.weights = new BarracudaArrayFromManagedArray(data);

                        savedAlphaBetasIndex += 2;
                    }
                    // Else initialize scale/bias tensors of InstanceNormalization to default 1/0
                    else
                    {
                        int channels = lastConv.datasets[1].shape.channels;
                        layer.datasets = new Layer.DataSet[2];

                        layer.datasets[0].shape  = new TensorShape(1, 1, 1, channels);
                        layer.datasets[0].offset = 0;
                        layer.datasets[0].length = channels;

                        layer.datasets[1].shape  = new TensorShape(1, 1, 1, channels);
                        layer.datasets[1].offset = channels;
                        layer.datasets[1].length = channels;

                        float[] data = new float[channels * 2];
                        for (int j = 0; j < data.Length / 2; j++)
                        {
                            data[j] = 1.0f;
                        }
                        for (int j = data.Length / 2; j < data.Length; j++)
                        {
                            data[j] = 0.0f;
                        }
                        layer.weights = new BarracudaArrayFromManagedArray(data);
                    }
                }
            }

            // Remove Slice layers originally used to get alpha/beta tensors into Style_Network
            for (int i = 0; i < layerList.Count; i++)
            {
                Layer layer = layerList[i];
                if (layer.type == Layer.Type.StridedSlice)
                {
                    layerList.RemoveAt(i);
                    i--;
                }
            }

            // Fold Relu into instance normalisation
            Dictionary <string, string> reluToInstNorm = new Dictionary <string, string>();

            for (int i = 0; i < layerList.Count; i++)
            {
                Layer layer = layerList[i];
                if (layer.type == Layer.Type.Activation && layer.activation == Layer.Activation.Relu)
                {
                    if (layerList[i - 1].type == Layer.Type.Normalization)
                    {
                        layerList[i - 1].activation = layer.activation;
                        reluToInstNorm[layer.name]  = layerList[i - 1].name;
                        layerList.RemoveAt(i);
                        i--;
                    }
                }
            }
            for (int i = 0; i < layerList.Count; i++)
            {
                Layer layer = layerList[i];
                for (int j = 0; j < layer.inputs.Length; j++)
                {
                    if (reluToInstNorm.ContainsKey(layer.inputs[j]))
                    {
                        layer.inputs[j] = reluToInstNorm[layer.inputs[j]];
                    }
                }
            }

            // Feed first convolution directly with input (no need for normalisation from the model)
            string firstConvName = "StyleNetwork/conv1/convolution_conv1/convolution";
            int    firstConv     = FindLayerIndexByName(layerList, firstConvName);

            layerList[firstConv].inputs = new[] { _model.inputs[1].name };

            if (modelType.value == ModelType.Reference)
            {
                layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/add"));
                layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/add/y"));
                layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/normalized_contentFrames"));
                layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/normalized_contentFrames/y"));
                layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/sub"));
                layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalisation/sub/y"));
            }
            if (modelType.value == ModelType.RefBut32Channels)
            {
                layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalized_contentFrames"));
                layerList.RemoveAt(FindLayerIndexByName(layerList, "StyleNetwork/normalized_contentFrames/y"));
            }

            // Remove final model post processing, post process happen in tensor to texture instead
            int postAdd = FindLayerIndexByName(layerList, "StyleNetwork/clamp_0_255/add");

            layerList.RemoveRange(postAdd, 5);

            // Correct wrong output layer list
            _model.outputs = new List <string>()
            {
                layerList[postAdd - 1].name
            };

            _model.layers = layerList;
            Model.Input input = _model.inputs[1];
            input.shape[0] = 0;
            input.shape[1] = _rtHandle.rt.height;
            input.shape[2] = _rtHandle.rt.width;
            input.shape[3] = 3;
            _model.inputs  = new List <Model.Input> {
                _model.inputs[1]
            };
            //Create worker and execute it once at target resolution to prime all memory allocation (however in editor resolution can still change at runtime)
            _worker = WorkerFactory.CreateWorker(WorkerFactory.ValidateType(workerType.value), _model, debugModelLoading.value);
            Dictionary <string, Tensor> temp = new Dictionary <string, Tensor>();
            var inputTensor = new Tensor(input.shape, input.name);

            temp.Add("frame", inputTensor);
            _worker.Execute(temp);
            inputTensor.Dispose();

            Debug.Log("Style Transfer Model: \n" + _model.ToString());
        }
예제 #4
0
        // https://github.com/JasonMa0012/barracuda-style-transfer/blob/fb61d2d8172e3150f6ebbfb78443d0fe9def66db/Assets/BarracudaStyleTransfer/BarracudaStyleTransfer.cs#L575
        private void PrepareStylePrediction()
        {
            if (_styleTexture == null)
            {
                return;
            }

            Model        tempModel             = ModelLoader.Load(_nnModels[(int)modelType.value], debugModelLoading.value); //_model.ShallowCopy();
            List <Layer> predictionAlphasBetas = new List <Layer>();
            List <Layer> layerList             = new List <Layer>(tempModel.layers);

            // Remove Divide by 255, Unity textures are in [0, 1] already
            int firstDivide = FindLayerIndexByName(layerList, "Style_Prediction_Network/normalized_image");

            if (firstDivide < 0)
            {
                Debug.Log(0);
            }
            layerList[firstDivide + 1].inputs[0] = layerList[firstDivide].inputs[0];
            layerList.RemoveAt(firstDivide);

            // Pre-process network to get it to run and extract Style alpha/beta tensors
            Layer lastConv = null;

            for (int i = 0; i < layerList.Count; i++)
            {
                Layer layer = layerList[i];

                // Remove Mirror padding layers (not supported, TODO)
                if (layer.name.Contains("reflect_padding"))
                {
                    layerList[i + 1].inputs = layer.inputs;
                    layerList[i + 1].pad    = layer.pad.ToArray();
                    layerList.RemoveAt(i);
                    i--;
                    continue;
                }
                // Placeholder instance norm bias + scale tensors
                if (layer.type == Layer.Type.Conv2D || layer.type == Layer.Type.Conv2DTrans)
                {
                    lastConv = layer;
                }
                else if (layer.type == Layer.Type.Normalization)
                {
                    int channels = lastConv.datasets[1].shape.channels;
                    layer.datasets = new Layer.DataSet[2];

                    layer.datasets[0].shape  = new TensorShape(1, 1, 1, channels);
                    layer.datasets[0].offset = 0;
                    layer.datasets[0].length = channels;

                    layer.datasets[1].shape  = new TensorShape(1, 1, 1, channels);
                    layer.datasets[1].offset = channels;
                    layer.datasets[1].length = channels;

                    float[] data = new float[channels * 2];
                    for (int j = 0; j < data.Length / 2; j++)
                    {
                        data[j] = 1.0f;
                    }
                    for (int j = data.Length / 2; j < data.Length; j++)
                    {
                        data[j] = 0.0f;
                    }
                    layer.weights = new BarracudaArrayFromManagedArray(data);
                }

                if (layer.type != Layer.Type.StridedSlice && layer.name.Contains("StyleNetwork/"))
                {
                    layerList.RemoveAt(i);
                    i--;
                }

                if (layer.type == Layer.Type.StridedSlice)
                {
                    predictionAlphasBetas.Add(layer);
                }
            }
            tempModel.layers = layerList;
            // Run Style_Prediction_Network on given style
            var styleInput = new Tensor(_styleTexture);
            Dictionary <string, Tensor> temp = new Dictionary <string, Tensor>();

            temp.Add("frame", styleInput);
            temp.Add("style", styleInput);
            IWorker tempWorker = WorkerFactory.CreateWorker(WorkerFactory.ValidateType(workerType.value), tempModel, debugModelLoading.value);

            tempWorker.Execute(temp);

            // Store alpha/beta tensors from Style_Prediction_Network to feed into the run-time network
            _predictionAlphasBetasData = new List <float[]>();
            foreach (var layer in predictionAlphasBetas)
            {
                _predictionAlphasBetasData.Add(tempWorker.PeekOutput(layer.name).ToReadOnlyArray());
            }


            tempWorker.Dispose();
            styleInput.Dispose();

            Debug.Log("Style Prediction Model: \n" + tempModel.ToString());
        }
    private void PrepareStylePrediction()
    {
        //Try to load style tensors from disk first
        StyleData loadedData = Resources.Load <StyleData>(GetStyleResourceName());

        if (loadedData)
        {
            predictionAlphasBetasData = new List <float[]>();
            for (int i = 0; i < loadedData.layerData.Count; i++)
            {
                predictionAlphasBetasData.Add(loadedData.layerData[i].data);
            }
            Resources.UnloadAsset(loadedData);
            return;
        }

        //Tensors not found on disk, compute them (and eventually store them on disk)
        Model        tempModel             = ModelLoader.Load(nnModel, verbose);
        List <Layer> predictionAlphasBetas = new List <Layer>();
        List <Layer> layerList             = new List <Layer>(tempModel.layers);

        // Remove Divide by 255, Unity textures are in [0, 1] already
        int firstDivide = FindLayerIndexByName(layerList, "Style_Prediction_Network/normalized_image");

        layerList[firstDivide + 1].inputs[0] = layerList[firstDivide].inputs[0];
        layerList.RemoveAt(firstDivide);

        // Pre-process network to get it to run and extract Style alpha/beta tensors
        Layer lastConv = null;

        for (int i = 0; i < layerList.Count; i++)
        {
            Layer layer = layerList[i];

            // Remove Mirror padding layers (not supported, TODO)
            if (layer.name.Contains("reflect_padding"))
            {
                layerList[i + 1].inputs = layer.inputs;
                layerList[i + 1].pad    = layer.pad.ToArray();
                layerList.RemoveAt(i);
                i--;
                continue;
            }
            // Placeholder instance norm bias + scale tensors
            if (layer.type == Layer.Type.Conv2D || layer.type == Layer.Type.Conv2DTrans)
            {
                lastConv = layer;
            }
            else if (layer.type == Layer.Type.Normalization)
            {
                int channels = lastConv.datasets[1].shape.channels;
                layer.datasets = new Layer.DataSet[2];

                layer.datasets[0].shape  = new TensorShape(1, 1, 1, channels);
                layer.datasets[0].offset = 0;
                layer.datasets[0].length = channels;

                layer.datasets[1].shape  = new TensorShape(1, 1, 1, channels);
                layer.datasets[1].offset = channels;
                layer.datasets[1].length = channels;

                float[] data = new float[channels * 2];
                for (int j = 0; j < data.Length / 2; j++)
                {
                    data[j] = 1.0f;
                }
                for (int j = data.Length / 2; j < data.Length; j++)
                {
                    data[j] = 0.0f;
                }
                layer.weights = data;
            }

            if (layer.type != Layer.Type.StridedSlice && layer.name.Contains("StyleNetwork/"))
            {
                layerList.RemoveAt(i);
                i--;
            }

            if (layer.type == Layer.Type.StridedSlice)
            {
                predictionAlphasBetas.Add(layer);
            }
        }
        tempModel.layers = layerList;
        // Run Style_Prediction_Network on given style
        styleInput = new Tensor(StyleImage);
        CustomPinTensorFromTexture(styleInput);
        Dictionary <string, Tensor> temp = new Dictionary <string, Tensor>();

        temp.Add("frame", styleInput);
        temp.Add("style", styleInput);
        IWorker tempWorker = WorkerFactory.CreateWorker(WorkerFactory.ValidateType(internalSetup.workerType), tempModel, verbose);

        tempWorker.Execute(temp);

        // Store alpha/beta tensors from Style_Prediction_Network to feed into the run-time network
        predictionAlphasBetasData = new List <float[]>();
        for (int i = 0; i < predictionAlphasBetas.Count; i++)
        {
            Tensor O = tempWorker.PeekOutput(predictionAlphasBetas[i].name);
            predictionAlphasBetasData.Add(new float[O.length]);
            for (int j = 0; j < O.length; j++)
            {
                predictionAlphasBetasData[i][j] = O[j];
            }

            O.Dispose();
        }

        tempWorker.Dispose();

#if UNITY_EDITOR
        //Store to disk
        if (internalSetup.shouldSaveStyleTransferDataAsAsset)
        {
            SaveStyleTransferDataAsAsset();
        }
#endif
    }