Beispiel #1
0
        public Rectangle[] Detect(Mat mat, byte[] buffer)
        {
            var frameWidth  = mat.Width;
            var frameHeight = mat.Height;

            //using var blob = CvDnn.BlobFromImage(mat, 1.0, new OpenCvSharp.Size(300, 300), new OpenCvSharp.Scalar(104, 117, 123), false, false);
            using var blob = CvDnn.BlobFromImage(mat, 1.0 / Mean, new OpenCvSharp.Size(300, 300), new OpenCvSharp.Scalar(Mean), true, false);
            Net.SetInput(blob);
            using var detections   = Net.Forward();
            using var detectionMat = new Mat(detections.Size(2), detections.Size(3), MatType.CV_32F, detections.Ptr(0));
            var       bestConfidence = 0.0;
            Rectangle?candidate      = null;

            for (var i = 0; i < detectionMat.Rows; i++)
            {
                var confidence = detectionMat.At <float>(i, 2);
                if ((confidence > 0.5) && (confidence > bestConfidence))
                {
                    var left   = (int)(detectionMat.At <float>(i, 3) * frameWidth);
                    var top    = (int)(detectionMat.At <float>(i, 4) * frameHeight);
                    var right  = (int)(detectionMat.At <float>(i, 5) * frameWidth);
                    var bottom = (int)(detectionMat.At <float>(i, 6) * frameHeight);
                    candidate = new Rectangle(left, top, right - left, bottom - top);
                }
            }

            if (candidate != null)
            {
                return(new Rectangle[] { candidate.Value });
            }
            else
            {
                return(Array.Empty <Rectangle>());
            }
        }
        /// <summary>
        /// Find the divided index for a histogram, used in the dynamic threshiolding algorithms
        /// </summary>
        /// <param name="histogram">input histogram, of type OpenCvSharp.Mat</param>
        /// <param name="histCalculation">histogram calculation direction, of type Entities.Enums.HistogramCalculation</param>
        /// <param name="maxHistValue">maximum value in histogram, of type double</param>
        /// <param name="maxHistIndex">index of maximum value in histogram, of type int</param>
        /// <returns>division value, of type int</returns>
        public int FindHistogramDividedIndex(Mat histogram, Enums.HistogramCalculation histCalculation, double maxHistValue, int maxHistIndex)
        {
            if (histCalculation == Enums.HistogramCalculation.Normal)
            {
                // Divided threshold value will me maximum threshold value divided by predefined value (THRESH_DIVIDE_VAL)
                for (int dividedValIdx = maxHistIndex; dividedValIdx < TASettings.HIST_BINS_COUNT; dividedValIdx++)
                {
                    if (histogram.At <float>(dividedValIdx) <= ((float)maxHistValue / TASettings.THRESH_DIVIDE_VAL))
                    {
                        return(dividedValIdx);
                    }
                }

                // Return maximum histogram value if no other value was found
                return((int)maxHistValue);
            }
            else
            {
                for (int dividedValIdx = maxHistIndex; dividedValIdx >= 0; dividedValIdx--)
                {
                    if (histogram.At <float>(dividedValIdx) <= ((float)maxHistValue / TASettings.THRESH_DIVIDE_VAL))
                    {
                        return(dividedValIdx);
                    }
                }

                // Return maximum histogram value if no other value was found
                return((int)maxHistValue);
            }
        }
Beispiel #3
0
        /// <summary>
        /// center image
        /// </summary>
        /// <param name="img"></param>
        static void MoveToCenter(Mat img)
        {
            int left = img.Rows - 1, right = 0, top = img.Rows - 1, buttom = 0;

            for (var i = 0; i < img.Rows; i++)
            {
                for (var j = 0; j < img.Cols; j++)
                {
                    if (img.At <byte>(i, j) != 0)
                    {
                        left  = Math.Min(left, j);
                        right = Math.Max(right, j);

                        top    = Math.Min(top, i);
                        buttom = Math.Max(buttom, i);
                    }
                }
            }
            int dx = (right + left - img.Rows) / 2, dy = (buttom + top - img.Cols) / 2;
            Mat dst = Mat.Zeros(img.Rows, img.Cols, img.Type());

            for (var i = 0; i < img.Rows; i++)
            {
                for (var j = 0; j < img.Cols; j++)
                {
                    if (i + dx < img.Rows && i + dx >= 0 && j + dy < img.Cols && j + dy >= 0)
                    {
                        dst.Set(i + dx, j + dy, img.At <byte>(i, j));
                    }
                }
            }
            dst.CopyTo(img);
        }
    private Mat mergeImageLayer(Mat buttomLayer, Mat upperLayer)
    {
        Mat result = new Mat(350, 450, MatType.CV_8UC3, Scalar.LightGray);

        Cv2.CopyTo(upperLayer, result);
        for (int row = 0; row < buttomLayer.Rows; row++)
        {
            for (int col = 0; col < buttomLayer.Cols; col++)
            {
                Debug.Log(row + ": " + col);
                int blue  = buttomLayer.At <Vec3b>(row, col).Item0;
                int green = buttomLayer.At <Vec3b>(row, col).Item1;
                int red   = buttomLayer.At <Vec3b>(row, col).Item2; // RGB value
                if (blue == 255 && green == 255 && red == 255)      // white
                {
                    int blue2  = upperLayer.At <Vec3b>(row, col).Item0;
                    int green2 = upperLayer.At <Vec3b>(row, col).Item1;
                    int red2   = upperLayer.At <Vec3b>(row, col).Item2;
                    if (blue2 == 211 && green2 == 211 && red2 == 211) // light-grey
                    {
                        result.Set <Vec3b>(row, col, new Vec3b(255, 255, 255));
                    }
                }
                else if (blue == 144 && green == 238 && red == 144) // light-green
                {
                    result.Set <Vec3b>(row, col, new Vec3b(144, 238, 144));
                }
            }
        }
        return(result);
    }
Beispiel #5
0
 private Mat mergeImageLayer(Mat buttomLayer, Mat upperLayer)
 {
     //Cv2.ImWrite(Application.persistentDataPath + "/buttom.png", buttomLayer);
     Cv2.CopyTo(upperLayer, result);
     Parallel.For(0, buttomLayer.Rows, row =>
     {
         for (int col = 0; col < buttomLayer.Cols; col++)
         {
             int blue  = buttomLayer.At <Vec3b>(row, col).Item0;
             int green = buttomLayer.At <Vec3b>(row, col).Item1;
             int red   = buttomLayer.At <Vec3b>(row, col).Item2; // RGB value
             if (blue == 255 && green == 255 && red == 255)      // white
             {
                 int blue2  = upperLayer.At <Vec3b>(row, col).Item0;
                 int green2 = upperLayer.At <Vec3b>(row, col).Item1;
                 int red2   = upperLayer.At <Vec3b>(row, col).Item2;
                 if (blue2 == 211 && green2 == 211 && red2 == 211) // light-grey
                 {
                     result.Set <Vec3b>(row, col, new Vec3b(255, 255, 255));
                 }
             }
             else if (blue == 144 && green == 238 && red == 144) // light-green
             {
                 int blue2  = upperLayer.At <Vec3b>(row, col).Item0;
                 int green2 = upperLayer.At <Vec3b>(row, col).Item1;
                 int red2   = upperLayer.At <Vec3b>(row, col).Item2;
                 result.Set <Vec3b>(row, col, new Vec3b(144, 238, 144));
             }
         }
     });
     return(result);
 }
