/*public bool OnTouch(View v, MotionEvent e)
         * {
         *  int cols = mRgba.Cols();
         *  int rows = mRgba.Rows();
         *
         *  int xOffset = (mOpenCvCameraView.Width - cols) / 2;
         *  int yOffset = (mOpenCvCameraView.Height - rows) / 2;
         *
         *  int x = (int)e.GetX() - xOffset;
         *  int y = (int)e.GetY() - yOffset;
         *
         *  Log.Info(TAG, "Touch image coordinates: (" + x + ", " + y + ")");
         *
         *  if ((x < 0) || (y < 0) || (x > cols) || (y > rows)) return false;
         *
         *  Rect touchedRect = new Rect();
         *
         *  touchedRect.X = (x > 4) ? x - 4 : 0;
         *  touchedRect.Y = (y > 4) ? y - 4 : 0;
         *
         *  touchedRect.Width = (x + 4 < cols) ? x + 4 - touchedRect.X : cols - touchedRect.X;
         *  touchedRect.Height = (y + 4 < rows) ? y + 4 - touchedRect.Y : rows - touchedRect.Y;
         *
         *  Mat touchedRegionRgba = mRgba.Submat(touchedRect);
         *
         *  Mat touchedRegionHsv = new Mat();
         *  Imgproc.CvtColor(touchedRegionRgba, touchedRegionHsv, Imgproc.ColorRgb2hsvFull);
         *
         *  // Calculate average color of touched region
         *  mBlobColorHsv = Core.SumElems(touchedRegionHsv);
         *  int pointCount = touchedRect.Width * touchedRect.Height;
         *  for (int i = 0; i < mBlobColorHsv.Val.Count; i++)
         *      mBlobColorHsv.Val[i] /= pointCount;
         *
         *  mBlobColorRgba = ConvertScalarHsv2Rgba(mBlobColorHsv);
         *
         *  Log.Info(TAG, "Touched rgba color: (" + mBlobColorRgba.Val[0] + ", " + mBlobColorRgba.Val[1] +
         *          ", " + mBlobColorRgba.Val[2] + ", " + mBlobColorRgba.Val[3] + ")");
         *
         *  mDetector.SetHsvColor(mBlobColorHsv);
         *  Imgproc.Resize(mDetector.Spectrum, mSpectrum, SPECTRUM_SIZE);
         *
         *  mIsColorSelected = true;
         *
         *  touchedRegionRgba.Release();
         *  touchedRegionHsv.Release();
         *
         *  return false; // don't need subsequent touch events
         * }*/

        private void CreateAuxiliaryMats()
        {
            if (mGray.Empty())
            {
                return;
            }

            int rows = mGray.Rows();
            int cols = mGray.Cols();

            if (mZoomWindow == null)
            {
                mZoomWindow  = mRgba.Submat(rows / 2 + rows / 10, rows, cols / 2 + cols / 10, cols);
                mZoomWindow2 = mRgba.Submat(0, rows / 2 - rows / 10, cols / 2 + cols / 10, cols);
            }
        }
        public Mat OnCameraFrame(CameraBridgeViewBase.ICvCameraViewFrame inputFrame)
        {
            mRgba = inputFrame.Rgba();
            mGray = inputFrame.Gray();

            if (mAbsoluteFaceSize == 0)
            {
                int height = mGray.Rows();
                if (Math.Round(height * mRelativeFaceSize) > 0)
                {
                    mAbsoluteFaceSize = (int)Math.Round(height * mRelativeFaceSize);
                }
            }

            if (mZoomWindow == null || mZoomWindow2 == null)
            {
                CreateAuxiliaryMats();
            }

            MatOfRect faces = new MatOfRect();

            if (FACE != null)
            {
                FACE.DetectMultiScale(mGray, faces, 1.1, 2, 2, // TODO: objdetect.CV_HAAR_SCALE_IMAGE
                                      new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
            }

            Rect[] facesArray = faces.ToArray();
            for (int i = 0; i < facesArray.Length; i++)
            {
                Imgproc.Rectangle(mRgba, facesArray[i].Tl(), facesArray[i].Br(), FACE_RECT_COLOR, 3);
                xCenter = (facesArray[i].X + facesArray[i].Width + facesArray[i].X) / 2;
                yCenter = (facesArray[i].Y + facesArray[i].Y + facesArray[i].Height) / 2;
                Point center = new Point(xCenter, yCenter);

                Imgproc.Circle(mRgba, center, 10, new Scalar(255, 0, 0, 255), 3);

                /* --- NOT NEEDED
                 * Imgproc.putText(mRgba, "[" + center.X + "," + center.Y + "]",
                 *      new Point(center.X + 20, center.Y + 20),
                 *      Core.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar(255, 255, 255, 255));
                 */

                Rect r = facesArray[i];

                // compute the eye area
                Rect eyearea = new Rect(r.X + r.Width / 8,
                                        (int)(r.Y + (r.Height / 4.5)), r.Width - 2 * r.Width / 8, (int)(r.Height / 3.0));

                // split it
                Rect eyearea_right = new Rect(r.X + r.Width / 16, (int)(r.Y + (r.Height / 4.5)),
                                              (r.Width - 2 * r.Width / 16) / 2, (int)(r.Height / 3.0));

                Rect eyearea_left = new Rect(r.X + r.Width / 16 + (r.Width - 2 * r.Width / 16) / 2,
                                             (int)(r.Y + (r.Height / 4.5)), (r.Width - 2 * r.Width / 16) / 2, (int)(r.Height / 3.0));

                // draw the area - mGray is working grayscale mat, if you want to see area in rgb preview,
                // change mGray to mRgba
                Imgproc.Rectangle(mRgba, eyearea_left.Tl(), eyearea_left.Br(), new Scalar(255, 0, 0, 255), 2);
                Imgproc.Rectangle(mRgba, eyearea_right.Tl(), eyearea_right.Br(), new Scalar(255, 0, 0, 255), 2);

                if (learn_frames < 5)
                {
                    teplateR = get_template(EYE, eyearea_right, 24);
                    teplateL = get_template(EYE, eyearea_left, 24);
                    learn_frames++;
                }
                else
                {
                    // Learning finished, use the new templates for template matching
                    match_eye(eyearea_right, teplateR, method);
                    match_eye(eyearea_left, teplateL, method);
                }

                // cut eye areas and put them to zoom windows
                Imgproc.Resize(mRgba.Submat(eyearea_left), mZoomWindow2, mZoomWindow2.Size());
                Imgproc.Resize(mRgba.Submat(eyearea_right), mZoomWindow, mZoomWindow.Size());
            }

            /*
             * mRgba = inputFrame.Rgba();
             * Log.Info(TAG, "called OnCameraFrame");
             *
             * if (mIsColorSelected)
             * {
             *  mDetector.Process(mRgba);
             *  List<MatOfPoint> contours = mDetector.Contours;
             *  Log.Error(TAG, "Contours count: " + contours.Count);
             *  Imgproc.DrawContours(mRgba, contours, -1, CONTOUR_COLOR);
             *
             *  Mat colorLabel = mRgba.Submat(4, 68, 4, 68);
             *  colorLabel.SetTo(mBlobColorRgba);
             *
             *  Mat spectrumLabel = mRgba.Submat(4, 4 + mSpectrum.Rows(), 70, 70 + mSpectrum.Cols());
             *  mSpectrum.CopyTo(spectrumLabel);
             * }
             */

            return(mRgba);
        }
        private void match_eye(Rect area, Mat mTemplate, int type)
        {
            Point matchLoc;
            Mat   mROI        = mGray.Submat(area);
            int   result_cols = mROI.Cols() - mTemplate.Cols() + 1;
            int   result_rows = mROI.Rows() - mTemplate.Rows() + 1;

            // Check for bad template size
            if (mTemplate.Cols() == 0 || mTemplate.Rows() == 0)
            {
                return;
            }

            Mat mResult = new Mat(result_cols, result_rows, CvType.Cv8u);

            switch (type)
            {
            case TM_SQDIFF:
                Imgproc.MatchTemplate(mROI, mTemplate, mResult, Imgproc.TmSqdiff);
                break;

            case TM_SQDIFF_NORMED:
                Imgproc.MatchTemplate(mROI, mTemplate, mResult, Imgproc.TmSqdiffNormed);
                break;

            case TM_CCOEFF:
                Imgproc.MatchTemplate(mROI, mTemplate, mResult, Imgproc.TmCcoeff);
                break;

            case TM_CCOEFF_NORMED:
                Imgproc.MatchTemplate(mROI, mTemplate, mResult, Imgproc.TmCcoeffNormed);
                break;

            case TM_CCORR:
                Imgproc.MatchTemplate(mROI, mTemplate, mResult, Imgproc.TmCcorr);
                break;

            case TM_CCORR_NORMED:
                Imgproc.MatchTemplate(mROI, mTemplate, mResult, Imgproc.TmCcorrNormed);
                break;
            }

            Core.MinMaxLocResult mmres = Core.MinMaxLoc(mResult);

            // there is difference in matching methods - best match is max/min value
            if (type == TM_SQDIFF || type == TM_SQDIFF_NORMED)
            {
                matchLoc = mmres.MinLoc;
            }
            else
            {
                matchLoc = mmres.MaxLoc;
            }

            Point matchLoc_tx = new Point(matchLoc.X + area.X, matchLoc.Y + area.Y);
            Point matchLoc_ty = new Point(matchLoc.X + mTemplate.Cols() + area.X,
                                          matchLoc.Y + mTemplate.Rows() + area.Y);

            Imgproc.Rectangle(mRgba, matchLoc_tx, matchLoc_ty, new Scalar(255, 255, 0, 255));
            Rect rec = new Rect(matchLoc_tx, matchLoc_ty);
        }