public override void Dispose()
        {
            if (grayMat != null)
            {
                grayMat.Dispose();
                grayMat = null;
            }

            if (faces != null)
            {
                faces.Dispose();
            }

            if (debugMat != null)
            {
                debugMat.Dispose();
                debugMat = null;
            }

            if (debugTexture != null)
            {
                Texture2D.Destroy(debugTexture);
                debugTexture = null;
            }

            #if UNITY_WEBGL && !UNITY_EDITOR
            if (getFilePath_Coroutine != null)
            {
                StopCoroutine(getFilePath_Coroutine);
                ((IDisposable)getFilePath_Coroutine).Dispose();
            }
            #endif
        }
示例#2
0
        /// <summary>
        /// Raises the destroy event.
        /// </summary>
        public override void Dispose()
        {
            if (grayMat != null)
            {
                grayMat.Dispose();
            }

            if (faces != null)
            {
                faces.Dispose();
            }

            if (texture != null)
            {
                Texture2D.Destroy(texture);
                texture = null;
            }

#if UNITY_WEBGL && !UNITY_EDITOR
            foreach (var coroutine in coroutines)
            {
                StopCoroutine(coroutine);
                ((IDisposable)coroutine).Dispose();
            }
#endif
        }
示例#3
0
        /// <summary>
        /// Raises the webcam texture to mat helper disposed event.
        /// </summary>
        public void OnWebCamTextureToMatHelperDisposed()
        {
            Debug.Log("OnWebCamTextureToMatHelperDisposed");

            if (grayMat != null)
            {
                grayMat.Dispose();
            }

            if (effectsMat != null)
            {
                effectsMat.Dispose();
            }

            if (texture != null)
            {
                Texture2D.Destroy(texture);
                texture = null;
            }

            if (faces != null)
            {
                faces.Dispose();
            }
        }
示例#4
0
        /// <summary>
        /// Raises the web cam texture to mat helper disposed event.
        /// </summary>
        public void OnWebCamTextureToMatHelperDisposed()
        {
            Debug.Log("OnWebCamTextureToMatHelperDisposed");

            processingAreaMat.Dispose();
            grayMat.Dispose();
            faces.Dispose();
        }
示例#5
0
        /// <summary>
        /// Raises the web cam texture to mat helper disposed event.
        /// </summary>
        public void OnWebCamTextureToMatHelperDisposed()
        {
            Debug.Log("OnWebCamTextureToMatHelperDisposed");

            grayMat.Dispose();
            cascade.Dispose();
            faces.Dispose();
        }
        /// <summary>
        /// Raises the web cam texture to mat helper disposed event.
        /// </summary>
        public void OnWebCamTextureToMatHelperDisposed()
        {
            Debug.Log("OnWebCamTextureToMatHelperDisposed");

            if (grayMat != null)
            {
                grayMat.Dispose();
            }

            if (faces != null)
            {
                faces.Dispose();
            }
        }
        /// <summary>
        /// Raises the destroy event.
        /// </summary>
        void OnDestroy()
        {
            if (grayMat != null)
            {
                grayMat.Dispose();
            }

            if (faces != null)
            {
                faces.Dispose();
            }

            if (cascade != null)
            {
                cascade.Dispose();
            }
        }
示例#8
0
        public void OnWebCamTextureToMatHelperDisposed()
        {
            if (grayMat != null)
            {
                grayMat.Dispose();
            }

            if (texture != null)
            {
                Texture2D.Destroy(texture);
                texture = null;
            }

            if (faces != null)
            {
                faces.Dispose();
            }
        }