Beispiel #6
0
        private void Divide(Mat img, List <Point> points, out Mat left, out Mat right)
        {
            var pointsL = new List <Point>(new Point[] { new Point(0, img.Height) });
            var pointsR = new List <Point>(new Point[] { new Point(img.Width, img.Height) });

            foreach (var p in points)
            {
                if (p.X < img.Width / 2 && p.Y > img.Height / 4)
                {
                    pointsL.Add(p);
                }
                else if (p.X > img.Width / 2 && p.Y > img.Height / 4)
                {
                    pointsR.Add(p);
                }
            }
            left  = new Mat(pointsL.Count, 2, MatType.CV_32F);
            right = new Mat(pointsR.Count, 2, MatType.CV_32F);
            for (int i = 0; i < pointsL.Count; i++)
            {
                left.At <float>(i, 0) = pointsL[i].X;
                left.At <float>(i, 1) = pointsL[i].Y;
                //Cv2.Circle(img, pointsL[i], 3, green, 4);
            }
            for (int i = 0; i < pointsR.Count; i++)
            {
                right.At <float>(i, 0) = pointsR[i].X;
                right.At <float>(i, 1) = pointsR[i].Y;
                //Cv2.Circle(img, pointsR[i], 3, green, 4);
            }
        }
Beispiel #7
0
        //去边框
        public static Mat ClearBorder(Mat threshold)
        {
            int rows = threshold.Rows;
            int cols = threshold.Cols;

            int noJumpCountThresh = (int)(0.15f * cols);

            Mat border = new Mat(rows, 1, MatType.CV_8UC1);

            for (int rowIndex = 0; rowIndex < rows; rowIndex++)
            {
                int  noJumpCount = 0;
                byte isBorder    = 0;

                for (int colIndex = 1; colIndex < cols - 7; colIndex++)
                {
                    if (threshold.At <byte>(rowIndex, colIndex) == threshold.At <byte>(rowIndex, colIndex + 1))
                    {
                        noJumpCount++;
                    }

                    if (noJumpCount > noJumpCountThresh)
                    {
                        noJumpCount = 0;
                        isBorder    = 1;
                        break;
                    }
                }
                border.Set <byte>(rowIndex, 0, isBorder);
            }

            int minTop = (int)(0.1f * rows);
            int maxTop = (int)(0.9f * rows);

            Mat result = threshold.Clone();

            for (int rowIndex = 0; rowIndex < minTop; rowIndex++)
            {
                if (border.At <byte>(rowIndex, 0) == 1)
                {
                    for (int colIndex = 0; colIndex < cols; colIndex++)
                    {
                        result.Set <byte>(rowIndex, colIndex, 0);
                    }
                }
            }

            for (int rowIndex = rows - 1; rowIndex > maxTop; rowIndex--)
            {
                if (border.At <byte>(rowIndex, 0) == 1)
                {
                    for (int colIndex = 0; colIndex < cols; colIndex++)
                    {
                        result.Set <byte>(rowIndex, colIndex, 0);
                    }
                }
            }

            return(result);
        }
Beispiel #8
0
        public override void RunTest()
        {
            // Read sample image
            using var frame = Cv2.ImRead(image);
            int frameHeight = frame.Rows;
            int frameWidth  = frame.Cols;

            using var faceNet = CvDnn.ReadNetFromCaffe(configFile, faceModel);
            using var blob    = CvDnn.BlobFromImage(frame, 1.0, new Size(300, 300), new Scalar(104, 117, 123), false, false);
            faceNet.SetInput(blob, "data");

            using var detection    = faceNet.Forward("detection_out");
            using var detectionMat = new Mat(detection.Size(2), detection.Size(3), MatType.CV_32F,
                                             detection.Ptr(0));
            for (int i = 0; i < detectionMat.Rows; i++)
            {
                float confidence = detectionMat.At <float>(i, 2);

                if (confidence > 0.7)
                {
                    int x1 = (int)(detectionMat.At <float>(i, 3) * frameWidth);
                    int y1 = (int)(detectionMat.At <float>(i, 4) * frameHeight);
                    int x2 = (int)(detectionMat.At <float>(i, 5) * frameWidth);
                    int y2 = (int)(detectionMat.At <float>(i, 6) * frameHeight);

                    Cv2.Rectangle(frame, new Point(x1, y1), new Point(x2, y2), new Scalar(0, 255, 0), 2, LineTypes.Link4);
                }
            }

            Window.ShowImages(frame);
        }
Beispiel #9
0
        private static Point3f MatrixToEulerAngles(Mat mHomography)
        {
            float num = (float)Math.Sqrt(mHomography.At <double>(0, 0) * mHomography.At <double>(0, 0) + mHomography.At <double>(1, 0) * mHomography.At <double>(1, 0));
            float num2;
            float num3;
            float num4;

            if (!((double)num < 1E-06))
            {
                num2 = (float)Math.Atan2(mHomography.At <double>(2, 1), mHomography.At <double>(2, 2));
                num3 = (float)Math.Atan2(0.0 - mHomography.At <double>(2, 0), num);
                num4 = (float)Math.Atan2(mHomography.At <double>(1, 0), mHomography.At <double>(0, 0));
            }
            else
            {
                num2 = (float)Math.Atan2(0.0 - mHomography.At <double>(1, 2), mHomography.At <double>(1, 1));
                num3 = (float)Math.Atan2(0.0 - mHomography.At <double>(2, 0), num);
                num4 = 0f;
            }
            Point3f result = default(Point3f);

            result.X = (float)((double)num2 * (180.0 / Math.PI));
            result.Y = (float)((double)num3 * (180.0 / Math.PI));
            result.Z = (float)((double)num4 * (180.0 / Math.PI));
            return(result);
        }
Beispiel #10
0
    void DetectLaser()
    {
        Mat[] bgrChannels = new Mat[3];
        Cv2.Split(videoSourceImage, out bgrChannels);

        Mat rt = new Mat();

        Cv2.Threshold(bgrChannels[2], rt, 240.0, 255.0, ThresholdTypes.Binary);

        Cv2.GaussianBlur(rt, rt, new Size(5, 5), 1);
        rt *= 255;

        Mat labels    = new Mat();
        Mat stats     = new Mat();
        Mat centroids = new Mat();

        Cv2.ConnectedComponentsWithStats(rt, labels, stats, centroids);

        if (centroids.Rows > 1)
        {
            Cv2.Circle(videoSourceImage, (int)centroids.At <double>(1, 0), (int)centroids.At <double>(1, 1), 20, new Scalar(255, 255, 255));
            Cv2.Circle(cannyImage, (int)centroids.At <double>(1, 0), (int)centroids.At <double>(1, 1), 20, new Scalar(255, 255, 255));
        }

        Cv2.Flip(videoSourceImage, videoSourceImage, FlipMode.XY);
        Cv2.Flip(cannyImage, cannyImage, FlipMode.XY);
        Cv2.ImShow("SuperLaserDetect", videoSourceImage);
        Cv2.ImShow("Processed WebCam", cannyImage);
    }
