Beispiel #1
0
        /// <summary>
        /// 注目画素の周辺画素の最大値と最小値を求める
        /// </summary>
        /// <param name="img">画像の画素データ</param>
        /// <param name="x">x座標</param>
        /// <param name="y">y座標</param>
        /// <param name="size">周辺画素の探索サイズ。奇数でなければならない</param>
        /// <param name="min">出力される最小値</param>
        /// <param name="max">出力される最大値</param>
        private static void MinMax(Mat img, int x, int y, int size, out byte min, out byte max)
        {
            int size2 = size / 2;

            min = byte.MaxValue;
            max = byte.MinValue;
            int xs = Math.Max(x - size2, 0);
            int xe = Math.Min(x + size2, img.Width);
            int ys = Math.Max(y - size2, 0);
            int ye = Math.Min(y + size2, img.Height);

            using (var tImg = new MatOfByte(img))
            {
                var indexer = tImg.GetIndexer();

                for (int xx = xs; xx < xe; xx++)
                {
                    for (int yy = ys; yy < ye; yy++)
                    {
                        byte v = indexer[yy, xx];
                        if (max < v)
                        {
                            max = v;
                        }
                        else if (min > v)
                        {
                            min = v;
                        }
                    }
                }
            }
        }
Beispiel #2
0
        static Mat doKernel(Mat img, Mat kernel)
        {
            Mat outputImg = new Mat();

            int kernel_size = kernel.Cols;
            int pad         = (kernel_size - 1) / 2;

            img.CopyTo(outputImg);

            MatOfByte mat = new MatOfByte(outputImg);
            var       idx = mat.GetIndexer();

            MatOfByte kernel_mat = new MatOfByte(kernel);
            var       kernel_idx = kernel_mat.GetIndexer();

            Console.WriteLine(kernel_mat.ToCvMat());

            for (int k_row = 0; k_row < kernel_size; k_row++) // k - kernel
            {
                for (int k_col = 0; k_col < kernel_size; k_col++)
                {
                    Console.WriteLine(kernel_idx[k_row, k_col]);
                }
            }

            float sum = 0;

            for (int c_row = pad; c_row < mat.Rows; c_row++) // c- center
            {
                for (int c_col = pad; c_col < mat.Cols - pad; c_col++)
                {
                    sum = 0;

                    for (int k_row = 0; k_row < kernel_size; k_row++) // k - kernel
                    {
                        for (int k_col = 0; k_col < kernel_size; k_col++)
                        {
                            sum += idx[c_row - pad + k_row, c_col - pad + k_col] * kernel_idx[k_row, k_col] *
                                   1 / (kernel_size * kernel_size);
                            var testShit   = idx[c_row - pad + k_row, c_col - pad + k_col].ToString();
                            var testKernel = kernel_idx[k_row, k_col];
                            // Console.WriteLine(testShit + " " + testKernel);
                        }
                    }
                    idx[c_row, c_col] = (byte)sum;
                }
            }

            return(outputImg);
        }
Beispiel #3
0
        public void MatIndexer()
        {
            const byte value          = 123;
            var        img            = new Mat(new Size(10, 10), MatType.CV_8UC1, Scalar.All(value));
            var        imgB           = new MatOfByte(img);
            var        indexer        = imgB.GetIndexer();
            var        generiCIndexer = img.GetGenericIndexer <byte>();

            Assert.Equal(value, indexer[0, 0]);
            Assert.Equal(value, generiCIndexer[0, 0]);

            img.Dispose();
            imgB.Dispose();
        }
Beispiel #4
0
        private static float[] HistogramCalculations(Mat img)
        {
            MatOfByte mat = new MatOfByte(img);
            var       idx = mat.GetIndexer();

            float[] histvalue = new float[256];

            for (int row = 0; row < img.Rows; row++)
            {
                for (int col = 0; col < img.Cols; col++)
                {
                    histvalue[idx[row, col]]++;
                }
            }
            return(histvalue);
        }
Beispiel #5
0
        /// <summary>
        /// Niblackの手法による二値化処理を行う。
        /// </summary>
        /// <param name="imgSrc">入力画像</param>
        /// <param name="imgDst">出力画像</param>
        /// <param name="kernelSize">局所領域のサイズ</param>
        /// <param name="k">係数</param>
#else
        /// <summary>
        /// Binarizes by Niblack's method
        /// </summary>
        /// <param name="src">Input image</param>
        /// <param name="dst">Output image</param>
        /// <param name="kernelSize">Window size</param>
        /// <param name="k">Adequate coefficient</param>