示例#9
0
        /// <summary>
        /// Postprocess the specified frame, outs and net.
        /// </summary>
        /// <param name="frame">Frame.</param>
        /// <param name="outs">Outs.</param>
        /// <param name="net">Net.</param>
        private void postprocess(Mat frame, List <Mat> outs, Net net)
        {
            string outLayerType = outBlobTypes[0];


            List <int>   classIdsList    = new List <int>();
            List <float> confidencesList = new List <float>();
            List <OpenCVForUnity.CoreModule.Rect> boxesList = new List <OpenCVForUnity.CoreModule.Rect>();

            if (net.getLayer(new DictValue(0)).outputNameToIndex("im_info") != -1)
            {
                // Faster-RCNN or R-FCN
                // Network produces output blob with a shape 1x1xNx7 where N is a number of
                // detections and an every detection is a vector of values
                // [batchId, classId, confidence, left, top, right, bottom]

                if (outs.Count == 1)
                {
                    outs[0] = outs[0].reshape(1, (int)outs[0].total() / 7);

                    //Debug.Log ("outs[i].ToString() " + outs [0].ToString ());

                    float[] data = new float[7];

                    for (int i = 0; i < outs[0].rows(); i++)
                    {
                        outs[0].get(i, 0, data);

                        float confidence = data[2];

                        if (confidence > confThreshold)
                        {
                            int class_id = (int)(data[1]);

                            int left   = (int)(data[3] * frame.cols());
                            int top    = (int)(data[4] * frame.rows());
                            int right  = (int)(data[5] * frame.cols());
                            int bottom = (int)(data[6] * frame.rows());
                            int width  = right - left + 1;
                            int height = bottom - top + 1;

                            classIdsList.Add((int)(class_id) - 0);
                            confidencesList.Add((float)confidence);
                            boxesList.Add(new OpenCVForUnity.CoreModule.Rect(left, top, width, height));
                        }
                    }
                }
            }
            else if (outLayerType == "DetectionOutput")
            {
                // Network produces output blob with a shape 1x1xNx7 where N is a number of
                // detections and an every detection is a vector of values
                // [batchId, classId, confidence, left, top, right, bottom]

                if (outs.Count == 1)
                {
                    outs[0] = outs[0].reshape(1, (int)outs[0].total() / 7);

                    //Debug.Log ("outs[i].ToString() " + outs [0].ToString ());

                    float[] data = new float[7];

                    for (int i = 0; i < outs[0].rows(); i++)
                    {
                        outs[0].get(i, 0, data);

                        float confidence = data[2];

                        if (confidence > confThreshold)
                        {
                            int class_id = (int)(data[1]);

                            int left   = (int)(data[3] * frame.cols());
                            int top    = (int)(data[4] * frame.rows());
                            int right  = (int)(data[5] * frame.cols());
                            int bottom = (int)(data[6] * frame.rows());
                            int width  = right - left + 1;
                            int height = bottom - top + 1;

                            classIdsList.Add((int)(class_id) - 0);
                            confidencesList.Add((float)confidence);
                            boxesList.Add(new OpenCVForUnity.CoreModule.Rect(left, top, width, height));
                        }
                    }
                }
            }
            else if (outLayerType == "Region")
            {
                for (int i = 0; i < outs.Count; ++i)
                {
                    // Network produces output blob with a shape NxC where N is a number of
                    // detected objects and C is a number of classes + 4 where the first 4
                    // numbers are [center_x, center_y, width, height]

                    //Debug.Log ("outs[i].ToString() "+outs[i].ToString());

                    float[] positionData   = new float[5];
                    float[] confidenceData = new float[outs[i].cols() - 5];

                    for (int p = 0; p < outs[i].rows(); p++)
                    {
                        outs[i].get(p, 0, positionData);

                        outs[i].get(p, 5, confidenceData);

                        int   maxIdx     = confidenceData.Select((val, idx) => new { V = val, I = idx }).Aggregate((max, working) => (max.V > working.V) ? max : working).I;
                        float confidence = confidenceData[maxIdx];

                        if (confidence > confThreshold)
                        {
                            int centerX = (int)(positionData[0] * frame.cols());
                            int centerY = (int)(positionData[1] * frame.rows());
                            int width   = (int)(positionData[2] * frame.cols());
                            int height  = (int)(positionData[3] * frame.rows());
                            int left    = centerX - width / 2;
                            int top     = centerY - height / 2;

                            classIdsList.Add(maxIdx);
                            confidencesList.Add((float)confidence);
                            boxesList.Add(new OpenCVForUnity.CoreModule.Rect(left, top, width, height));
                        }
                    }
                }
            }
            else
            {
                Debug.Log("Unknown output layer type: " + outLayerType);
            }


            MatOfRect boxes = new MatOfRect();

            boxes.fromList(boxesList);

            MatOfFloat confidences = new MatOfFloat();

            confidences.fromList(confidencesList);


            MatOfInt indices = new MatOfInt();

            Dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);

            //Debug.Log ("indices.dump () "+indices.dump ());
            //Debug.Log ("indices.ToString () "+indices.ToString());

            for (int i = 0; i < indices.total(); ++i)
            {
                int idx = (int)indices.get(i, 0)[0];
                OpenCVForUnity.CoreModule.Rect box = boxesList[idx];
                drawPred(classIdsList[idx], confidencesList[idx], box.x, box.y,
                         box.x + box.width, box.y + box.height, frame);
            }

            indices.Dispose();
            boxes.Dispose();
            confidences.Dispose();
        }
        private void Run()
        {
            //if true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.
            Utils.setDebugMode(true);


            Mat frame = Imgcodecs.imread(scenetext01_jpg_filepath);

            #if !UNITY_WSA_10_0
            if (frame.empty())
            {
                Debug.LogError("text/scenetext01.jpg is not loaded.Please copy from “OpenCVForUnity/StreamingAssets/text/” to “Assets/StreamingAssets/” folder. ");
            }
            #endif

            Mat binaryMat = new Mat();
            Mat maskMat   = new Mat();


            List <MatOfPoint> regions = new List <MatOfPoint> ();

            ERFilter er_filter1 = Text.createERFilterNM1(trained_classifierNM1_xml_filepath, 8, 0.00015f, 0.13f, 0.2f, true, 0.1f);

            ERFilter er_filter2 = Text.createERFilterNM2(trained_classifierNM2_xml_filepath, 0.5f);


            Mat transition_p = new Mat(62, 62, CvType.CV_64FC1);
            //            string filename = "OCRHMM_transitions_table.xml";
            //            FileStorage fs(filename, FileStorage::READ);
            //            fs["transition_probabilities"] >> transition_p;
            //            fs.release();

            //Load TransitionProbabilitiesData.
            transition_p.put(0, 0, GetTransitionProbabilitiesData(OCRHMM_transitions_table_xml_filepath));

            Mat           emission_p = Mat.eye(62, 62, CvType.CV_64FC1);
            string        voc        = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            OCRHMMDecoder decoder    = OCRHMMDecoder.create(
                OCRHMM_knn_model_data_xml_gz_filepath,
                voc, transition_p, emission_p);

            //Text Detection
            Imgproc.cvtColor(frame, frame, Imgproc.COLOR_BGR2RGB);
            Imgproc.cvtColor(frame, binaryMat, Imgproc.COLOR_RGB2GRAY);
            Imgproc.threshold(binaryMat, binaryMat, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
            Core.absdiff(binaryMat, new Scalar(255), maskMat);


            Text.detectRegions(binaryMat, er_filter1, er_filter2, regions);
            Debug.Log("regions.Count " + regions.Count);


            MatOfRect groups_rects           = new MatOfRect();
            List <OpenCVForUnity.Rect> rects = new List <OpenCVForUnity.Rect> ();
            Text.erGrouping(frame, binaryMat, regions, groups_rects);


            for (int i = 0; i < regions.Count; i++)
            {
                regions [i].Dispose();
            }
            regions.Clear();


            rects.AddRange(groups_rects.toList());

            groups_rects.Dispose();


            //Text Recognition (OCR)

            List <Mat> detections = new List <Mat> ();

            for (int i = 0; i < (int)rects.Count; i++)
            {
                Mat group_img = new Mat();
                maskMat.submat(rects [i]).copyTo(group_img);
                Core.copyMakeBorder(group_img, group_img, 15, 15, 15, 15, Core.BORDER_CONSTANT, new Scalar(0));
                detections.Add(group_img);
            }

            Debug.Log("detections.Count " + detections.Count);


            //#Visualization
            for (int i = 0; i < rects.Count; i++)
            {
                Imgproc.rectangle(frame, new Point(rects [i].x, rects [i].y), new Point(rects [i].x + rects [i].width, rects [i].y + rects [i].height), new Scalar(255, 0, 0), 2);
                Imgproc.rectangle(frame, new Point(rects [i].x, rects [i].y), new Point(rects [i].x + rects [i].width, rects [i].y + rects [i].height), new Scalar(255, 255, 255), 1);

                string output = decoder.run(detections [i], 0);
                if (!string.IsNullOrEmpty(output))
                {
                    Debug.Log("output " + output);
                    Imgproc.putText(frame, output, new Point(rects [i].x, rects [i].y), Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(0, 0, 255), 1, Imgproc.LINE_AA, false);
                }
            }


            Texture2D texture = new Texture2D(frame.cols(), frame.rows(), TextureFormat.RGBA32, false);

            Utils.matToTexture2D(frame, texture);

//            Texture2D texture = new Texture2D (detections [0].cols (), detections [0].rows (), TextureFormat.RGBA32, false);
//
//            Utils.matToTexture2D (detections [0], texture);

            gameObject.GetComponent <Renderer> ().material.mainTexture = texture;


            for (int i = 0; i < detections.Count; i++)
            {
                detections [i].Dispose();
            }
            binaryMat.Dispose();
            maskMat.Dispose();

            Utils.setDebugMode(false);
        }
示例#11
0
        /// <summary>
        /// Postprocess the specified frame, outs and net.
        /// </summary>
        /// <param name="frame">Frame.</param>
        /// <param name="outs">Outs.</param>
        /// <param name="net">Net.</param>
        private void postprocess(Mat frame, List <Mat> outs, Net net)
        {
            string outLayerType = outBlobTypes[0];


            List <int>   classIdsList    = new List <int>();
            List <float> confidencesList = new List <float>();
            List <OpenCVForUnity.CoreModule.Rect> boxesList = new List <OpenCVForUnity.CoreModule.Rect>();

            if (outLayerType == "Region")
            {
                for (int i = 0; i < outs.Count; ++i)
                {
                    // Network produces output blob with a shape NxC where N is a number of
                    // detected objects and C is a number of classes + 4 where the first 4
                    // numbers are [center_x, center_y, width, height]

                    //Debug.Log("outs[i].ToString() " + outs[i].ToString());

                    float[] positionData   = new float[5];
                    float[] confidenceData = new float[outs[i].cols() - 5];

                    for (int p = 0; p < outs[i].rows(); p++)
                    {
                        outs[i].get(p, 0, positionData);

                        outs[i].get(p, 5, confidenceData);

                        int   maxIdx     = confidenceData.Select((val, idx) => new { V = val, I = idx }).Aggregate((max, working) => (max.V > working.V) ? max : working).I;
                        float confidence = confidenceData[maxIdx];

                        if (confidence > confThreshold)
                        {
                            int centerX = (int)(positionData[0] * frame.cols());
                            int centerY = (int)(positionData[1] * frame.rows());
                            int width   = (int)(positionData[2] * frame.cols());
                            int height  = (int)(positionData[3] * frame.rows());
                            int left    = centerX - width / 2;
                            int top     = centerY - height / 2;

                            classIdsList.Add(maxIdx);
                            confidencesList.Add((float)confidence);
                            boxesList.Add(new OpenCVForUnity.CoreModule.Rect(left, top, width, height));
                        }
                    }
                }
            }
            else
            {
                Debug.Log("Unknown output layer type: " + outLayerType);
            }


            MatOfRect boxes = new MatOfRect();

            boxes.fromList(boxesList);

            MatOfFloat confidences = new MatOfFloat();

            confidences.fromList(confidencesList);


            MatOfInt indices = new MatOfInt();

            Dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
            //Check the Language selected
            switch (menuVariables.GetLanguage())
            {
            case "EN":
                vocOffset = 0;
                break;

            case "ES":
                vocOffset = 80;
                break;

            case "FR":
                vocOffset = 160;
                break;

            case "DE":
                vocOffset = 240;
                break;

            case "IT":
                vocOffset = 320;
                break;

            default:
                vocOffset = 0;
                break;
            }

            //Draw the bouding box only if its in the center of the image (On Cursor)
            for (int i = 0; i < indices.total(); ++i)
            {
                int idx = (int)indices.get(i, 0)[0];
                OpenCVForUnity.CoreModule.Rect box = boxesList[idx];
                if (isOnCursor(box, cursorObject.GetComponent <Cursor>()))
                {
                    drawPred(vocOffset + classIdsList[idx], confidencesList[idx], box.x, box.y,
                             box.x + box.width, box.y + box.height, frame);
                    wordDisplay.text = classNames[classIdsList[idx]];
                    //Update the text summarizing the object encountered
                    if (!vocIDList.Contains(classIdsList[idx]))
                    {
                        //Update the vocabulary learned
                        vocIDList.Add(classIdsList[idx]);
                        EnglishText.text += "\n" + classNames[classIdsList[idx]] + "\n";
                        SpanishText.text += "\n" + classNames[80 + classIdsList[idx]] + "\n";
                        FrenchText.text  += "\n" + classNames[160 + classIdsList[idx]] + "\n";
                        GermanText.text  += "\n" + classNames[240 + classIdsList[idx]] + "\n";
                        ItalianText.text += "\n" + classNames[320 + classIdsList[idx]] + "\n";
                    }
                }
            }


            indices.Dispose();
            boxes.Dispose();
            confidences.Dispose();
        }
示例#12
0
        /// <summary>
        /// Process
        /// </summary>
        /// <returns></returns>
        private async void Process()
        {
            float DOWNSCALE_RATIO = 1.0f;

            while (true)
            {
                // Check TaskCancel
                if (tokenSource.Token.IsCancellationRequested)
                {
                    break;
                }

                rgbaMat = webCamTextureToMatHelper.GetMat();
                // Debug.Log ("rgbaMat.ToString() " + rgbaMat.ToString ());

                Mat downScaleRgbaMat = null;
                DOWNSCALE_RATIO = 1.0f;
                if (enableDownScale)
                {
                    downScaleRgbaMat = imageOptimizationHelper.GetDownScaleMat(rgbaMat);
                    DOWNSCALE_RATIO  = imageOptimizationHelper.downscaleRatio;
                }
                else
                {
                    downScaleRgbaMat = rgbaMat;
                    DOWNSCALE_RATIO  = 1.0f;
                }
                Imgproc.cvtColor(downScaleRgbaMat, bgrMat, Imgproc.COLOR_RGBA2BGR);



                await Task.Run(() =>
                {
                    // detect faces on the downscale image
                    if (!enableSkipFrame || !imageOptimizationHelper.IsCurrentFrameSkipped())
                    {
                        if (net == null)
                        {
                            Imgproc.putText(rgbaMat, "model file is not loaded.", new Point(5, rgbaMat.rows() - 30), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar(255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
                            Imgproc.putText(rgbaMat, "Please read console message.", new Point(5, rgbaMat.rows() - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar(255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
                        }
                        else
                        {
                            // Create a 4D blob from a frame.
                            Size inpSize = new Size(inpWidth > 0 ? inpWidth : bgrMat.cols(),
                                                    inpHeight > 0 ? inpHeight : bgrMat.rows());
                            Mat blob = Dnn.blobFromImage(bgrMat, scale, inpSize, mean, swapRB, false);


                            // Run a model.
                            net.setInput(blob);

                            if (net.getLayer(new DictValue(0)).outputNameToIndex("im_info") != -1)
                            {  // Faster-RCNN or R-FCN
                                Imgproc.resize(bgrMat, bgrMat, inpSize);
                                Mat imInfo = new Mat(1, 3, CvType.CV_32FC1);
                                imInfo.put(0, 0, new float[] {
                                    (float)inpSize.height,
                                    (float)inpSize.width,
                                    1.6f
                                });
                                net.setInput(imInfo, "im_info");
                            }


                            TickMeter tm = new TickMeter();
                            tm.start();

                            List <Mat> outs = new List <Mat>();
                            net.forward(outs, outBlobNames);

                            tm.stop();
                            //                    Debug.Log ("Inference time, ms: " + tm.getTimeMilli ());


                            postprocess(bgrMat, outs, net);

                            for (int i = 0; i < outs.Count; i++)
                            {
                                outs[i].Dispose();
                            }
                            blob.Dispose();


                            if (enableDownScale)
                            {
                                for (int i = 0; i < _boxesList.Count; ++i)
                                {
                                    var rect      = _boxesList[i];
                                    _boxesList[i] = new OpenCVForUnity.CoreModule.Rect(
                                        (int)(rect.x * DOWNSCALE_RATIO),
                                        (int)(rect.y * DOWNSCALE_RATIO),
                                        (int)(rect.width * DOWNSCALE_RATIO),
                                        (int)(rect.height * DOWNSCALE_RATIO));
                                }
                            }
                        }


                        //Imgproc.rectangle(rgbaMat, new Point(0, 0), new Point(rgbaMat.width(), rgbaMat.height()), new Scalar(0, 0, 0, 0), -1);


                        MatOfRect boxes = new MatOfRect();
                        boxes.fromList(_boxesList);

                        MatOfFloat confidences = new MatOfFloat();
                        confidences.fromList(_confidencesList);


                        MatOfInt indices = new MatOfInt();
                        Dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);

                        //            Debug.Log ("indices.dump () "+indices.dump ());
                        //            Debug.Log ("indices.ToString () "+indices.ToString());

                        for (int i = 0; i < indices.total(); ++i)
                        {
                            int idx = (int)indices.get(i, 0)[0];
                            OpenCVForUnity.CoreModule.Rect box = _boxesList[idx];
                            drawPred(_classIdsList[idx], _confidencesList[idx], box.x, box.y,
                                     box.x + box.width, box.y + box.height, rgbaMat);
                        }

                        indices.Dispose();
                        boxes.Dispose();
                        confidences.Dispose();
                    }
                });



                Utils.fastMatToTexture2D(rgbaMat, texture);


                Thread.Sleep(10);
            }
        }
示例#13
0
        /// <summary>
        /// Scanning the specified frame, outs and net.
        /// </summary>
        /// <param name="frame">Frame.</param>
        /// <param name="outs">Outs.</param>
        /// <param name="net">Net.</param>
        private void postscan(Mat frame, List <Mat> outs, Net net)
        {
            string       outLayerType    = outBlobTypes[0];
            List <int>   classIdsList    = new List <int>();
            List <float> confidencesList = new List <float>();
            List <OpenCVForUnity.CoreModule.Rect> boxesList = new List <OpenCVForUnity.CoreModule.Rect>();

            if (outLayerType == "Region")
            {
                for (int i = 0; i < outs.Count; ++i)
                {
                    // Network produces output blob with a shape NxC where N is a number of
                    // detected objects and C is a number of classes + 4 where the first 4
                    // numbers are [center_x, center_y, width, height]

                    //Debug.Log("outs[i].ToString() " + outs[i].ToString());

                    float[] positionData   = new float[5];
                    float[] confidenceData = new float[outs[i].cols() - 5];

                    for (int p = 0; p < outs[i].rows(); p++)
                    {
                        outs[i].get(p, 0, positionData);

                        outs[i].get(p, 5, confidenceData);

                        int   maxIdx     = confidenceData.Select((val, idx) => new { V = val, I = idx }).Aggregate((max, working) => (max.V > working.V) ? max : working).I;
                        float confidence = confidenceData[maxIdx];

                        if (confidence > confThreshold)
                        {
                            int centerX = (int)(positionData[0] * frame.cols());
                            int centerY = (int)(positionData[1] * frame.rows());
                            int width   = (int)(positionData[2] * frame.cols());
                            int height  = (int)(positionData[3] * frame.rows());
                            int left    = centerX - width / 2;
                            int top     = centerY - height / 2;

                            classIdsList.Add(maxIdx);
                            confidencesList.Add((float)confidence);
                            boxesList.Add(new OpenCVForUnity.CoreModule.Rect(left, top, width, height));
                        }
                    }
                }
            }
            else
            {
                Debug.Log("Unknown output layer type: " + outLayerType);
            }


            MatOfRect boxes = new MatOfRect();

            boxes.fromList(boxesList);

            MatOfFloat confidences = new MatOfFloat();

            confidences.fromList(confidencesList);


            MatOfInt indices = new MatOfInt();

            Dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);

            //for-loop for the mini game - if a new class appears, add it to the
            for (int i = 0; i < indices.total(); ++i)
            {
                int idx = (int)indices.get(i, 0)[0];

                if (!minigameList.Contains(classIdsList[idx]))
                {
                    Debug.Log(classNames[classIdsList[idx]]);
                    minigameList.Add(classIdsList[idx]);
                    if (minigameList.Count() > 1)
                    {
                        wordDisplay.text = minigameList.Count().ToString() + " words";
                    }
                    else
                    {
                        wordDisplay.text = minigameList.Count().ToString() + " word";
                    }
                }
            }
            indices.Dispose();
            boxes.Dispose();
            confidences.Dispose();
        }
        // Update is called once per frame
        void Update()
        {
            if (webCamTextureToMatHelper.IsPlaying() && webCamTextureToMatHelper.DidUpdateThisFrame())
            {
                Mat rgbaMat = webCamTextureToMatHelper.GetMat();

                Imgproc.cvtColor(rgbaMat, rgbMat, Imgproc.COLOR_RGBA2RGB);


                /*Text Detection*/
                Imgproc.cvtColor(rgbMat, binaryMat, Imgproc.COLOR_RGB2GRAY);
                Imgproc.threshold(binaryMat, binaryMat, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
                Core.absdiff(binaryMat, new Scalar(255), maskMat);


                List <MatOfPoint> regions = new List <MatOfPoint> ();


                OpenCVForUnity.Text.detectRegions(binaryMat, er_filter1, er_filter2, regions);

//                Debug.Log ("regions.Count " + regions.Count);

                MatOfRect groups_rects           = new MatOfRect();
                List <OpenCVForUnity.Rect> rects = new List <OpenCVForUnity.Rect> ();
                if (regions.Count > 0)
                {
                    OpenCVForUnity.Text.erGrouping(rgbMat, binaryMat, regions, groups_rects);
                }


                for (int i = 0; i < regions.Count; i++)
                {
                    regions [i].Dispose();
                }
                regions.Clear();

                rects.AddRange(groups_rects.toList());

                groups_rects.Dispose();



                /*Text Recognition (OCR)*/

                List <Mat> detections = new List <Mat> ();

                for (int i = 0; i < (int)rects.Count; i++)
                {
                    Mat group_img = new Mat();

                    maskMat.submat(rects [i]).copyTo(group_img);
                    Core.copyMakeBorder(group_img, group_img, 15, 15, 15, 15, Core.BORDER_CONSTANT, new Scalar(0));
                    detections.Add(group_img);
                }

//                Debug.Log ("detections.Count " + detections.Count);

//                Debug.Log ("rects.Count " + rects.Count);

                //#Visualization
                for (int i = 0; i < rects.Count; i++)
                {
                    Imgproc.rectangle(rgbaMat, new Point(rects [i].x, rects [i].y), new Point(rects [i].x + rects [i].width, rects [i].y + rects [i].height), new Scalar(255, 0, 0, 255), 2);
                    Imgproc.rectangle(rgbaMat, new Point(rects [i].x, rects [i].y), new Point(rects [i].x + rects [i].width, rects [i].y + rects [i].height), new Scalar(255, 255, 255, 255), 1);

                    Imgproc.putText(rgbaMat, "" + i, new Point(rects [i].x, rects [i].y), Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(255, 0, 0, 255), 1, Imgproc.LINE_AA, false);
                }


                for (int i = 0; i < detections.Count; i++)
                {
                    string output = decoder.run(detections [i], 0);
                    Debug.Log("output " + output);
                    if (string.IsNullOrEmpty(output))
                    {
                        Debug.LogError("IsNullOrEmpty output " + output);
                    }
                    else
                    {
                        Imgproc.putText(rgbaMat, "  " + output, new Point(rects [i].x, rects [i].y), Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(255, 0, 0, 255), 1, Imgproc.LINE_AA, false);
                    }
                }

                for (int i = 0; i < detections.Count; i++)
                {
                    detections [i].Dispose();
                }
                detections.Clear();


                Imgproc.putText(rgbaMat, "W:" + rgbaMat.width() + " H:" + rgbaMat.height() + " SO:" + Screen.orientation, new Point(5, rgbaMat.rows() - 10), Core.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(255, 255, 255, 255), 2, Imgproc.LINE_AA, false);

                Utils.matToTexture2D(rgbaMat, texture, webCamTextureToMatHelper.GetBufferColors());
            }
        }