Beispiel #11
0
        public void AddPRNUNoise()
        {
            var precision = 10000;

            for (var y = 0; y < 600; y++)
            {
                for (var x = 0; x < 800; x++)
                {
                    var value = Image.At <ushort>(y, x);

                    if (value > 0)
                    {
                        var performance = 1.0 + ((_rand.Next(0, precision) / ((double)precision)) - 0.5) / 100;
                        var noised      = value * performance;

                        if (noised > ushort.MaxValue)
                        {
                            noised = ushort.MaxValue;
                        }
                        else if (noised < 0)
                        {
                            noised = 0;
                        }

                        Image.Set(y, x, (ushort)noised);
                    }
                }
            }
        }
Beispiel #12
0
        public static Mat ToSDFRender(Mat sdf)
        {
            var    drawing = new Mat(sdf.Rows, sdf.Cols, MatType.CV_8UC3);
            double minVal, maxVal;

            sdf.MinMaxIdx(out minVal, out maxVal);
            for (int j = 0; j < sdf.Rows; j++)
            {
                for (int i = 0; i < sdf.Cols; i++)
                {
                    if (sdf.At <float>(j, i) < 0)
                    {
                        drawing.Set(j, i, new Vec3b((byte)(255 - (int)Math.Abs((sdf.At <float>(j, i)) * 255 / minVal)), 0, 0));
                    }
                    else if (sdf.At <float>(j, i) > 0)
                    {
                        drawing.Set(j, i, new Vec3b(0, 0, (byte)(255 - (int)sdf.At <float>(j, i) * 255 / maxVal)));
                    }
                    else
                    {
                        drawing.Set(j, i, new Vec3b(255, 255, 255));
                    }
                }
            }
            return(drawing);
        }
Beispiel #13
0
        ////// <summary>
        /// Combines a 3x3 matrix with a 1x3 translation vector into a 4x4 transformation matrix
        /// </summary>
        /// <param name="matrix">3x3 matrix</param>
        /// <param name="translationVector">1x3 translation vector</param>
        /// <param name="specials">Set of values to be appended to the last column of the resulting matrix</param>
        /// <returns>4x4 transformation matrix in the correct order for vvvv</returns>
        private static Matrix ToTransformationMatrix(Mat matrix, Mat translationVector, float[] specials)
        {
            Matrix result = Matrix.Identity;

            if (matrix != null && translationVector != null)
            {
                if ((matrix.Width == 3 && matrix.Height == 3) &&
                    (translationVector.Width == 1 && translationVector.Height == 3))
                {
                    Mat rm = matrix.Clone();
                    Mat tv = translationVector.Clone();
                    rm.ConvertTo(rm, OpenCvSharp.MatType.CV_32FC1);
                    tv.ConvertTo(tv, OpenCvSharp.MatType.CV_32FC1);
                    result = new Matrix(
                        rm.At <float>(0, 0),
                        rm.At <float>(1, 0),
                        rm.At <float>(2, 0),
                        specials[0],
                        rm.At <float>(0, 1),
                        rm.At <float>(1, 1),
                        rm.At <float>(2, 1),
                        specials[1],
                        rm.At <float>(0, 2),
                        rm.At <float>(1, 2),
                        rm.At <float>(2, 2),
                        specials[2],
                        tv.At <float>(0),
                        tv.At <float>(1),
                        tv.At <float>(2),
                        specials[3]);
                }
            }
            return(result);
        }
Beispiel #14
0
        public Angles GetAnglesAndPoints(Mat <Point2d> points, int width, int height)
        {
            using (var objPtsMat = InputArray.Create(Model_points, MatType.CV_32FC3)) //new Mat(objPts.Count, 1, MatType.CV_32FC3, objPts))
                using (var imgPtsMat = InputArray.Create(points, MatType.CV_32FC2))   //new Mat(imgPts.Length, 1, MatType.CV_32FC2, imgPts))
                    using (var cameraMatrixMat = Mat.Eye(3, 3, MatType.CV_64FC1))
                        using (var distMat = Mat.Zeros(5, 0, MatType.CV_64FC1))
                            using (var rvecMat = new Mat())
                                using (var tvecMat = new Mat())
                                {
                                    Cv2.SolvePnP(objPtsMat, imgPtsMat, cameraMatrixMat, distMat, rvecMat, tvecMat);

                                    using (Mat resultPoints = new Mat())
                                    {
                                        Cv2.ProjectPoints(objPtsMat, rvecMat, tvecMat, cameraMatrixMat, distMat, resultPoints);
                                    }

                                    // 根据旋转矩阵求解坐标旋转角
                                    double theta_x = Math.Atan2((float)rvecMat.At <double>(2, 1), (float)rvecMat.At <double>(2, 2));
                                    double theta_y = Math.Atan2((float)-rvecMat.At <double>(2, 0),
                                                                Math.Sqrt((float)((rvecMat.At <double>(2, 1) * rvecMat.At <double>(2, 1)) + ((float)rvecMat.At <double>(2, 2) * rvecMat.At <double>(2, 2)))));
                                    double theta_z = Math.Atan2((float)rvecMat.At <double>(1, 0), (float)rvecMat.At <double>(0, 0));

                                    // 将弧度转为角度
                                    Angles angles = new Angles();
                                    angles.Roll  = theta_x * (180 / Math.PI);
                                    angles.Pitch = theta_y * (180 / Math.PI);
                                    angles.Yaw   = theta_z * (180 / Math.PI);

                                    // 将映射的点的坐标保存下来
                                    // outarray类型的resultpoints如何转存到list中?
                                    return(angles);
                                }
        }
Beispiel #15
0
        /// <summary>
        /// 輝度値をステータスバーへ表示
        /// </summary>
        /// <param name="mat"></param>
        /// <param name="X">画像のX座標</param>
        /// <param name="Y">画像のY座標</param>
        private void DrawBrightValue(Mat mat, int X, int Y)
        {
            // 画像データが無い場合は何もしない
            if (mat == null)
            {
                return;
            }
            if (mat.Data == IntPtr.Zero)
            {
                return;
            }

            string lblText;

            lblText = "(" + X.ToString() + ", " + Y.ToString() + ") = ";

            if (mat.Channels() == 1)
            {
                // モノクロの場合
                lblText += mat.At <byte>(Y, X).ToString();
            }
            else
            {
                // カラーの場合
                lblText += "(" +
                           mat.At <OpenCvSharp.CPlusPlus.Vec3b>(Y, X)[2].ToString() + ", " +
                           mat.At <OpenCvSharp.CPlusPlus.Vec3b>(Y, X)[1].ToString() + ", " +
                           mat.At <OpenCvSharp.CPlusPlus.Vec3b>(Y, X)[0].ToString() + ")";
            }
            lblBright.Text = lblText;
        }