#endif
        public static void Niblack(Mat src, Mat dst, int kernelSize, double k)
        {
            if (src == null)
                throw new ArgumentNullException("src");
            if (dst == null)
                throw new ArgumentNullException("dst");

            // グレースケールのみ
            if (src.Type() != MatType.CV_8UC1)
                throw new ArgumentException("src must be gray scale image");
            if (dst.Type() != MatType.CV_8UC1)
                throw new ArgumentException("dst must be gray scale image");

            // サイズのチェック
            if (kernelSize < 3)
                throw new ArgumentOutOfRangeException("kernelSize", "size must be 3 and above");
            if (kernelSize % 2 == 0)
                throw new ArgumentOutOfRangeException("kernelSize", "size must be odd number");

            int width = src.Width;
            int height = src.Height;
            dst.Create(src.Size(), src.Type());

            using (var tSrcMat = new MatOfByte(src))
            using (var tDstMat = new MatOfByte(dst))
            {
                var tSrc = tSrcMat.GetIndexer();
                var tDst = tDstMat.GetIndexer();

                //for (int y = 0; y < gray.Height; y++)
                MyParallel.For(0, height, delegate(int y)
                {
                    for (int x = 0; x < width; x++)
                    {
                        double m, s;
                        MeanStddev(src, x, y, kernelSize, out m, out s);
                        double threshold = m + k * s;

                        if (tSrc[y, x] < threshold)
                            tDst[y, x] = 0;
                        else
                            tDst[y, x] = 255;
                    }
                }
                );
            }
        }
        public Dictionary <string, BitmapSource> SplitColoredQR(Mat combinedMat)
        {
            Dictionary <string, BitmapSource> outputSplitImages = new Dictionary <string, BitmapSource>();
            Size size  = new Size(combinedMat.Width, combinedMat.Height);
            int  depth = combinedMat.Depth();

            Mat redComponent = Mat.Zeros(size, MatType.CV_8UC1);
            Mat grnComponent = Mat.Zeros(size, MatType.CV_8UC1);
            Mat bluComponent = Mat.Zeros(size, MatType.CV_8UC1);

            // Get mat indexers
            MatOfByte3 mobComb = new MatOfByte3(combinedMat);
            MatOfByte  mobRed  = new MatOfByte(redComponent);
            MatOfByte  mobGrn  = new MatOfByte(grnComponent);
            MatOfByte  mobBlu  = new MatOfByte(bluComponent);

            MatIndexer <Vec3b> indexerComb = mobComb.GetIndexer();
            MatIndexer <byte>  indexerRed  = mobRed.GetIndexer();
            MatIndexer <byte>  indexerGrn  = mobGrn.GetIndexer();
            MatIndexer <byte>  indexerBlu  = mobBlu.GetIndexer();

            for (int y = 0; y < combinedMat.Height; y++)
            {
                for (int x = 0; x < combinedMat.Width; x++)
                {
                    // Assign intensity of red channel from the combined mat to the red component mat
                    indexerRed[y, x] = indexerComb[y, x].Item2;

                    // Assign intensity of green channel from the combined mat to the green component mat
                    indexerGrn[y, x] = indexerComb[y, x].Item1;

                    // Assign intensity of blue channel from the combined mat to the blue component mat
                    indexerBlu[y, x] = indexerComb[y, x].Item0;
                }
            }

            outputSplitImages.Add(QR_TYPE_RED_OUT, Utils.MatToImage(redComponent));
            outputSplitImages.Add(QR_TYPE_GREEN_OUT, Utils.MatToImage(grnComponent));
            outputSplitImages.Add(QR_TYPE_BLUE_OUT, Utils.MatToImage(bluComponent));

            return(outputSplitImages);
        }
        //(practice)
        static public Mat Displace(this Mat Uimg, int sftX, int sftY, bool DispB)    //位置移動
        {
            Size sz = Uimg.Size();
            int  W = sz.Width, H = sz.Height;
            Mat  UimgD = new Mat(sz, MatType.CV_8UC1, Scalar.All(255));

            {
                using (MatOfByte imgMBS = new MatOfByte(Uimg))
                    using (MatOfByte imgMBD = new MatOfByte(UimgD)){
                        var IdxS = imgMBS.GetIndexer();
                        var IdxD = imgMBD.GetIndexer();
                        for (int y = 0; y < H; y++)
                        {
                            int yy = y + sftY;
                            if (yy < 0 || yy >= H)
                            {
                                continue;
                            }
                            for (int x = 0; x < W; x++)
                            {
                                int xx = x + sftX;
                                if (xx < 0 || xx >= W - 1)
                                {
                                    continue;
                                }
                                IdxD[yy, xx] = IdxS[y, x];
                            }
                        }
                    }
            }

            if (DispB)
            {
                //    using(new Window("origin",WindowMode.Normal,Uimg))
                using (new Window("Displaced", WindowMode.Normal, UimgD)){ Cv2.WaitKey(0); }
            }
            return(UimgD);
        }
        static public Mat RandomWhite(this Mat Uimg, double rndP, bool DispB)
        {
            Size sz = Uimg.Size();
            int  W = sz.Width, H = sz.Height, h2 = H / 2;
            Mat  UimgD = Uimg.Clone(); // new Mat(sz,MatType.CV_8UC1,Scalar.All(255));

            {
                using (MatOfByte imgMBS = new MatOfByte(Uimg))
                    using (MatOfByte imgMBD = new MatOfByte(UimgD)){
                        var IdxS = imgMBS.GetIndexer();
                        var IdxD = imgMBD.GetIndexer();
                        for (int y = 0; y < H; y++)
                        {
                            for (int x = 0; x < W; x++)
                            {
                                if (IdxS[y, x] == 255)
                                {
                                    continue;
                                }
                                if (rndRW.NextDouble() < rndP)
                                {
                                    IdxD[y, x] = 255;
                                }
                            }
                        }
                    }
            }

            if (DispB)
            {
                //    using(new Window("origin",WindowMode.Normal,Uimg))
                using (new Window("RandomWhite", WindowMode.Normal, UimgD)){ Cv2.WaitKey(0); }
            }

            return(UimgD);
        }
Beispiel #9
0
        /// <summary>
        /// 注目画素の周辺画素の平均値と標準偏差を求める
        /// </summary>
        /// <param name="img">画像の画素データ</param>
        /// <param name="x">x座標</param>
        /// <param name="y">y座標</param>
        /// <param name="size">周辺画素の探索サイズ。奇数でなければならない</param>
        /// <param name="mean">出力される平均</param>
        /// <param name="stddev">出力される標準偏差</param>
        private static void MeanStddev(Mat img, int x, int y, int size, out double mean, out double stddev)
        {
            int  count = 0;
            int  sum   = 0;
            int  sqsum = 0;
            int  size2 = size / 2;
            int  xs    = Math.Max(x - size2, 0);
            int  xe    = Math.Min(x + size2, img.Width);
            int  ys    = Math.Max(y - size2, 0);
            int  ye    = Math.Min(y + size2, img.Height);
            byte v;

            using (var tImg = new MatOfByte(img))
            {
                var indexer = tImg.GetIndexer();
                for (int xx = xs; xx < xe; xx++)
                {
                    for (int yy = ys; yy < ye; yy++)
                    {
                        v      = indexer[yy, xx];
                        sum   += v;
                        sqsum += v * v;
                        count++;
                    }
                }
            }

            mean = (double)sum / count;
            double var = ((double)sqsum / count) - (mean * mean);

            if (var < 0.0)
            {
                var = 0.0;
            }
            stddev = Math.Sqrt(var);
        }
