Exemple #1
0
        private int _ComputeThreshold(Image <Gray, Byte> filteredImage, DetectedCircle circle)
        {
            float min, max;

            //Gray avg;
            //MCvScalar sdv;
            //filteredImageWithROI.AvgSdv(out avg, out sdv);
            //DenseHistogram histo = new DenseHistogram(256, new RangeF(0, 256));

            //histo.Calculate(new Image<Gray, Byte>[] { filteredImageWithROI }, true, null);
            float[] grayHist = _ComputeHistogram(filteredImage, circle);//histo.GetBinValues();
            //grayHist = grayHist.Skip(20).ToArray(); //discard the black pixels of the borders

            double avg       = 0;
            double numPixels = 0;

            for (int i = 0; i < grayHist.Length; i++)
            {
                numPixels += grayHist[i];
                avg       += (i) * grayHist[i];
            }
            avg = avg / numPixels;
            double sumOfSquaresOfDifferences = grayHist.Select(val => (val - avg) * (val - avg)).Sum();
            double sd = Math.Sqrt(sumOfSquaresOfDifferences / numPixels);

            min = Array.FindIndex(grayHist, b => b > 0);
            max = 255 - Array.FindIndex(grayHist.Reverse().ToArray(), b => b > 0);

            if (ThresholdModel == EThresholdModel.Model1)
            {
                return((int)(0.6257849 * avg + 0.5013893 * max));
            }
            else
            {
                return((int)(10.7573408 + 0.6273262 * avg + 0.4531369 * max));
            }

            /*else if (ThresholdModel == EThresholdModel.Model2)
             *  return (int)(0.6210 * avg + 0.6431 * max - 1.005 * sd - 0.2508 * min);
             * else if (ThresholdModel == EThresholdModel.Model4)
             *  return (int)(48.74 + avg * 0.4726 + max * 0.3060);
             * else
             *  return (int)(83.97 + 0.7667 * avg);*/
        }
Exemple #2
0
        private float[] _ComputeHistogram(Image <Gray, Byte> filteredImage, DetectedCircle detectedCircle)
        {
            float[] hist = new float[256];

            byte[,,] data = filteredImage.Data;
            Parallel.For(filteredImage.ROI.Y, filteredImage.ROI.Y + filteredImage.Rows, i =>
            {
                Parallel.For(filteredImage.ROI.X, filteredImage.ROI.X + filteredImage.Cols, j =>
                {
                    double inside = CvInvoke.PointPolygonTest(detectedCircle.contour, new PointF(j, i), false);
                    if (inside >= 0)
                    {
                        hist[data[i, j, 0]]++;
                    }
                });
            });

            return(hist);
        }
Exemple #3
0
        private Dictionary <int, KeyValuePair <decimal, decimal> > _FindContoursAndCalculate(Emgu.CV.Image <Bgr, Byte> colorImage, out Emgu.CV.Image <Gray, Byte> processedImage)
        {
            int circles = 0;
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            Mat hierarchy = new Mat();

            /// Detect edges using Threshold
            Image <Gray, Byte> Img_Source_Gray = colorImage.Convert <Gray, Byte>();

            Img_Source_Gray = Img_Source_Gray.SmoothBlur(3, 3);
            Image <Gray, Byte> threshold_output = Img_Source_Gray.ThresholdBinary(new Gray(90), new Gray(255));

            /// Find contours
            CvInvoke.FindContours(threshold_output, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
            /// Approximate contours to polygons + get bounding rects and circles
            VectorOfVectorOfPoint contours_poly = new VectorOfVectorOfPoint(contours.Size);

            Point[][]  con  = contours.ToArrayOfArray();
            PointF[][] conf = new PointF[con.GetLength(0)][];
            for (int i = 0; i < con.GetLength(0); i++)
            {
                conf[i] = new PointF[con[i].Length];
                for (int j = 0; j < con[i].Length; j++)
                {
                    conf[i][j] = new PointF(con[i][j].X, con[i][j].Y);
                }
            }


            for (int i = 0; i < contours.Size; i++)
            {
                double a = CvInvoke.ContourArea(contours[i], false);
                if (a > 30000)
                {
                    CvInvoke.ApproxPolyDP(contours[i], contours_poly[circles], 3, true);

                    circles++;
                }
            }

            /// Draw polygonal contour + bonding rects + circles
            Image <Gray, byte> filteredImage = new Image <Gray, byte>(Img_Source_Gray.Width, Img_Source_Gray.Height);

            for (int i = 0; i < circles; i++)
            {
                CvInvoke.DrawContours(filteredImage, contours_poly, i, new MCvScalar(255, 255, 255), -1);
            }


            filteredImage = colorImage.Convert <Gray, Byte>().And(filteredImage);
            Image <Gray, Byte>    whiteAreas      = new Image <Gray, byte>(filteredImage.Width, filteredImage.Height);
            List <DetectedCircle> detectedCircles = new List <DetectedCircle>();

            for (int i = 0; i < circles; i++)
            {
                PointF[]       pointfs        = Array.ConvertAll(contours_poly[i].ToArray(), input => new PointF(input.X, input.Y));
                Rectangle      boundingRect   = PointCollection.BoundingRectangle(pointfs);
                DetectedCircle detectedCircle = new DetectedCircle()
                {
                    contour = contours_poly[i], boundingRect = boundingRect, center = new Point(boundingRect.X + (boundingRect.Width / 2), boundingRect.Y + (boundingRect.Height / 2))
                };
                detectedCircles.Add(detectedCircle);
                filteredImage.ROI = boundingRect;
                int threshold = _ComputeThreshold(filteredImage, detectedCircle);
                filteredImage.ROI = Rectangle.Empty;
                Image <Gray, Byte> mask = new Image <Gray, byte>(filteredImage.Width, filteredImage.Height);
                mask.Draw(boundingRect, new Gray(255), -1);
                mask = filteredImage.And(mask);
                /* Extract white are solely based on the Blue channel */
                mask       = mask.ThresholdBinary(new Gray(threshold), new Gray(255));
                whiteAreas = whiteAreas.Or(mask.Convert <Gray, Byte>().ThresholdBinary(new Gray(10), new Gray(255)));
                CvInvoke.DrawContours(whiteAreas, contours_poly, i, new MCvScalar(255, 255, 255), 3);
            }


            detectedCircles = detectedCircles.OrderBy(c => c.center.X).ToList();
            processedImage  = whiteAreas;
            return(_ComputeMetrics(whiteAreas, detectedCircles, circles));
        }