Beispiel #16
0
        //Поиск крайних точек объекта сверху и снизу
        Point[] FindShape(Rect rect)
        {
            bool topFound = false, bottomFound = false;

            Point top = new Point(), bottom = new Point();

            int i = 0;

            while (!topFound || !bottomFound)
            {
                if (depthMap.At <byte>(rect.Top + i, rect.Left + rect.Width / 2) > 0 && !topFound)
                {
                    top = new Point(rect.Left + rect.Width / 2, rect.Top + i);

                    topFound = true;
                }

                if (depthMap.At <byte>(rect.Bottom - i, rect.Left + rect.Width / 2) > 0 && !bottomFound)
                {
                    bottom = new Point(rect.Left + rect.Width / 2, rect.Bottom - i);

                    bottomFound = true;
                }

                i++;
            }

            return(new Point[2] {
                top, bottom
            });
        }
Beispiel #17
0
        Mat TransfLogaritimica()
        {
            Mat logImage = greyImage.Clone();

            byte fmax = 0; byte fmin = 255;

            for (int x = 0; x < logImage.Rows; x++)
            {
                for (int y = 0; y < logImage.Cols; y++)
                {
                    byte pixel = logImage.At <byte>(x, y);
                    if (pixel > fmax)
                    {
                        fmax = pixel;
                    }
                    if (pixel < fmin)
                    {
                        fmin = pixel;
                    }
                }
            }
            for (int x = 0; x < logImage.Rows; x++)
            {
                for (int y = 0; y < logImage.Cols; y++)
                {
                    byte   f         = logImage.At <byte>(x, y);
                    double alpha     = 255 / Math.Log(1 + fmax);
                    double resultado = alpha * Math.Log(f + 1);
                    logImage.Set <byte>(x, y, (byte)resultado);
                }
            }
            return(logImage);
        }
Beispiel #18
0
        Mat AjustarContraste()
        {
            Mat  cont = greyImage.Clone();
            byte fmax = 0; byte fmin = 255;

            for (int x = 0; x < cont.Rows; x++)
            {
                for (int y = 0; y < cont.Cols; y++)
                {
                    byte pixel = cont.At <byte>(x, y);
                    if (pixel > fmax)
                    {
                        fmax = pixel;
                    }
                    if (pixel < fmin)
                    {
                        fmin = pixel;
                    }
                }
            }
            byte gmax = 255; byte gmin = 0;

            for (int x = 0; x < cont.Rows; x++)
            {
                for (int y = 0; y < cont.Cols; y++)
                {
                    byte f = cont.At <byte>(x, y);
                    cont.Set <byte>(x, y, (byte)(((gmax - gmin) / (fmax - fmin)) * (f - fmin) + gmin));
                }
            }
            return(cont);
        }
Beispiel #19
0
    private (double, double) findMatchPoint(Mat templateFromLeftImg, Mat epliline)
    {
        Mat    rightImg_roi = new Mat(templateFromLeftImg.Rows, SCREEN_WIDTH, MatType.CV_8UC3);
        double a            = epliline.At <Point3d>(0).X;
        double b            = epliline.At <Point3d>(0).Y;
        double c            = epliline.At <Point3d>(0).Z; // ax+by+cz=0 (homogeneous coordinates)

        for (int col = 0; col < SCREEN_WIDTH; col++)      // affine transformation
        {
            double y = (-c - a * col) / b;
            for (int row = (int)(y - rightImg_roi.Rows / 2); row < (int)(y + rightImg_roi.Rows / 2); row++)
            {
                rightImg_roi.Set <Vec3b>(row - (int)(y - rightImg_roi.Rows / 2), col, rightImg.Get <Vec3b>(row, col));
            }
        }
        Mat    result = new Mat();
        double maxVal;
        double minVal;
        Point  minLoc = new Point();
        Point  maxLoc = new Point();

        Cv2.MatchTemplate(rightImg_roi, templateFromLeftImg, result, TemplateMatchModes.SqDiffNormed);
        Cv2.MinMaxLoc(result, out minVal, out maxVal, out minLoc, out maxLoc);

        /*
         * if(templateFromLeftImg == part1)
         * {
         *  Cv2.Circle(rightImg_roi, minLoc.X + templateFromLeftImg.Cols / 2, minLoc.Y + templateFromLeftImg.Rows / 2, 2, Scalar.Red, -1, LineTypes.Link8);
         *  Cv2.ImWrite(Application.persistentDataPath + "/test output.png", rightImg_roi);
         * }
         */
        return(minLoc.X + templateFromLeftImg.Cols / 2, minLoc.Y + templateFromLeftImg.Rows / 2);  // center point of matcing rectangle
    }
        public double[,] captureRGBCloud()
        {
            Mmind.Response reply   = sendRequest(CaptureGratingImage, 4, "");
            Mat            depthC3 = read32FC3Mat(reply.ImageGrating);
            Mat            color   = captureColorImg();
            int            nums    = color.Rows * color.Cols;

            double[,] xyzbgr = new double[nums, 6];
            int count = 0;

            for (int i = 0; i < depthC3.Rows; i++)
            {
                for (int j = 0; j < depthC3.Cols; j++)
                {
                    xyzbgr[count, 0] = (double)depthC3.At <Vec3f>(i, j)[0] * 0.001;
                    xyzbgr[count, 1] = (double)depthC3.At <Vec3f>(i, j)[1] * 0.001;
                    xyzbgr[count, 2] = (double)depthC3.At <Vec3f>(i, j)[2] * 0.001;
                    xyzbgr[count, 3] = color.At <Vec3b>(i, j)[0];
                    xyzbgr[count, 4] = color.At <Vec3b>(i, j)[1];
                    xyzbgr[count, 5] = color.At <Vec3b>(i, j)[2];
                    count++;
                }
            }

            return(xyzbgr);
        }
Beispiel #21
0
        // 去柳钉
        public static Mat ClearMaoding(Mat threshold, int num)
        {
            List <float> jumps = new List <float>();

            Mat jump = new Mat(threshold.Rows, 1, MatType.CV_32F);

            for (int rowIndex = num; rowIndex < threshold.Rows - num; rowIndex++)
            {
                int jumpCount = 0;
                for (int colIndex = num; colIndex < threshold.Cols - num; colIndex++)
                {
                    if (threshold.At <byte>(rowIndex, colIndex) != threshold.At <byte>(rowIndex, colIndex + 1))
                    {
                        jumpCount++;
                    }
                }
                jump.Set <float>(rowIndex, 0, (float)jumpCount);
            }

            int x      = 7;
            Mat result = threshold.Clone();

            for (int rowIndex = 0; rowIndex < threshold.Rows; rowIndex++)
            {
                if (jump.At <float>(rowIndex) <= x)
                {
                    for (int colIndex = 0; colIndex < threshold.Cols; colIndex++)
                    {
                        result.Set <byte>(rowIndex, colIndex, 0);
                    }
                }
            }

            return(result);
        }