Beispiel #10
0
        public bool MaskOutline(Mat whiteLightImage, Mat edgeMaskImage, out Mat mergedImage)
        {
            bool result = false;

            mergedImage = whiteLightImage.Clone();

            try
            {
                //convert white mask outlines to purple color outlines
                MatOfByte matb        = new MatOfByte(edgeMaskImage);
                var       indexerGray = matb.GetIndexer();

                MatOfByte3 mat3         = new MatOfByte3(mergedImage);
                var        indexerColor = mat3.GetIndexer();

                for (int y = 0; y < edgeMaskImage.Height; y++)
                {
                    for (int x = 0; x < edgeMaskImage.Width; x++)
                    {
                        byte edge = indexerGray[y, x];
                        if (edge == 255)                                   //white
                        {
                            indexerColor[y, x] = new Vec3b(255, 128, 255); //purple
                        }
                    }
                }


                result = true;
            }
            catch (Exception ex)
            {
            }

            return(result);
        }
Beispiel #11
0
        static Mat doMedianFilter(Mat img, Mat kernel)
        {
            Mat outputImg = new Mat();

            int kernel_size = kernel.Cols;
            int pad         = (kernel_size - 1) / 2;

            img.CopyTo(outputImg);

            MatOfByte mat = new MatOfByte(outputImg);
            var       idx = mat.GetIndexer();

            int k = 0;

            decimal[] vector = new decimal[kernel_size * kernel_size];

            for (int c_row = pad; c_row < mat.Rows - pad; c_row++) // c- center
            {
                for (int c_col = pad; c_col < mat.Cols - pad; c_col++)
                {
                    k = 0;
                    for (int k_row = 0; k_row < kernel_size; k_row++) // k - kernel
                    {
                        for (int k_col = 0; k_col < kernel_size; k_col++)
                        {
                            vector[k] = idx[c_row - pad + k_row, c_col - pad + k_col];
                            k++;
                        }
                    }

                    idx[c_row, c_col] = (byte)Median(vector);
                }
            }

            return(outputImg);
        }
Beispiel #12
0
        /// <summary>
        /// Nickの手法による二値化処理を行う。
        /// </summary>
        /// <param name="imgSrc">入力画像</param>
        /// <param name="imgDst">出力画像</param>
        /// <param name="kernelSize">局所領域のサイズ</param>
        /// <param name="k">係数</param>
#else
        /// <summary>
        /// Binarizes by Nick's method
        /// </summary>
        /// <param name="src">Input image</param>
        /// <param name="dst">Output image</param>
        /// <param name="kernelSize">Window size</param>
        /// <param name="k">Adequate coefficient</param>
#endif
        public static void Nick(Mat src, Mat dst, int kernelSize, double k)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            if (dst == null)
            {
                throw new ArgumentNullException("dst");
            }

            // グレースケールのみ
            if (src.Type() != MatType.CV_8UC1)
            {
                throw new ArgumentException("src must be gray scale image");
            }
            if (dst.Type() != MatType.CV_8UC1)
            {
                throw new ArgumentException("dst must be gray scale image");
            }

            // サイズのチェック
            if (kernelSize < 3)
            {
                throw new ArgumentOutOfRangeException("kernelSize", "size must be 3 and above");
            }
            if (kernelSize % 2 == 0)
            {
                throw new ArgumentOutOfRangeException("kernelSize", "size must be odd number");
            }

            int borderSize = kernelSize / 2;
            int width      = src.Width;
            int height     = src.Height;

            dst.Create(src.Size(), src.Type());

            using (var tempMat = new Mat(height + (borderSize * 2), width + (borderSize * 2), src.Type()))
                using (var sumMat = new Mat(tempMat.Height + 1, tempMat.Width + 1, MatType.CV_64FC1, 1))
                    using (var sqSumMat = new Mat(tempMat.Height + 1, tempMat.Width + 1, MatType.CV_64FC1, 1))
                    {
                        Cv2.CopyMakeBorder(src, tempMat, borderSize, borderSize, borderSize, borderSize, BorderTypes.Replicate, Scalar.All(0));
                        Cv2.Integral(tempMat, sumMat, sqSumMat);

                        using (var tSrcMat = new MatOfByte(src))
                            using (var tDstMat = new MatOfByte(dst))
                                using (var tSumMat = new MatOfDouble(sumMat))
                                    using (var tSqSumMat = new MatOfDouble(sqSumMat))
                                    {
                                        var tSrc   = tSrcMat.GetIndexer();
                                        var tDst   = tDstMat.GetIndexer();
                                        var tSum   = tSumMat.GetIndexer();
                                        var tSqSum = tSqSumMat.GetIndexer();

                                        int ylim         = height + borderSize;
                                        int xlim         = width + borderSize;
                                        int kernelPixels = kernelSize * kernelSize;
                                        for (int y = borderSize; y < ylim; y++)
                                        {
                                            for (int x = borderSize; x < xlim; x++)
                                            {
                                                int    x1    = x - borderSize;
                                                int    y1    = y - borderSize;
                                                int    x2    = x + borderSize + 1;
                                                int    y2    = y + borderSize + 1;
                                                double sum   = tSum[y2, x2] - tSum[y2, x1] - tSum[y1, x2] + tSum[y1, x1];
                                                double sqsum = tSqSum[y2, x2] - tSqSum[y2, x1] - tSqSum[y1, x2] + tSqSum[y1, x1];
                                                double mean  = sum / kernelPixels;
                                                double term  = (sqsum - mean * mean) / kernelPixels;
                                                if (term < 0.0)
                                                {
                                                    term = 0.0;
                                                }
                                                term = Math.Sqrt(term);

                                                double threshold = mean + k * term;
                                                if (tSrc[y - borderSize, x - borderSize] < threshold)
                                                {
                                                    tDst[y - borderSize, x - borderSize] = 0;
                                                }
                                                else
                                                {
                                                    tDst[y - borderSize, x - borderSize] = 255;
                                                }
                                            }
                                        }
                                    }
                    }
        }
