Ejemplo n.º 1
0
        private Bitmap CreateObjectMask(Bitmap img, /*out IplImage image_mask,*/
                                        out double mask_length, out double mask_area, out double mask_width, out double mask_height,
                                        out double mask_pvheight, int num_smooth, int contrast, double canny1, double canny2,
                                        out Mat image_mask_spc, out double mask2_area, int filter_size = 3,
                                        int brightAreaThreshold = -1, int darkAreaThreshold = -1)
        {
            Bitmap dst = null;
            //IplImage img_mask = Cv.CreateImage(new CvSize(img.Width, img.Height), BitDepth.U8, 1);
            Mat img_mask = new Mat(new OpenCvSharp.Size(img.Width, img.Height), MatType.CV_8UC1, 0);

            image_mask_spc = null;
            mask_length    = mask_area = mask_width = mask_height = mask_pvheight = mask2_area = 0;

            Mat img_gray;
            Mat img_canny;
            Mat img_mask_copy;

            int    i, x, y, offset;
            IntPtr ptr;
            Byte   pixel;

            //////////////////
            var    distance        = new List <double>();
            double center_x        = 0;
            double center_y        = 0;
            double center_count    = 0;
            double distance_mean   = 0;
            double distance_stddev = 0;
            double sum_m           = 0;
            double sum_v           = 0;
            double temp            = 0;

            //////////////////

            ////////////////////////////////////////////////////////////
            ////////////////////////Mask make///////////////////////////
            ////////////////////////////////////////////////////////////
            img_gray      = new Mat(new OpenCvSharp.Size(img.Width, img.Height), MatType.CV_8UC1, 0);
            img_canny     = new Mat(new OpenCvSharp.Size(img.Width, img.Height), MatType.CV_8UC1, 0);
            img_mask_copy = new Mat(new OpenCvSharp.Size(img.Width, img.Height), MatType.CV_8UC1, 0);

            Mat src = BitmapConverter.ToMat(img);

            Cv2.CvtColor(src, img_gray, ColorConversionCodes.BGR2GRAY);

            //Contrast -> Increase the edge contrast for transparent diamond
            byte[] lut = CalcLut(contrast, 0);
            //img_gray.LUT(img_gray, lut);
            Cv2.LUT(img_gray, lut, img_gray);

            //Median filter -> Eliminate point noise in the image



            //Elimination of big dusts should be coded here
            if (num_smooth > 0)
            {
                //for (i = 0; i < num_smooth; i++) img_gray.Smooth(img_gray, SmoothType.Median, 3, 3, 0, 0);
                //for (i = 0; i < num_smooth; i++) img_gray.Smooth(img_gray, SmoothType.Median, filter_size, filter_size, 0, 0);
                for (i = 0; i < num_smooth; i++)
                {
                    Cv2.MedianBlur(img_gray, img_gray, filter_size);
                }

                img_canny = img_gray.Canny(canny1, canny2);
            }
            else
            {
                img_canny = img_gray.Canny(canny1, canny2);
            }

            /////////////////////////////////////////////////////////////
            //ConvexHull
            /////////////////////////////////////////////////////////////

            //OpenCvSharp.CvMemStorage storage = new CvMemStorage(0);
            //CvSeq points = Cv.CreateSeq(SeqType.EltypePoint, CvSeq.SizeOf, CvPoint.SizeOf, storage);
            //CvSeq<CvPoint> points = new CvSeq<CvPoint>(SeqType.EltypePoint, CvSeq.SizeOf, storage);
            //CvPoint pt;

            List <OpenCvSharp.Point> points = new List <OpenCvSharp.Point>();

            OpenCvSharp.Point pt;

            ptr = img_canny.Data;
            for (y = 0; y < img_canny.Height; y++)
            {
                for (x = 0; x < img_canny.Width; x++)
                {
                    offset = (img_canny.Width * y) + (x);
                    pixel  = Marshal.ReadByte(ptr, offset);
                    if (pixel > 0)
                    {
                        pt.X = x;
                        pt.Y = y;
                        points.Add(pt);
                        //////////////////////
                        center_x = center_x + x;
                        center_y = center_y + y;
                        center_count++;
                        //////////////////////
                    }
                }
            }

            center_x = center_x / center_count;
            center_y = center_y / center_count;

            //CvPoint[] hull;
            //CvMemStorage storage1 = new CvMemStorage(0);
            //CvSeq<CvPoint> contours;
            //List<Mat> hull = new List<Mat>();
            MatOfPoint hull = new MatOfPoint();

            int x_min = 3000, x_max = 0, y_min = 3000, y_max = 0;
            int y_x_min = 3000, y_x_max = 3000;

            if (points.Count > 0)
            {
                //Calcurate Ave and Std of distance from each edge points to the weighed center
                for (i = 0; i < points.Count; i++)
                {
                    pt   = points[i];
                    temp = Math.Sqrt((pt.X - center_x) * (pt.X - center_x) + (pt.Y - center_y) * (pt.Y - center_y));
                    distance.Add(temp);
                    sum_m += temp;
                    sum_v += temp * temp;
                }

                distance_mean   = sum_m / points.Count;
                temp            = (sum_v / points.Count) - distance_mean * distance_mean;
                distance_stddev = Math.Sqrt(temp);

                // Outlier elimination
                for (i = points.Count - 1; i >= 0; i--)
                {
                    if (distance[i] > (distance_mean + 3.0 * distance_stddev))
                    {
                        points.RemoveAt(i);
                    }
                }

                Cv2.ConvexHull(MatOfPoint.FromArray(points), hull, true);


                //2014/4/14 Add calc mask_width, mask_height and mask_pvheight

                foreach (OpenCvSharp.Point item in hull)
                {
                    if (x_min > item.X)
                    {
                        x_min   = item.X;
                        y_x_min = item.Y;
                    }
                    else if (x_min == item.X && y_x_min > item.Y)
                    {
                        y_x_min = item.Y;
                    }

                    if (x_max < item.X)
                    {
                        x_max   = item.X;
                        y_x_max = item.Y;
                    }
                    else if (x_max == item.X && y_x_max > item.Y)
                    {
                        y_x_max = item.Y;
                    }

                    if (y_min > item.Y)
                    {
                        y_min = item.Y;
                    }
                    if (y_max < item.Y)
                    {
                        y_max = item.Y;
                    }
                }
                mask_width    = x_max - x_min;
                mask_height   = y_max - y_min;
                mask_pvheight = ((double)y_x_max + (double)y_x_min) / 2 - (double)y_min;

                /////////////////////////////////////////////////////////////
                // For icecream cone shape diamond, need to use triangle mask
                /////////////////////////////////////////////////////////////

                if (diamond_group == DIAMOND_GROUPING.RBC_HighDepth)
                {
                    for (i = 0; i < hull.Count(); i++)
                    {
                        OpenCvSharp.Point p = hull.At <OpenCvSharp.Point>(i);
                        if (y_x_max >= y_x_min)
                        {
                            if (p.Y > y_x_min)
                            {
                                p.X = x_max;
                                p.Y = y_x_max;
                            }
                        }
                        else
                        {
                            if (p.Y > y_x_max)
                            {
                                p.X = x_min;
                                p.Y = y_x_min;
                            }
                        }
                    }
                }

                //////////////////////////////////////////////////////////////

                Cv2.FillConvexPoly(img_mask, hull, Scalar.White, LineTypes.AntiAlias, 0);

                //2013/11/3 Add erode function
                if (erode > 0)
                {
                    for (i = 0; i < erode; i++)
                    {
                        Cv2.Erode(img_mask, img_mask, null);
                    }
                }

                //Calc length and area of img_mask -> use for fancy shape diamonds
                //Cv.FindContours(img_mask, storage1, out contours, CvContour.SizeOf, ContourRetrieval.External, ContourChain.ApproxSimple);
                //Cv.FIndCOntours overwrites img_mask, need to use copy image
                //IplImage img_mask_copy = Cv.Clone(img_mask);
                //Cv2.Copy(img_mask, img_mask_copy);
                Mat   hierarchy = new Mat();
                Mat[] contours;
                img_mask.CopyTo(img_mask_copy);
                Cv2.FindContours(img_mask_copy, out contours, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
                //Cv.ReleaseImage(img_mask_copy);

                mask_length = Cv2.ArcLength(contours[0], true);
                mask_area   = Math.Abs(Cv2.ContourArea(contours[0]));
                //Cv.ClearSeq(contours);
            }
            else
            {
                mask_length = 0.0;
                mask_area   = 0.0;
            }

            //Memory release
            //Cv.ReleaseImage(img_gray);
            //Cv.ReleaseImage(img_canny);
            //Cv.ReleaseImage(img_mask_copy);
            //Cv.ClearSeq(points);
            //Cv.ReleaseMemStorage(storage);
            //Cv.ReleaseMemStorage(storage1);

            //if the diamond is out of croped image, do not calc color values
            if (x_min == 0 | x_max == (img.Width - 1) | y_min == 0 | y_max == (img.Height - 1))
            {
                return(dst);
            }

            //img_mask.SaveImage(@"P:\Projects\DustDetection\TestSamples\gColorFancyImages\temp\image_mask_hiroshi.jpg");

            if (mask_length > 0)
            {
                dst = BitmapConverter.ToBitmap(img_mask);
            }

            return(dst);
        }