Beispiel #22
0
        public double[,] captureRGBCloud()
        {
            byte[] response   = sendRequest(Command.CaptureImage, 0, "", MatXYZ);
            int    jsonSize   = readInt(response, 0);
            double scale      = readDouble(response, jsonSize + SIZE_OF_JSON);
            int    imageSize  = readInt(response, SIZE_OF_JSON + jsonSize + SIZE_OF_SCALE);
            int    imageBegin = SIZE_OF_JSON + jsonSize + SIZE_OF_SCALE + sizeof(Int32);

            byte[] imageDepth = response.Skip(imageBegin).Take(imageSize).ToArray();
            Mat    depthC3    = read32FC3Mat(imageDepth, scale);
            Mat    color      = captureColorImg();
            int    nums       = color.Rows * color.Cols;

            double[,] xyzbgr = new double[nums, 6];
            int count = 0;

            for (int i = 0; i < depthC3.Rows; i++)
            {
                for (int j = 0; j < depthC3.Cols; j++)
                {
                    xyzbgr[count, 0] = (double)depthC3.At <Vec3f>(i, j)[0] * 0.001;
                    xyzbgr[count, 1] = (double)depthC3.At <Vec3f>(i, j)[1] * 0.001;
                    xyzbgr[count, 2] = (double)depthC3.At <Vec3f>(i, j)[2] * 0.001;
                    xyzbgr[count, 3] = color.At <Vec3b>(i, j)[0];
                    xyzbgr[count, 4] = color.At <Vec3b>(i, j)[1];
                    xyzbgr[count, 5] = color.At <Vec3b>(i, j)[2];
                    count++;
                }
            }

            return(xyzbgr);
        }
Beispiel #23
0
        //清除铆钉
        public static Mat ClearMaoding(Mat threshold)
        {
            //List<float> jumps = new List<float>();
            Mat jump = new Mat(threshold.Rows, 1, MatType.CV_32F);

            for (int rowIndex = 0; rowIndex < threshold.Rows; rowIndex++)
            {
                int jumpCount = 0;
                for (int colIndex = 0; colIndex < threshold.Cols - 1; colIndex++)
                {
                    if (threshold.At <byte>(rowIndex, colIndex) != threshold.At <byte>(rowIndex, colIndex + 1))
                    {
                        jumpCount++;
                    }
                }
                jump.Set <float>(rowIndex, 0, (float)jumpCount);
            }
            //设置阈值,检测过程中黑白像素点变化的次数,并记录下每一排的变化次数,从而将铆钉去除
            int x      = 7;
            Mat result = threshold.Clone();

            for (int rowIndex = 0; rowIndex < threshold.Rows; rowIndex++)
            {
                if (jump.At <float>(rowIndex) <= x)
                {
                    for (int colIndex = 0; colIndex < threshold.Cols; colIndex++)
                    {
                        result.Set <byte>(rowIndex, colIndex, 0);
                    }
                }
            }
            return(result);
        }
Beispiel #24
0
        public void CalcHist()
        {
            using var src = new Mat(@"_data/image/mandrill.png", ImreadModes.Grayscale);

            using var hist = new Mat();
            Cv2.CalcHist(
                images: new[] { src },
                channels: new[] { 0 },
                mask: null,
                hist: hist,
                dims: 1,
                histSize: new[] { 256 },
                ranges: new[] { new Rangef(0, 256) });

            if (Debugger.IsAttached)
            {
                const int histW = 512;
                const int histH = 400;
                var       binW  = Math.Round((double)histW / 256);
                using var histImage = new Mat(histH, histW, MatType.CV_8UC3, Scalar.All(0));
                Cv2.Normalize(hist, hist, 0, histImage.Rows, NormTypes.MinMax, -1);

                for (int i = 0; i < 256; i++)
                {
                    var pt1 = new Point2d(binW * (i - 1), histH - Math.Round(hist.At <float>(i - 1)));
                    var pt2 = new Point2d(binW * (i), histH - Math.Round(hist.At <float>(i)));
                    Cv2.Line(
                        histImage, (Point)pt1, (Point)pt2,
                        Scalar.Red, 1, LineTypes.Link8);
                }

                Window.ShowImages(src, histImage);
            }
        }
Beispiel #25
0
    Vector3 project3DPoints(Vector3 obj)
    {
        Mat point2d_vec = new Mat(4, 1, MatType.CV_64FC1);

        Mat cameraMatrixMat = new Mat(3, 3, MatType.CV_64FC1, cameraMatrix);

        Mat point3d_vec = new Mat(4, 1, MatType.CV_64FC1);

        point3d_vec.Set <double>(0, obj.x);
        point3d_vec.Set <double>(1, obj.y);
        point3d_vec.Set <double>(2, obj.z);
        point3d_vec.Set <double>(3, 1);

        point2d_vec = cameraMatrixMat * projMatrix * point3d_vec;

        var X2D = point2d_vec.At <double>(0) / point2d_vec.At <double>(2);
        var Y2D = point2d_vec.At <double>(1) / point2d_vec.At <double>(2);

        Debug.Log(" 3d Points " + obj.x + " " + obj.y + " " + obj.z);
        Debug.Log(" 2d point  x : " + X2D + " y " + Y2D);
        //Debug.Log(" float 2d point  x : " + (float)X2D + " y " + (float)Y2D);

        Vector3 pnpPoints = new Vector3((float)X2D, (float)Y2D, 0.0f);

        return(pnpPoints);
    }
        public Rectangle[] Detect(Mat mat, byte[] buffer)
        {
            var frameWidth  = mat.Width;
            var frameHeight = mat.Height;

            using var blob = CvDnn.BlobFromImage(mat, 1.0, new OpenCvSharp.Size(300, 300), new OpenCvSharp.Scalar(104, 117, 123), false, false);
            Net.SetInput(blob);
            using var detections   = Net.Forward();
            using var detectionMat = new Mat(detections.Size(2), detections.Size(3), MatType.CV_32F, detections.Ptr(0));
            var rectangles = new List <Rectangle>();

            for (var i = 0; i < detectionMat.Rows; i++)
            {
                var confidence = detectionMat.At <float>(i, 2);
                if (confidence > 0.7)
                {
                    var left   = (int)(detectionMat.At <float>(i, 3) * frameWidth);
                    var top    = (int)(detectionMat.At <float>(i, 4) * frameHeight);
                    var right  = (int)(detectionMat.At <float>(i, 5) * frameWidth);
                    var bottom = (int)(detectionMat.At <float>(i, 6) * frameHeight);

                    rectangles.Add(new Rectangle(left, top, right - left, bottom - top));
                }
            }

            return(rectangles.ToArray());
        }
        PointF GetEdgePoint(Mat imgGray)
        {
            PointF __vector = __end.Location - new System.Drawing.Size(System.Drawing.Point.Round(__start.Location));

            float __distance = (float)Math.Sqrt(Math.Pow(__vector.X, 2) + Math.Pow(__vector.Y, 2));

            ///turns into unit vector
            __vector.X = __vector.X / __distance;
            __vector.Y = __vector.Y / __distance;
            if (__distance <= 0)
            {
                return(PointF.Empty);
            }
            PointF __accumulation = __start.Location;

            double __acuumulatedLength = 0;

            // interpolate start-end , load into table
            // access each point's gray value
            // post handling
            Dictionary <PointF, MatType> __mattypeTable   = new Dictionary <PointF, MatType>();
            Dictionary <PointF, byte>    __grayValueTable = new Dictionary <PointF, byte>();


            while (__acuumulatedLength <= __distance)
            {
                __accumulation += new SizeF(__vector);

                //establish pair of coordinate , gray value
                __mattypeTable.Add(__accumulation,
                                   imgGray.At <MatType>(
                                       Convert.ToInt32(__accumulation.Y),
                                       Convert.ToInt32(__accumulation.X)
                                       )
                                   );
                __grayValueTable.Add(__accumulation,
                                     imgGray.At <byte>(
                                         Convert.ToInt32(__accumulation.Y),
                                         Convert.ToInt32(__accumulation.X)
                                         )
                                     );

                //unit length added one
                __acuumulatedLength++;
            }

            //diff and find maximum
            List <byte> __grayValueList = __grayValueTable.Values.ToList();
            List <int>  __diffValueList = new List <int>();

            for (int i = 0; i < __grayValueList.Count - 1; i++)
            {
                __diffValueList.Add(Math.Abs(__grayValueList[i + 1] - __grayValueList[i]));
            }
            int edgeIndex = __diffValueList.IndexOf(__diffValueList.Max());

            return(__grayValueTable.Keys.ElementAt(edgeIndex));
        }