Beispiel #13
0
        /// <summary>
        /// Bernsenの手法による二値化処理を行う。
        /// </summary>
        /// <param name="imgSrc">入力画像</param>
        /// <param name="imgDst">出力画像</param>
        /// <param name="kernelSize">局所領域のサイズ</param>
        /// <param name="constrastMin">この数値以下のコントラストの領域は背景領域とみなす</param>
        /// <param name="bgThreshold">背景領域と見なされた領域に適用する閾値(背景領域以外では、適応的に閾値を求める)</param>
#else
        /// <summary>
        /// Binarizes by Bernsen's method
        /// </summary>
        /// <param name="src">Input image</param>
        /// <param name="dst">Output image</param>
        /// <param name="kernelSize">Window size</param>
        /// <param name="constrastMin">Adequate coefficient</param>
        /// <param name="bgThreshold">Adequate coefficient</param>
#endif
        public static void Bernsen(Mat src, Mat dst, int kernelSize, byte constrastMin, byte bgThreshold)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            if (dst == null)
            {
                throw new ArgumentNullException("dst");
            }

            // グレースケールのみ
            if (src.Type() != MatType.CV_8UC1)
            {
                throw new ArgumentException("src must be gray scale image");
            }
            if (dst.Type() != MatType.CV_8UC1)
            {
                throw new ArgumentException("dst must be gray scale image");
            }

            // サイズのチェック
            if (kernelSize < 3)
            {
                throw new ArgumentOutOfRangeException("kernelSize", "size must be 3 and above");
            }
            if (kernelSize % 2 == 0)
            {
                throw new ArgumentOutOfRangeException("kernelSize", "size must be odd number");
            }

            int width  = src.Width;
            int height = src.Height;

            dst.Create(src.Size(), src.Type());

            using (var tSrcMat = new MatOfByte(src))
                using (var tDstMat = new MatOfByte(dst))
                {
                    var tSrc = tSrcMat.GetIndexer();
                    var tDst = tDstMat.GetIndexer();

                    for (int y = 0; y < height; y++)
                    {
                        for (int x = 0; x < width; x++)
                        {
                            byte min, max;
                            MinMax(src, x, y, kernelSize, out min, out max);

                            int  contrast = max - min;
                            byte threshold;
                            if (contrast < constrastMin)
                            {
                                threshold = bgThreshold;
                            }
                            else
                            {
                                threshold = (byte)((max + min) / 2);
                            }

                            if (tSrc[y, x] <= threshold)
                            {
                                tDst[y, x] = 0;
                            }
                            else
                            {
                                tDst[y, x] = 255;
                            }
                        }
                    }
                }
        }
Beispiel #14
0
        /// <summary>
        /// Niblackの手法による二値化処理を行う。
        /// </summary>
        /// <param name="imgSrc">入力画像</param>
        /// <param name="imgDst">出力画像</param>
        /// <param name="kernelSize">局所領域のサイズ</param>
        /// <param name="k">係数</param>
#else
        /// <summary>
        /// Binarizes by Niblack's method
        /// </summary>
        /// <param name="src">Input image</param>
        /// <param name="dst">Output image</param>
        /// <param name="kernelSize">Window size</param>
        /// <param name="k">Adequate coefficient</param>
#endif
        public static void Niblack(Mat src, Mat dst, int kernelSize, double k)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            if (dst == null)
            {
                throw new ArgumentNullException("dst");
            }

            // グレースケールのみ
            if (src.Type() != MatType.CV_8UC1)
            {
                throw new ArgumentException("src must be gray scale image");
            }
            if (dst.Type() != MatType.CV_8UC1)
            {
                throw new ArgumentException("dst must be gray scale image");
            }

            // サイズのチェック
            if (kernelSize < 3)
            {
                throw new ArgumentOutOfRangeException("kernelSize", "size must be 3 and above");
            }
            if (kernelSize % 2 == 0)
            {
                throw new ArgumentOutOfRangeException("kernelSize", "size must be odd number");
            }

            int width  = src.Width;
            int height = src.Height;

            dst.Create(src.Size(), src.Type());

            using (var tSrcMat = new MatOfByte(src))
                using (var tDstMat = new MatOfByte(dst))
                {
                    var tSrc = tSrcMat.GetIndexer();
                    var tDst = tDstMat.GetIndexer();

                    //for (int y = 0; y < gray.Height; y++)
                    MyParallel.For(0, height, delegate(int y)
                    {
                        for (int x = 0; x < width; x++)
                        {
                            double m, s;
                            MeanStddev(src, x, y, kernelSize, out m, out s);
                            double threshold = m + k * s;

                            if (tSrc[y, x] < threshold)
                            {
                                tDst[y, x] = 0;
                            }
                            else
                            {
                                tDst[y, x] = 255;
                            }
                        }
                    }
                                   );
                }
        }
Beispiel #15
0
        /// <summary>
        /// Niblackの手法による二値化処理を行う(高速だが、メモリを多く消費するバージョン)。
        /// </summary>
        /// <param name="imgSrc">入力画像</param>
        /// <param name="imgDst">出力画像</param>
        /// <param name="kernelSize">局所領域のサイズ</param>
        /// <param name="k">係数</param>
#else
        /// <summary>
        /// Binarizes by Niblack's method (This is faster but memory-hogging)
        /// </summary>
        /// <param name="src">Input image</param>
        /// <param name="dst">Output image</param>
        /// <param name="kernelSize">Window size</param>
        /// <param name="k">Adequate coefficient</param>