Beispiel #28
0
    public void pnp(Point3f[] objPts, Point2f[] imgPts, Camera cam, SolvePnPFlags type, string filename)
    {
        Debug.Log($" PNP   : {objPts.Length} : {imgPts.Length}");

        TextWriter rotFile   = new StreamWriter(filename + "-RotPnP.txt");
        TextWriter transFile = new StreamWriter(filename + "-TransPnP.txt");

        using (var objPtsMat = new Mat(objPts.Length, 1, MatType.CV_32FC3, objPts))
            using (var imgPtsMat = new Mat(imgPts.Length, 1, MatType.CV_32FC2, imgPts))
                using (var cameraMatrixMat = new Mat(3, 3, MatType.CV_64FC1, getCameraMatrix(cam)))
                    using (var distMat = Mat.Zeros(5, 0, MatType.CV_64FC1))
                        using (var rvecMat = new Mat())
                            using (var tvecMat = new Mat())
                            {
                                Cv2.SolvePnP(objPtsMat, imgPtsMat, cameraMatrixMat, distMat, rvecMat, tvecMat, flags: type);
                                //Debug.Log("Solved " + rvecMat + "  :  "+tvecMat);

                                Mat rot_matrix  = Mat.Zeros(3, 3, MatType.CV_64FC1);
                                Mat tr_matrix   = Mat.Zeros(3, 1, MatType.CV_64FC1);
                                Mat proj_matrix = Mat.Zeros(3, 4, MatType.CV_64FC1);

                                Cv2.Rodrigues(rvecMat, rot_matrix);
                                tr_matrix = tvecMat;

                                rotFile.WriteLine(rot_matrix.At <double>(0, 0) + " " + rot_matrix.At <double>(0, 1) + " " + rot_matrix.At <double>(0, 2));
                                rotFile.WriteLine(rot_matrix.At <double>(1, 0) + " " + rot_matrix.At <double>(1, 1) + " " + rot_matrix.At <double>(1, 2));
                                rotFile.WriteLine(rot_matrix.At <double>(2, 0) + " " + rot_matrix.At <double>(2, 1) + " " + rot_matrix.At <double>(2, 2));
                                transFile.WriteLine(tr_matrix.At <double>(0) + " " + tr_matrix.At <double>(1) + " " + tr_matrix.At <double>(2));

                                proj_matrix.Set <double>(0, 0, rot_matrix.At <double>(0, 0));
                                proj_matrix.Set <double>(0, 1, rot_matrix.At <double>(0, 1));
                                proj_matrix.Set <double>(0, 2, rot_matrix.At <double>(0, 2));

                                proj_matrix.Set <double>(1, 0, rot_matrix.At <double>(1, 0));
                                proj_matrix.Set <double>(1, 1, rot_matrix.At <double>(1, 1));
                                proj_matrix.Set <double>(1, 2, rot_matrix.At <double>(1, 2));

                                proj_matrix.Set <double>(2, 0, rot_matrix.At <double>(2, 0));
                                proj_matrix.Set <double>(2, 1, rot_matrix.At <double>(2, 1));
                                proj_matrix.Set <double>(2, 2, rot_matrix.At <double>(2, 2));

                                proj_matrix.Set <double>(0, 3, tr_matrix.At <double>(0));
                                proj_matrix.Set <double>(1, 3, tr_matrix.At <double>(1));
                                proj_matrix.Set <double>(2, 3, tr_matrix.At <double>(2));

                                //rot = eulerAngle(rot_matrix);

                                // Debug.Log($"1  : Matrix4x4.TRS(translation, rotation, scale) {Matrix4x4.TRS(cam.transform.position, cam.transform.rotation, new Vector3(10, 10, 10))}");
                                // Debug.Log($"1  : Matrix4x4.TRS(translation, rotation, scale) {Matrix4x4.TRS(cam.transform.position, cam.transform.rotation, new Vector3(10, 10, 10))}");

                                //Debug.Log($"rot1 {cam.transform.eulerAngles} rot2 { rot * Mathf.Rad2Deg}");
                                //Debug.Log($"tr1: {cam.transform.position} tr2: {tr_matrix.At<double>(0)}, {tr_matrix.At<double>(1)}, {tr_matrix.At<double>(2)}");
                                projectionMatrix = proj_matrix;
                            }

        rotFile.Flush();
        transFile.Flush();
    }
Beispiel #29
0
    private void drawEpipolarLine(Mat plate, Mat epliline)// use for testing only
    {
        double x = epliline.At <Point3d>(0).X;
        double y = epliline.At <Point3d>(0).Y;
        double z = epliline.At <Point3d>(0).Z;

        Cv2.Line(plate, new Point(0, -z / y), new Point(SCREEN_WIDTH - 1, (-x * (SCREEN_WIDTH - 1) - z) / y), Scalar.Green);
        Cv2.ImWrite(Application.persistentDataPath + "/test output.png", plate);
    }
        private static Mat BGRToHSV(Mat img)
        {
            int width  = img.Cols;
            int height = img.Rows;

            float r, g, b;
            float h = 0f, s, v;
            float _max, _min;

            var hsv = Mat.Zeros(height, width, MatType.CV_32FC3).ToMat();

            // each y, x
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    // BGR -> HSV
                    r = (float)img.At <Vec3b>(y, x)[2] / 255;
                    g = (float)img.At <Vec3b>(y, x)[1] / 255;
                    b = (float)img.At <Vec3b>(y, x)[0] / 255;

                    _max = Math.Max(r, Math.Max(g, b));
                    _min = Math.Min(r, Math.Min(g, b));

                    // get Hue
                    if (_max == _min)
                    {
                        h = 0;
                    }
                    else if (_min == b)
                    {
                        h = 60 * (g - r) / (_max - _min) + 60;
                    }
                    else if (_min == r)
                    {
                        h = 60 * (b - g) / (_max - _min) + 180;
                    }
                    else if (_min == g)
                    {
                        h = 60 * (r - b) / (_max - _min) + 300;
                    }

                    // get Saturation
                    s = _max - _min;

                    // get Value
                    v = _max;

                    var pixel = hsv.At <Vec3f>(y, x);
                    pixel.Item0 = h;
                    pixel.Item1 = s;
                    pixel.Item2 = v;
                    hsv.Set(y, x, pixel);
                }
            }
            return(hsv);
        }