#endif
        public static void NiblackFast(Mat src, Mat dst, int kernelSize, double k)
        {
            if (src == null)
                throw new ArgumentNullException("src");
            if (dst == null)
                throw new ArgumentNullException("dst");

            // グレースケールのみ
            if (src.Type() != MatType.CV_8UC1)
                throw new ArgumentException("src must be gray scale image");
            if (dst.Type() != MatType.CV_8UC1)
                throw new ArgumentException("dst must be gray scale image");

            // サイズのチェック
            if (kernelSize < 3)
                throw new ArgumentOutOfRangeException("kernelSize", "size must be 3 and above");
            if (kernelSize % 2 == 0)
                throw new ArgumentOutOfRangeException("kernelSize", "size must be odd number");

            int borderSize = kernelSize / 2;
            int width = src.Width;
            int height = src.Height;
            dst.Create(src.Size(), src.Type());

            using (var tempMat = new Mat(height + (borderSize * 2), width + (borderSize * 2), src.Type()))
            using (var sumMat = new Mat(tempMat.Height + 1, tempMat.Width + 1, MatType.CV_64FC1, 1))
            using (var sqSumMat = new Mat(tempMat.Height + 1, tempMat.Width + 1, MatType.CV_64FC1, 1))
            {
                Cv2.CopyMakeBorder(src, tempMat, borderSize, borderSize, borderSize, borderSize, BorderTypes.Replicate, Scalar.All(0));
                Cv2.Integral(tempMat, sumMat, sqSumMat);

                using (var tSrcMat = new MatOfByte(src))
                using (var tDstMat = new MatOfByte(dst))
                using (var tSumMat = new MatOfDouble(sumMat))
                using (var tSqSumMat = new MatOfDouble(sqSumMat))
                {
                    var tSrc = tSrcMat.GetIndexer();
                    var tDst = tDstMat.GetIndexer();
                    var tSum = tSumMat.GetIndexer();
                    var tSqSum = tSqSumMat.GetIndexer();

                    int ylim = height + borderSize;
                    int xlim = width + borderSize;
                    int kernelPixels = kernelSize * kernelSize;
                    for (int y = borderSize; y < ylim; y++)
                    {
                        for (int x = borderSize; x < xlim; x++)
                        {
                            int x1 = x - borderSize;
                            int y1 = y - borderSize;
                            int x2 = x + borderSize + 1;
                            int y2 = y + borderSize + 1;
                            double sum = tSum[y2, x2] - tSum[y2, x1] - tSum[y1, x2] + tSum[y1, x1];
                            double sqsum = tSqSum[y2, x2] - tSqSum[y2, x1] - tSqSum[y1, x2] + tSqSum[y1, x1];
                            double mean = sum / kernelPixels;
                            double var = (sqsum / kernelPixels) - (mean * mean);
                            if (var < 0.0) var = 0.0;
                            double stddev = Math.Sqrt(var);

                            double threshold = mean + k * stddev;
                            if (tSrc[y - borderSize, x - borderSize] < threshold)
                                tDst[y - borderSize, x - borderSize] = 0;
                            else
                                tDst[y - borderSize, x - borderSize] = 255;
                        }
                    }
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// 注目画素の周辺画素の最大値と最小値を求める
        /// </summary>
        /// <param name="img">画像の画素データ</param>
        /// <param name="x">x座標</param>
        /// <param name="y">y座標</param>
        /// <param name="size">周辺画素の探索サイズ。奇数でなければならない</param>
        /// <param name="min">出力される最小値</param>
        /// <param name="max">出力される最大値</param>
        private static void MinMax(Mat img, int x, int y, int size, out byte min, out byte max)
        {
            int size2 = size / 2;
            min = byte.MaxValue;
            max = byte.MinValue;
            int xs = Math.Max(x - size2, 0);
            int xe = Math.Min(x + size2, img.Width);
            int ys = Math.Max(y - size2, 0);
            int ye = Math.Min(y + size2, img.Height);

            using (var tImg = new MatOfByte(img))
            {
                var indexer = tImg.GetIndexer();

                for (int xx = xs; xx < xe; xx++)
                {
                    for (int yy = ys; yy < ye; yy++)
                    {
                        byte v = indexer[yy, xx];
                        if (max < v)
                            max = v;
                        else if (min > v)
                            min = v;
                    }
                }
            }
        }
Beispiel #17
0
        /// <summary>
        /// 注目画素の周辺画素の平均値と標準偏差を求める
        /// </summary>
        /// <param name="img">画像の画素データ</param>
        /// <param name="x">x座標</param>
        /// <param name="y">y座標</param>
        /// <param name="size">周辺画素の探索サイズ。奇数でなければならない</param>
        /// <param name="mean">出力される平均</param>
        /// <param name="stddev">出力される標準偏差</param>
        private static void MeanStddev(Mat img, int x, int y, int size, out double mean, out double stddev)
        {
            int count = 0;
            int sum = 0;
            int sqsum = 0;
            int size2 = size / 2;
            int xs = Math.Max(x - size2, 0);
            int xe = Math.Min(x + size2, img.Width);
            int ys = Math.Max(y - size2, 0);
            int ye = Math.Min(y + size2, img.Height);
            byte v;

            using (var tImg = new MatOfByte(img))
            {
                var indexer = tImg.GetIndexer();
                for (int xx = xs; xx < xe; xx++)
                {
                    for (int yy = ys; yy < ye; yy++)
                    {
                        v = indexer[yy, xx];
                        sum += v;
                        sqsum += v*v;
                        count++;
                    }
                }
            }

            mean = (double)sum / count;
            double var = ((double)sqsum / count) - (mean * mean);
            if (var < 0.0) var = 0.0;
            stddev = Math.Sqrt(var);
        }
Beispiel #18
0
        /// <summary>
        /// Bernsenの手法による二値化処理を行う。
        /// </summary>
        /// <param name="imgSrc">入力画像</param>
        /// <param name="imgDst">出力画像</param>
        /// <param name="kernelSize">局所領域のサイズ</param>
        /// <param name="constrastMin">この数値以下のコントラストの領域は背景領域とみなす</param>
        /// <param name="bgThreshold">背景領域と見なされた領域に適用する閾値(背景領域以外では、適応的に閾値を求める)</param>
#else
        /// <summary>
        /// Binarizes by Bernsen's method
        /// </summary>
        /// <param name="src">Input image</param>
        /// <param name="dst">Output image</param>
        /// <param name="kernelSize">Window size</param>
        /// <param name="constrastMin">Adequate coefficient</param>
        /// <param name="bgThreshold">Adequate coefficient</param>
#endif
        public static void Bernsen(Mat src, Mat dst, int kernelSize, byte constrastMin, byte bgThreshold)
        {
            if (src == null)
                throw new ArgumentNullException("src");
            if (dst == null)
                throw new ArgumentNullException("dst");

            // グレースケールのみ
            if (src.Type() != MatType.CV_8UC1)
                throw new ArgumentException("src must be gray scale image");
            if (dst.Type() != MatType.CV_8UC1)
                throw new ArgumentException("dst must be gray scale image");

            // サイズのチェック
            if (kernelSize < 3)
                throw new ArgumentOutOfRangeException("kernelSize", "size must be 3 and above");
            if (kernelSize % 2 == 0)
                throw new ArgumentOutOfRangeException("kernelSize", "size must be odd number");

            int width = src.Width;
            int height = src.Height;
            dst.Create(src.Size(), src.Type());

            using (var tSrcMat = new MatOfByte(src))
            using (var tDstMat = new MatOfByte(dst))
            {
                var tSrc = tSrcMat.GetIndexer();
                var tDst = tDstMat.GetIndexer();

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        byte min, max;
                        MinMax(src, x, y, kernelSize, out min, out max);

                        int contrast = max - min;
                        byte threshold;
                        if (contrast < constrastMin)
                            threshold = bgThreshold;
                        else
                            threshold = (byte)((max + min) / 2);

                        if (tSrc[y, x] <= threshold)
                            tDst[y, x] = 0;
                        else
                            tDst[y, x] = 255;
                    }
                }
            }

        }
Beispiel #19
0
        public static float[] GetArray(this Mat self, float[] buffer = null, bool bgr2rgb = true)
        {
            int width  = self.Width;
            int height = self.Height;

            float[] f;
            if (buffer == null)
            {
                f = new float[width * height * self.Channel];
            }
            else
            {
                if (buffer.Length < width * height * self.Channel)
                {
                    throw new ArgumentOutOfRangeException(nameof(buffer));
                }
                f = buffer;
            }

            if (self.Channel == 3)
            {
                using (MatOfByte3 matByte = new MatOfByte3())
                {
                    self.CopyTo(matByte);

                    var indexer = matByte.GetIndexer();
                    int i       = 0;
                    for (int y = 0; y < height; y++)
                    {
                        for (int x = 0; x < width; x++)
                        {
                            Vec3b color = indexer[y, x];
                            if (bgr2rgb)
                            {
                                f[i] = color.Item2;
                                i++;
                                f[i] = color.Item1;
                                i++;
                                f[i] = color.Item0;
                                i++;
                            }
                            else
                            {
                                f[i] = color.Item0;
                                i++;
                                f[i] = color.Item1;
                                i++;
                                f[i] = color.Item2;
                                i++;
                            }
                        }
                    }
                }
            }
            else if (self.Channel == 1)
            {
                using (var matByte = new MatOfByte())
                {
                    self.CopyTo(matByte);

                    var w       = self.Width;
                    var h       = self.Height;
                    var indexer = matByte.GetIndexer();
                    int i       = 0;
                    for (int y = 0; y < h; y++)
                    {
                        for (int x = 0; x < w; x++)
                        {
                            var pixel = indexer[y, x];
                            f[i] = pixel;
                            i++;
                        }
                    }
                }
            }
            else
            {
                throw new Exception("not supported channel");
            }

            return(f);
        }
        public Dictionary <string, string> DecodeQRCode(QRCodeProperties qrCodeProps, QRColorMode colorMode)
        {
            outputMessages = new Dictionary <string, string>();

            if (colorMode == QRColorMode.Grayscale)
            {
                string decodedBinary = string.Empty;
                outputMats.TryGetValue(QR_TYPE_MONOCHROME, out Mat qrMatMono);

                // Get mat indexer
                MatOfByte         mob1        = new MatOfByte(qrMatMono);
                MatIndexer <byte> indexerByte = mob1.GetIndexer();

                // Read decoded strings
                int     bitsPerChar   = 7;
                int     messageLength = inputMessage.Length;
                decimal messageChars  = messageLength / bitsPerChar;

                // Read decoded binary
                for (int i = 0; i < messageChars; i++)
                {
                    decodedBinary += ReadMonochromePixels(indexerByte, i, bitsPerChar);
                }

                // Add decoded messag to output list
                outputMessages.Add(QR_TYPE_MONOCHROME, decodedBinary);

                return(outputMessages);
            }
            else if (colorMode == QRColorMode.Color)
            {
                string decodedBinaryRed      = string.Empty;
                string decodedBinaryGreen    = string.Empty;
                string decodedBinaryBlue     = string.Empty;
                string decodedBinaryCombined = string.Empty;

                outputMats.TryGetValue(QR_TYPE_COMBINED, out Mat qrMatCombined);

                // Get mat indexer
                MatOfByte3         mobComb        = new MatOfByte3(qrMatCombined);
                MatIndexer <Vec3b> indexerMobComb = mobComb.GetIndexer();

                // Read decoded strings
                int     bitsPerChar          = 7;
                int     messageLength        = inputMessage.Length;
                decimal messageChars         = messageLength / bitsPerChar;
                int     coloredMessageLength = (int)Math.Ceiling(messageChars / 3);

                for (int i = 0; i < coloredMessageLength; i++)
                {
                    string tempRed   = ReadColorPixels(indexerMobComb, QR_TYPE_RED, i, bitsPerChar);
                    string tempGreen = ReadColorPixels(indexerMobComb, QR_TYPE_GREEN, i, bitsPerChar);
                    string tempBlue  = ReadColorPixels(indexerMobComb, QR_TYPE_BLUE, i, bitsPerChar);

                    decodedBinaryRed   += tempRed;
                    decodedBinaryGreen += tempGreen;
                    decodedBinaryBlue  += tempBlue;

                    decodedBinaryCombined += tempRed;
                    decodedBinaryCombined += tempGreen;
                    decodedBinaryCombined += tempBlue;
                }

                // Add output messages
                outputMessages.Add(QR_TYPE_RED, decodedBinaryRed);
                outputMessages.Add(QR_TYPE_GREEN, decodedBinaryGreen);
                outputMessages.Add(QR_TYPE_BLUE, decodedBinaryBlue);
                outputMessages.Add(QR_TYPE_COMBINED, decodedBinaryCombined);

                return(outputMessages);
            }

            return(null);
        }
        public Dictionary <string, BitmapSource> GenerateQRCore(string inputMessage, QRCodeProperties qrCodeProps, QRColorMode colorMode)
        {
            outputImages      = new Dictionary <string, BitmapSource>();
            outputMats        = new Dictionary <string, Mat>();
            matSearchPixels   = new List <Point>();
            this.inputMessage = inputMessage;

            CalculateSearchPoint(qrCodeProps);

            if (colorMode == QRColorMode.Grayscale)
            {
                // Generate empty mat and set all pixels to white
                qrMatMono = Mat.Zeros(new Size(qrCodeProps.ImgSize.Width, qrCodeProps.ImgSize.Height), MatType.CV_8UC1);
                //qrMat.SetTo(Scalar.White);

                // Get mat indexer
                MatOfByte         mob1        = new MatOfByte(qrMatMono);
                MatIndexer <byte> indexerByte = mob1.GetIndexer();

                int stringIndex = -1;
                for (int y = 0; y < qrCodeProps.CellsPerDim * qrCodeProps.CellSize; y += qrCodeProps.CellSize)
                {
                    for (int x = 0; x < qrCodeProps.CellsPerDim * qrCodeProps.CellSize; x += qrCodeProps.CellSize)
                    {
                        // If message is done reading
                        if (++stringIndex + 1 > inputMessage.Length)
                        {
                            break;
                        }

                        // If bit is 0, skip this cell
                        if (inputMessage[stringIndex].Equals('0'))
                        {
                            continue;
                        }

                        // If bit is 1, color the cell
                        else if (inputMessage[stringIndex].Equals('1'))
                        {
                            for (int i = y; i < y + qrCodeProps.CellSize; i++)
                            {
                                for (int j = x; j < x + qrCodeProps.CellSize; j++)
                                {
                                    indexerByte[i, j] = LUM_INTENSITY_MAX;
                                }
                            }
                        }
                    }
                }

                // Add image and mat to output lists
                outputImages.Add(QR_TYPE_MONOCHROME, Utils.MatToImage(qrMatMono));
                outputMats.Add(QR_TYPE_MONOCHROME, qrMatMono);

                // Return images to UI
                return(outputImages);
            }
            else if (colorMode == QRColorMode.Color)
            {
                // Generate empty mats and fill with white
                Mat qrRedMat   = Mat.Zeros(new Size(qrCodeProps.ImgSize.Width, qrCodeProps.ImgSize.Height), MatType.CV_8UC3);
                Mat qrGreenMat = Mat.Zeros(new Size(qrCodeProps.ImgSize.Width, qrCodeProps.ImgSize.Height), MatType.CV_8UC3);
                Mat qrBlueMat  = Mat.Zeros(new Size(qrCodeProps.ImgSize.Width, qrCodeProps.ImgSize.Height), MatType.CV_8UC3);
                //qrCyanMat.SetTo(Scalar.White);
                //qrMagentaMat.SetTo(Scalar.White);
                //qrYellowMat.SetTo(Scalar.White);

                // Get mat indexers
                MatOfByte3 mobRed   = new MatOfByte3(qrRedMat);
                MatOfByte3 mobGreen = new MatOfByte3(qrGreenMat);
                MatOfByte3 mobBlue  = new MatOfByte3(qrBlueMat);

                MatIndexer <Vec3b> indexerMobRed   = mobRed.GetIndexer();
                MatIndexer <Vec3b> indexerMobGreen = mobGreen.GetIndexer();
                MatIndexer <Vec3b> indexerMobBlue  = mobBlue.GetIndexer();

                // Split message thrice
                int    bitsPerChar     = 7;
                int    messageChars    = inputMessage.Length / bitsPerChar;
                string messageForRed   = string.Empty;
                string messageForGreen = string.Empty;
                string messageForBlue  = string.Empty;

                for (int i = 0; i < messageChars; i++)
                {
                    if (i % 3 == 0)
                    {
                        for (int j = 0; j < bitsPerChar; j++)
                        {
                            messageForRed += inputMessage[(i * bitsPerChar) + j];
                        }
                    }

                    else if (i % 3 == 1)
                    {
                        for (int j = 0; j < bitsPerChar; j++)
                        {
                            messageForGreen += inputMessage[(i * bitsPerChar) + j];
                        }
                    }

                    else if (i % 3 == 2)
                    {
                        for (int j = 0; j < bitsPerChar; j++)
                        {
                            messageForBlue += inputMessage[(i * bitsPerChar) + j];
                        }
                    }
                }

                indexerMobRed   = WriteColorComponent(messageForRed, qrCodeProps, indexerMobRed, COLOR_RED);
                indexerMobGreen = WriteColorComponent(messageForGreen, qrCodeProps, indexerMobGreen, COLOR_GREEN);
                indexerMobBlue  = WriteColorComponent(messageForBlue, qrCodeProps, indexerMobBlue, COLOR_BLUE);

                Mat combinedMat = qrRedMat + qrGreenMat + qrBlueMat;

                // Add image and mats to output lists
                outputImages.Add(QR_TYPE_COMBINED, Utils.MatToImage(combinedMat));
                outputImages.Add(QR_TYPE_RED, Utils.MatToImage(qrRedMat));
                outputImages.Add(QR_TYPE_GREEN, Utils.MatToImage(qrGreenMat));
                outputImages.Add(QR_TYPE_BLUE, Utils.MatToImage(qrBlueMat));
                outputMats.Add(QR_TYPE_COMBINED, combinedMat);
                outputMats.Add(QR_TYPE_RED, qrRedMat);
                outputMats.Add(QR_TYPE_GREEN, qrGreenMat);
                outputMats.Add(QR_TYPE_BLUE, qrBlueMat);

                return(outputImages);
            }

            return(null);
        }
Beispiel #22
0
        static void Main(string[] args)
        {
            // Used to check memory leak
            //for (int i = 0; i < 1000; i++)
            using (var state = new ThreadLocal <FormExtractionHandle>(NativeFormExtraction.CreateFormExtraction))
            {
                GC.Collect();
                List <string> pathFiles = GetSamplesAndCleanUpResults();

                // For testing:
                pathFiles = pathFiles.Where(m => m.Contains("form9")).ToList();

                int numThread      = 1;            // Environment.ProcessorCount;
                var showDebugImage = true;         // If true, you may want to use: numThread = 1.

                Parallel.ForEach(pathFiles, new ParallelOptions {
                    MaxDegreeOfParallelism = numThread
                }, pathFile =>
                {
                    FormExtractionHandle handle = state.Value;

                    NativeFormExtraction.SetOptions(handle, 800, 25, 15, 5, 20000, 50000, showDebugImage);

                    var resizeWidth = 800;
                    var orig        = new Mat(pathFile);
                    var image       = new Mat(pathFile, ImreadModes.GrayScale);

                    Cv2.AdaptiveThreshold(image, image, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 9, 4);

                    // Resize image if too large.
                    if (image.Width > resizeWidth)
                    {
                        var height = resizeWidth * image.Height / image.Width;
                        Cv2.Resize(image, image, new Size(resizeWidth, height));
                    }

                    Cv2.BitwiseNot(image, image);
                    Cv2.Dilate(image, image, Cv2.GetStructuringElement(MorphShapes.Cross, new Size(2, 2)));

                    MatOfByte mat             = new MatOfByte(image);
                    MatIndexer <byte> indexer = mat.GetIndexer();

                    var row      = image.Height;
                    var col      = image.Width;
                    Mat newImage = new Mat(row, col, MatType.CV_8UC3);
                    newImage.SetTo(Scalar.Black);

                    // We must determine if it "may" be an interesting blob.
                    Stopwatch watch = new Stopwatch();
                    watch.Start();

                    int[] imgData = new int[row * col];
                    for (int y = 0; y < row; y++)
                    {
                        for (int x = 0; x < col; x++)
                        {
                            imgData[y + x * row] = indexer[y, x];
                        }
                    }

                    var result = NativeFormExtraction.RunFormExtraction(handle, imgData, row, col);
                    if (result != 0)
                    {
                        throw new Exception("Unknown error occured with the function: RunFormExtraction");
                    }
                    watch.Stop();
                    Console.WriteLine("Duration: " + watch.Elapsed);

                    if (showDebugImage)
                    {
                        var debugImg = NativeFormExtraction.GetDebugImage(handle, row * col);

                        var img = CreateImage(debugImg, row, col, hasColor: true);
                        Cv2.BitwiseOr(newImage, img, newImage);

                        Cv2.BitwiseNot(image, image);
                        int width  = 400;
                        var height = width * image.Height / image.Width;
                        Cv2.Resize(orig, orig, new Size(width, height));
                        Cv2.Resize(image, image, new Size(width, height));
                        Cv2.Resize(newImage, newImage, new Size(width, height));

                        using (new Window("orig", orig))
                            using (new Window("pre", image))
                                using (new Window("post", newImage))
                                {
                                    Cv2.WaitKey();
                                    Cv2.DestroyAllWindows();
                                }
                    }

                    // Dispose.
                    orig.Dispose();
                    image.Dispose();
                    newImage.Dispose();
                    mat.Dispose();
                });
            }

            Console.WriteLine("End");
            Console.ReadLine();
        }
Beispiel #23
0
        public static FormExtractionResult ProcessImage(string filename, FormExtractionOptions options = null)
        {
            if (options == null)
            {
                // Assume recommanded parameters.
                options = new FormExtractionOptions();
            }

            var orig  = new Mat(filename);
            var image = new Mat(filename, ImreadModes.GrayScale);

            Cv2.AdaptiveThreshold(image, image, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 9, 4);

            // Resize image if too large.
            if (image.Width > options.ResizeWidth)
            {
                var height = options.ResizeWidth * image.Height / image.Width;
                Cv2.Resize(image, image, new Size(options.ResizeWidth, height));
            }

            Cv2.BitwiseNot(image, image);
            Cv2.Dilate(image, image, Cv2.GetStructuringElement(MorphShapes.Cross, new Size(2, 2)));

            MatOfByte         mat     = new MatOfByte(image);
            MatIndexer <byte> indexer = mat.GetIndexer();

            var row      = image.Height;
            var col      = image.Width;
            Mat newImage = new Mat(row, col, MatType.CV_8UC3);

            newImage.SetTo(Scalar.Black);

            // We must determine if it "may" be an interesting blob.
            Stopwatch watch = new Stopwatch();

            watch.Start();

            int[] imgData = new int[row * col];
            for (int y = 0; y < row; y++)
            {
                for (int x = 0; x < col; x++)
                {
                    imgData[y + x * row] = indexer[y, x];
                }
            }

            var result = HasBoxes(imgData, row, col, options);

            watch.Stop();
            result.Duration = watch.Elapsed;

            // Preview
            if (result.Boxes.Any() && image.Width != 0 && options.ShowDebugImage)
            {
                var img = CreateImage(result.DebugImg, hasColor: true);
                Cv2.BitwiseOr(newImage, img, newImage);

                Cv2.BitwiseNot(image, image);
                int width  = 400;
                var height = width * image.Height / image.Width;
                Cv2.Resize(orig, orig, new Size(width, height));
                Cv2.Resize(image, image, new Size(width, height));
                Cv2.Resize(newImage, newImage, new Size(width, height));

                using (new Window("orig", orig))
                    using (new Window("pre", image))
                        using (new Window("post", newImage))
                        {
                            Cv2.WaitKey();
                            Cv2.DestroyAllWindows();
                        }
            }

            // Dispose.
            orig.Dispose();
            image.Dispose();
            newImage.Dispose();
            mat.Dispose();

            return(result);
        }