Beispiel #31
0
        private static void HDR()
        {
            var hdr = CalibrateDebevec.Create();

            Mat[] images = new Mat[3];
            images[0] = Cv2.ImRead(@"data\lenna.png", ImreadModes.AnyColor);
            images[1] = Cv2.ImRead(@"data\lenna.png", ImreadModes.AnyColor);
            images[2] = Cv2.ImRead(@"data\lenna.png", ImreadModes.AnyColor);

            float[] speeds = new float[3];
            speeds[0] = 1;
            speeds[1] = 1;
            speeds[2] = 1;

            Mat dst = new Mat();

            hdr.Process(images, dst, speeds);

            dst.ToString();

            for (int i = 0; i < Math.Max(dst.Rows, dst.Cols); i++)
            {
                Console.WriteLine(dst.At<float>(i));
            }
        }
Beispiel #32
0
        /// <summary>
        /// Solve equation AX = Y
        /// </summary>
        private void ByMat()
        {
            // x + y = 10
            // 2x + 3y = 26
            // (x=4, y=6)

            double[,] av = {{1, 1}, 
                          {2, 3}};
            double[] yv = {10, 26};

            Mat a = new Mat(2, 2, MatType.CV_64FC1, av);
            Mat y = new Mat(2, 1, MatType.CV_64FC1, yv);
            Mat x = new Mat();

            Cv2.Solve(a, y, x, MatrixDecomposition.LU);

            Console.WriteLine("ByMat:");
            Console.WriteLine("X1 = {0}, X2 = {1}", x.At<double>(0), x.At<double>(1));
        }
Beispiel #33
0
        public void ByMat()
        {
            // x + y = 10
            // 2x + 3y = 26
            // (x=4, y=6)

            double[,] av = {{1, 1},
                          {2, 3}};
            double[] yv = { 10, 26 };

            Mat a = new Mat(2, 2, MatType.CV_64FC1, av);
            Mat y = new Mat(2, 1, MatType.CV_64FC1, yv);
            Mat x = new Mat();

            Cv2.Solve(a, y, x, DecompTypes.LU);

            Console.WriteLine("X1 = {0}, X2 = {1}", x.At<double>(0), x.At<double>(1));
            Assert.That(x.At<double>(0), Is.EqualTo(4).Within(1e-6));
            Assert.That(x.At<double>(1), Is.EqualTo(6).Within(1e-6));
        }
        private static void example02()
        {
            var src = new Mat(@"..\..\Images\fruits.jpg", LoadMode.AnyDepth | LoadMode.AnyColor);
            Cv2.ImShow("Source", src);
            Cv2.WaitKey(1); // do events

            Cv2.Blur(src, src, new Size(15, 15));
            Cv2.ImShow("Blurred Image", src);
            Cv2.WaitKey(1); // do events

            // Converts the MxNx3 image into a Kx3 matrix where K=MxN and
            // each row is now a vector in the 3-D space of RGB.
            // change to a Mx3 column vector (M is number of pixels in image)
            var columnVector = src.Reshape(cn: 3, rows: src.Rows * src.Cols);

            // convert to floating point, it is a requirement of the k-means method of OpenCV.
            var samples = new Mat();
            columnVector.ConvertTo(samples, MatType.CV_32FC3);

            for (var clustersCount = 2; clustersCount <= 8; clustersCount += 2)
            {
                var bestLabels = new Mat();
                var centers = new Mat();
                Cv2.Kmeans(
                    data: samples,
                    k: clustersCount,
                    bestLabels: bestLabels,
                    criteria:
                        new TermCriteria(type: CriteriaType.Epsilon | CriteriaType.Iteration, maxCount: 10, epsilon: 1.0),
                    attempts: 3,
                    flags: KMeansFlag.PpCenters,
                    centers: centers);

                var clusteredImage = new Mat(src.Rows, src.Cols, src.Type());
                for (var size = 0; size < src.Cols * src.Rows; size++)
                {
                    var clusterIndex = bestLabels.At<int>(0, size);
                    var newPixel = new Vec3b
                    {
                        Item0 = (byte)(centers.At<float>(clusterIndex, 0)), // B
                        Item1 = (byte)(centers.At<float>(clusterIndex, 1)), // G
                        Item2 = (byte)(centers.At<float>(clusterIndex, 2)) // R
                    };
                    clusteredImage.Set(size / src.Cols, size % src.Cols, newPixel);
                }

                Cv2.ImShow(string.Format("Clustered Image [k:{0}]", clustersCount), clusteredImage);
                Cv2.WaitKey(1); // do events
            }

            Cv2.WaitKey();
            Cv2.DestroyAllWindows();
        }
        /// <summary>
        /// https://github.com/Itseez/opencv_extra/blob/master/learning_opencv_v2/ch13_ex13_1.cpp
        /// </summary>
        private static void example01()
        {
            using (var window = new Window("Clusters", flags: WindowMode.AutoSize | WindowMode.FreeRatio))
            {
                const int maxClusters = 5;
                var rng = new RNG(state: (ulong)DateTime.Now.Ticks);

                for (; ; )
                {
                    var clustersCount = rng.Uniform(a: 2, b: maxClusters + 1);
                    var samplesCount = rng.Uniform(a: 1, b: 1001);

                    var points = new Mat(rows: samplesCount, cols: 1, type: MatType.CV_32FC2);
                    clustersCount = Math.Min(clustersCount, samplesCount);

                    var img = new Mat(rows: 500, cols: 500, type: MatType.CV_8UC3, s: Scalar.All(0));

                    // generate random sample from multi-gaussian distribution
                    for (var k = 0; k < clustersCount; k++)
                    {
                        var pointChunk = points.RowRange(
                                startRow: k * samplesCount / clustersCount,
                                endRow: (k == clustersCount - 1)
                                    ? samplesCount
                                    : (k + 1) * samplesCount / clustersCount);

                        var center = new Point
                        {
                            X = rng.Uniform(a: 0, b: img.Cols),
                            Y = rng.Uniform(a: 0, b: img.Rows)
                        };
                        rng.Fill(
                            mat: pointChunk,
                            distType: DistributionType.Normal,
                            a: new Scalar(center.X, center.Y),
                            b: new Scalar(img.Cols * 0.05f, img.Rows * 0.05f));
                    }

                    Cv2.RandShuffle(dst: points, iterFactor: 1, rng: rng);

                    var labels = new Mat();
                    var centers = new Mat(rows: clustersCount, cols: 1, type: points.Type());
                    Cv2.Kmeans(
                        data: points,
                        k: clustersCount,
                        bestLabels: labels,
                        criteria: new TermCriteria(CriteriaType.Epsilon | CriteriaType.Iteration, 10, 1.0),
                        attempts: 3,
                        flags: KMeansFlag.PpCenters,
                        centers: centers);

                    Scalar[] colors =
                    {
                       new Scalar(0, 0, 255),
                       new Scalar(0, 255, 0),
                       new Scalar(255, 100, 100),
                       new Scalar(255, 0, 255),
                       new Scalar(0, 255, 255)
                    };

                    for (var i = 0; i < samplesCount; i++)
                    {
                        var clusterIdx = labels.At<int>(i);
                        Point ipt = points.At<Point2f>(i);
                        Cv2.Circle(
                            img: img,
                            center: ipt,
                            radius: 2,
                            color: colors[clusterIdx],
                            lineType: LineType.AntiAlias,
                            thickness: Cv.FILLED);
                    }

                    window.Image = img;

                    var key = (char)Cv2.WaitKey();
                    if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
                    {
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// https://github.com/Itseez/opencv_extra/blob/master/learning_opencv_v2/ch9_watershed.cpp
        /// </summary>
        private static void watershedExample()
        {
            var src = new Mat(@"..\..\Images\corridor.jpg", LoadMode.AnyDepth | LoadMode.AnyColor);
            var srcCopy = new Mat();
            src.CopyTo(srcCopy);

            var markerMask = new Mat();
            Cv2.CvtColor(srcCopy, markerMask, ColorConversion.BgrToGray);

            var imgGray = new Mat();
            Cv2.CvtColor(markerMask, imgGray, ColorConversion.GrayToBgr);
            markerMask = new Mat(markerMask.Size(), markerMask.Type(), s: Scalar.All(0));

            var sourceWindow = new Window("Source (Select areas by mouse and then press space)")
            {
                Image = srcCopy
            };

            var previousPoint = new Point(-1, -1);
            sourceWindow.OnMouseCallback += (@event, x, y, flags) =>
            {
                if (x < 0 || x >= srcCopy.Cols || y < 0 || y >= srcCopy.Rows)
                {
                    return;
                }

                if (@event == MouseEvent.LButtonUp || !flags.HasFlag(MouseEvent.FlagLButton))
                {
                    previousPoint = new Point(-1, -1);
                }
                else if (@event == MouseEvent.LButtonDown)
                {
                    previousPoint = new Point(x, y);
                }
                else if (@event == MouseEvent.MouseMove && flags.HasFlag(MouseEvent.FlagLButton))
                {
                    var pt = new Point(x, y);
                    if (previousPoint.X < 0)
                    {
                        previousPoint = pt;
                    }

                    Cv2.Line(img: markerMask, pt1: previousPoint, pt2: pt, color: Scalar.All(255), thickness: 5);
                    Cv2.Line(img: srcCopy, pt1: previousPoint, pt2: pt, color: Scalar.All(255), thickness: 5);
                    previousPoint = pt;
                    sourceWindow.Image = srcCopy;
                }
            };

            var rnd = new Random();

            for (; ; )
            {
                var key = Cv2.WaitKey(0);

                if ((char)key == 27) // ESC
                {
                    break;
                }

                if ((char)key == 'r') // Reset
                {
                    markerMask = new Mat(markerMask.Size(), markerMask.Type(), s: Scalar.All(0));
                    src.CopyTo(srcCopy);
                    sourceWindow.Image = srcCopy;
                }

                if ((char)key == 'w' || (char)key == ' ') // Apply watershed
                {
                    Point[][] contours; //vector<vector<Point>> contours;
                    HiearchyIndex[] hierarchyIndexes; //vector<Vec4i> hierarchy;
                    Cv2.FindContours(
                        markerMask,
                        out contours,
                        out hierarchyIndexes,
                        mode: ContourRetrieval.CComp,
                        method: ContourChain.ApproxSimple);

                    if (contours.Length == 0)
                    {
                        continue;
                    }

                    var markers = new Mat(markerMask.Size(), MatType.CV_32S, s: Scalar.All(0));

                    var componentCount = 0;
                    var contourIndex = 0;
                    while ((contourIndex >= 0))
                    {
                        Cv2.DrawContours(
                            markers,
                            contours,
                            contourIndex,
                            color: Scalar.All(componentCount+1),
                            thickness: -1,
                            lineType: LineType.Link8,
                            hierarchy: hierarchyIndexes,
                            maxLevel: int.MaxValue);

                        componentCount++;
                        contourIndex = hierarchyIndexes[contourIndex].Next;
                    }

                    if (componentCount == 0)
                    {
                        continue;
                    }

                    var colorTable = new List<Vec3b>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        var b = rnd.Next(0, 255); //Cv2.TheRNG().Uniform(0, 255);
                        var g = rnd.Next(0, 255); //Cv2.TheRNG().Uniform(0, 255);
                        var r = rnd.Next(0, 255); //Cv2.TheRNG().Uniform(0, 255);

                        colorTable.Add(new Vec3b((byte)b, (byte)g, (byte)r));
                    }

                    Cv2.Watershed(src, markers);

                    var watershedImage = new Mat(markers.Size(), MatType.CV_8UC3);

                    // paint the watershed image
                    for (var i = 0; i < markers.Rows; i++)
                    {
                        for (var j = 0; j < markers.Cols; j++)
                        {
                            var idx = markers.At<int>(i, j);
                            if (idx == -1)
                            {
                                watershedImage.Set(i, j, new Vec3b(255, 255, 255));
                            }
                            else if (idx <= 0 || idx > componentCount)
                            {
                                watershedImage.Set(i, j, new Vec3b(0, 0, 0));
                            }
                            else
                            {
                                watershedImage.Set(i, j, colorTable[idx - 1]);
                            }
                        }
                    }

                    watershedImage = watershedImage * 0.5 + imgGray * 0.5;
                    Cv2.ImShow("Watershed Transform", watershedImage);
                    Cv2.WaitKey(1); //do events
                }
            }

            sourceWindow.Dispose();
            Cv2.DestroyAllWindows();
            src.Dispose();
        }
        public ActionResult Histgram(HttpPostedFileBase imageData)
        {
            try
            {
                if (imageData == null) { throw new ArgumentException("File is not exist."); }

                using (var img = Mat.FromStream(imageData.InputStream, LoadMode.Color))
                {
                    int chWidth = 260;
                    int chHeight = 200;
                    using (var mask = new Mat())
                    using (var hist = new Mat())
                    using (var histImg = new Mat(new Size(chWidth, chHeight), MatType.CV_8UC3, Scalar.All(255)))
                    {
                        Mat[] images = new Mat[] { img };
                        int[] channels = new int[] { 0 };
                        int[] hdims = new int[] { 256 };
                        float[] hranges = new float[] { 0, 256 };
                        float[][] ranges = new float[][] { hranges };
                        Cv2.CalcHist(images, channels, mask, hist, 1, hdims, ranges);

                        double minVal, maxVal;
                        Cv2.MinMaxLoc(hist, out minVal, out maxVal);

                        for (int j = 0; j < hdims[0]; ++j)
                        {
                            int binW = (int)((double)chWidth / hdims[0]);
                            Cv2.Rectangle(histImg, new Point(j * binW, histImg.Rows), new Point((j + 1) * binW, histImg.Rows - (int)(hist.At<float>(j) * (maxVal != 0 ? chHeight/ maxVal : 0.0))), Scalar.All(100));
                        }

                        byte[] imgBytes = img.ToBytes(".png");
                        string base64Img = Convert.ToBase64String(imgBytes);
                        ViewBag.Base64Img = base64Img;

                        byte[] result = histImg.ToBytes(".png");
                        string base64Result = Convert.ToBase64String(result);
                        ViewBag.Base64Result = base64Result;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            return View();
        }