Пример #1
0
        /// <summary>
        /// Reserves a rectangular area for the given image in this.Maze.
        /// The chosen location is remembered in this.imageLocations.
        /// Returns true if the reservation was successful.
        /// </summary>
        /// <param name="contourImage"></param>
        /// <returns></returns>
        private bool AddImage(ContourImage contourImage)
        {
            Image img     = contourImage.DisplayedImage;
            int   padding = MazePainter.ApplyScaleFactor(8) + this.wallWidth;
            int   sqW     = (img.Width + padding) / this.gridWidth + 1;
            int   sqH     = (img.Height + padding) / this.gridWidth + 1;

            int xOffsetImg = (sqW * gridWidth - img.Width) / 2;
            int yOffsetImg = (sqH * gridWidth - img.Height) / 2;

            OutlineShape shape = (ContourImage.DisplayProcessedImage ? contourImage.GetCoveredShape(gridWidth, wallWidth, xOffsetImg, yOffsetImg) : null);

            Rectangle rect;

            if (Maze.ReserveRectangle(sqW, sqH, 2, shape, out rect))
            {
                // Remember the image data and location.  It will be painted in PaintMaze().
                int x = rect.X * gridWidth + xOffset + xOffsetImg;
                int y = rect.Y * gridWidth + yOffset + yOffsetImg;
                imageLocations.Add(new Rectangle(x, y, img.Width, img.Height));
                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #2
0
        private void showContourButton_Click(object sender, EventArgs e)
        {
            if (this.imageButton.Image == null)
            {
                return;
            }

            if (template == null)
            {
                template = this.imageButton.Image;
            }

            DateTime start = DateTime.Now;

            ContourImage ci = new ContourImage(template, null);

            ci.ProcessImage();
            processed = ci.ProcessedImage;

            TimeSpan t  = DateTime.Now - start;
            int      ms = (int)t.TotalMilliseconds;

            this.timeLabel.Text = ms.ToString();

            this.imageButton.Image = processed;
        }
Пример #3
0
        /// <summary>
        /// Returns an image loaded from the given path and scaled to the known size range.
        /// </summary>
        /// <param name="imagePath"></param>
        /// <param name="r"></param>
        /// <returns></returns>
        private ContourImage LoadImage(string imagePath, Random r)
        {
            try
            {
                //Log.WriteLine("{ " + string.Format("LoadImage({0})", imagePath));
                Image img = new Bitmap(imagePath);

                //Log.WriteLine("- LoadImage() scale image");
                #region Scale img so that its larger dimension is between the desired min and max size.

                bool resize = false;

                if (img.Width > maxSize || img.Height > maxSize)
                {
                    resize = true;
                }
                if (minSizeRequired && img.Width < minSize && img.Height < minSize)
                {
                    resize = true;
                }

                if (resize)
                {
                    int d = r.Next(minSize, maxSize);
                    int h = img.Height, w = img.Width;
                    if (h > w)
                    {
                        w = d * w / h;
                        h = d;
                    }
                    else
                    {
                        h = d * h / w;
                        w = d;
                    }
                    Bitmap tmpImg = new Bitmap(img, new Size(w, h));
                    img.Dispose(); // closes and unlocks the image file
                    img = tmpImg;
                }

                #endregion

                //Log.WriteLine("- LoadImage() create contour image");
                ContourImage result = new ContourImage(img, imagePath);

                //Log.WriteLine("} LoadImage()");
                return(result);
            }
            catch (Exception ex)
            {
                string msg = string.Format("cannot load image [{0}]: {1}", imagePath, ex.Message);
                Log.WriteLine(msg, true);
                badImages[imagePath] = true;
                return(null);
            }
        }
Пример #4
0
        /// <summary>
        /// Processes and enqueues the given image.
        /// </summary>
        /// <param name="img"></param>
        private void Enqueue(ContourImage img)
        {
            //Log.WriteLine("{ " + string.Format("Enqueue({0})", img.ToString()));

            // Wait while the queue contains enough items.
            queueFullSemaphore.WaitOne();

            if (img != null)
            {
                img.ProcessImage();
            }

            // Enqueue the processed image.
            //Log.WriteLine("- Enqueue() Enqueue");
            queue.Enqueue(img);

            #region Add the image path to a separate list; save that list to the Registry

            if (queuedImagePaths != null)
            {
                lock (queuedImagePaths)
                {
                    if (img.HasContour)
                    {
                        // True contour images should be loaded last.
                        queuedImagePaths.Add(img.Path);
                    }
                    else
                    {
                        // Images without a contour should be loaded first.
                        queuedImagePaths.Insert(0, img.Path);
                    }

                    if (queuedImagePaths.Count >= queueLength)
                    {
                        SaveImagePaths();
                    }
                }
            }

            #endregion

            queueEmptySemaphore.Release();

#if true
            /* Continue at the lower thread priority as soon as the first image has been loaded.
             * This assumes that a) we need only one image or b) we can easily load more images on demand.
             * This works fine if enough images can be loaded from the saved images list.
             * See LoadImagePaths().
             */
            ReduceThreadPriority();
#endif
            //Log.WriteLine("} Enqueue()");
        }
Пример #5
0
        /// <summary>
        /// Puts the given number of images into the this.images list.
        /// </summary>
        /// <param name="count"></param>
        public void PrepareImages(int count)
        {
            //Log.WriteLine("{ PrepareImages()");
            images.Clear();
            imageLocations.Clear();

            bool haveBackgroundImage = this.MazePainter.PrepareBackgroundImage();

            #region Determine number of images to be placed into reserved areas.

            Random r = Maze.Random;
            int    n, nMin, nMax = count;

            if (haveBackgroundImage && r.Next(100) < 25)
            {
                nMax = 0;
            }

            if (nMax <= 2)
            {
                nMin = nMax;
            }
            else
            {
                nMin = nMax * 2 / 3;
            }

            if (nMax > 0)
            {
                n = r.Next(nMin, nMax + 1);
            }
            else
            {
                n = 0;
            }

            #endregion

            for (int i = 0; i < n; i++)
            {
                ContourImage img = imageLoader.GetNext(r);
                if (img != null)
                {
                    images.Add(img);
                }
            }

            this.hasPreparedImages = true; // even if images.Count = 0
            //Log.WriteLine("} PrepareImages()");
        }
Пример #6
0
        /// <summary>
        /// Background thread:
        /// Fills the queue with images.
        /// </summary>
        private void LoadImages()
        {
            Random r = RandomFactory.CreateRandom();

            #region Start with a few images, preferably without a contour.

            // The saved image paths are already ordered (see SaveImagePaths()).
            LoadAndEnqueue(r, true, LoadImagePaths());

            if (queue.Count >= queueLength)
            {
                ReduceThreadPriority();
            }
            else
            {
                LoadAndEnqueue(r, false, FindImages(imageFolder, queueLength + 1, true, r));
            }

            #endregion

            #region Continuously load more images, keeping the queue full.

            while (true)
            {
                int loadedImagesCount = 0;

                foreach (string imagePath in FindImages(imageFolder, 100, false, r))
                {
                    ContourImage img = LoadImage(imagePath, r);
                    if (img == null)
                    {
                        continue;
                    }

                    Enqueue(img);
                    ++loadedImagesCount;
                }

                // If no image was loaded successfully, enqueue a null value.
                if (loadedImagesCount == 0)
                {
                    Enqueue(null);
                }
            }

            #endregion
        }
Пример #7
0
        /// <summary>
        /// Reserves an area for each of the prepared images (as found in this.images).
        /// If no free area is found for an image, it is discarded.
        /// </summary>
        public void ReserveAreaForImages()
        {
            if (this.HasPreparedImages)
            {
                for (int i = 0; i < images.Count; i++)
                {
                    ContourImage img = images[i];
                    if (!AddImage(img))
                    {
                        images.RemoveAt(i);
                        i--;
                    }
                }
            }

            this.hasPreparedImages = false;
        }
Пример #8
0
        public void IL_GetNextTest_01()
        {
            string testObject = "GetNext";

            int    minSize     = 300;
            int    maxSize     = 500;
            string imageFolder = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_IMAGE_FOLDER);

            int queueLength = 4;

            ImageLoader target = new ImageLoader(minSize, maxSize, false, imageFolder, queueLength, "TEST");

            for (int i = 0; i < 20; i++)
            {
                ContourImage img = target.GetNext(null);
                Assert.AreNotEqual(null, img, testObject + "returned null");
            }
        }
Пример #9
0
        private ContourImage Dequeue()
        {
            //Log.WriteLine("{ Dequeue()");
            queueEmptySemaphore.WaitOne();
            //Log.WriteLine("- Dequeue() Dequeue");
            ContourImage result = queue.Dequeue() as ContourImage;

            if (queuedImagePaths != null)
            {
                lock (queuedImagePaths)
                {
                    queuedImagePaths.Remove(result.Path);
                }
            }
            queueFullSemaphore.Release();
            //Log.WriteLine("} Dequeue()");
            return(result);
        }
Пример #10
0
        public Mat DrawAllCellContourBoundingBoxes()
        {
            var matToReturn         = ContourImage.CreateNewMatLikeThis();
            var boxVecOfVectorPoint = new VectorOfVectorOfPointF();

            foreach (var contour in Contours.ToArrayOfArray())
            {
                var tempVector = new VectorOfPoint(contour);
                var tempRect   = CvInvoke.MinAreaRect(tempVector);
                var box        = CvInvoke.BoxPoints(tempRect);
                var boxVec     = new VectorOfPointF(box);
                boxVecOfVectorPoint.Push(boxVec);
            }

            var convertedVectorOfVectorPoint = boxVecOfVectorPoint.ConvertToVectorOfPoint();

            CvInvoke.DrawContours(matToReturn, convertedVectorOfVectorPoint, -1, new MCvScalar(0, 255, 0, 255), 2);
            return(matToReturn);
        }
Пример #11
0
 //saját
 public void Process()
 {
     //TODO ezeknek a refeknek az elhagyása
     ProcessedImage = null;
     ContourImage   = null;
     Contours.Clear();
     ImgProcessor.Process();
     OgImage        = ImgProcessor.OgImageMat;
     ProcessedImage = ImgProcessor.ImageMat;
     ContourImage   = ImgProcessor.ContourImageMat;
     Contours.Push(ImgProcessor.ContoursToReturn);
     Boxes.Push(ImgProcessor.AngledBoundingBoxesToReturn);
     DetectedCellCount = Contours.Size;
     MainWindow.ImageProcessorExaminer.AddImage(OgImage.CreateNewHardCopyFromMat(), "ImageHandler_OgImage");
     MainWindow.ImageProcessorExaminer.AddImage(Image.CreateNewHardCopyFromMat(), "ImageHandler_Image");
     MainWindow.ImageProcessorExaminer.AddImage(ProcessedImage.CreateNewHardCopyFromMat(), "ImageHandler_ProcessedImage");
     MainWindow.ImageProcessorExaminer.AddImage(ContourImage.CreateNewHardCopyFromMat(), "ImageHandler_ContourImage");
     ProcessOverlays();
 }
Пример #12
0
        /// <summary>
        /// Compares the given image's dimensions to the desired limits.
        /// Returns true if the image should be discarded.
        /// </summary>
        /// <param name="img">Image.</param>
        /// <param name="testMinSize">May be this.minSizeRequired</param>
        private bool ImageHasImproperSize(ContourImage img, bool testMinSize)
        {
            if (img == null)
            {
                return(false);
            }

            int h = img.DisplayedImage.Height;
            int w = img.DisplayedImage.Width;

            if (h > maxSize || w > maxSize)
            {
                return(true);
            }
            if (testMinSize && (h < minSize || w < minSize))
            {
                return(true);
            }

            return(false);
        }
Пример #13
0
        /// <summary>
        /// Paints the images into their reserved areas.
        /// </summary>
        /// <param name="g"></param>
        private void PaintImages(Graphics g)
        {
            Region clip = g.Clip;

            for (int i = 0; i < images.Count; i++)
            {
                ContourImage img = images[i];

                if (img.HasContour)
                {
                    // Set a clipping region around the image.
                    Region r = img.BorderRegion.Clone();
                    r.Translate(imageLocations[i].X, imageLocations[i].Y);
                    g.Clip = r;
                }
                else
                {
                    // Paint a black border around the image, covering any background images.
                    Rectangle border = imageLocations[i];
                    border.Inflate(2, 2);
                    g.Clip = clip;
                    g.FillRectangle(Brushes.Black, border);
                }

                g.DrawImage(img.DisplayedImage, imageLocations[i]);
            }

            // Restore previous clip region (infinite).
            g.Clip = clip;

            for (int i = 0; i < controlLocations.Count; i++)
            {
                // Paint a black border around the control, covering any background images.
                Rectangle border = controlLocations[i];
                border.Inflate(2, 2);
                g.FillRectangle(Brushes.Black, border);
            }
        }
Пример #14
0
        /// <summary>
        /// Loads and enqueues all images of the given list.
        /// </summary>
        /// <param name="imagePaths"></param>
        /// <param name="preserveOrder">When false, the list is reordered so that images without a contour that need not be processed come first.</param>
        /// <param name="r"></param>
        private void LoadAndEnqueue(Random r, bool preserveOrder, IEnumerable <string> imagePaths)
        {
            //Log.WriteLine("{ " + string.Format("LoadAndEnqueue({0})", imagePaths.GetType().ToString()));
            List <ContourImage> unprocessedImages = new List <ContourImage>(queueLength + 1);

            IEnumerator <string> e = imagePaths.GetEnumerator();

            while (e.MoveNext())
            {
                string       imagePath = e.Current;
                ContourImage img       = null;

                if (imagePath != null)
                {
                    img = LoadImage(imagePath, r);
                }
                if (img == null)
                {
                    continue;
                }
                else if (!preserveOrder && img.HasContour)
                {
                    //Log.WriteLine("- LoadAndEnqueue() save contour image: " + img.ToString());
                    unprocessedImages.Add(img);
                }
                else
                {
                    Enqueue(img);
                }
            }

            foreach (ContourImage img in unprocessedImages)
            {
                Enqueue(img);
            }
            //Log.WriteLine("} LoadAndEnqueue()");
        }
Пример #15
0
        public void CI_InsertPairTest_08_ThickLines()
        {
            string testObject = "ContourImage.ScanObject";

            Color backgroundColor = Color.White;
            Color foregroundColor = Color.Black;
            Brush fgBrush         = new SolidBrush(foregroundColor);
            Pen   fgPen           = new Pen(fgBrush, 8);

            fgPen.StartCap = fgPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;

            // When painting into the image, leave an outer frame of 16 pixels free.
            // Only use the range 50..250.
            int      width = 300, height = 300;
            Bitmap   image = new Bitmap(width, height);
            Graphics g     = Graphics.FromImage(image);

            int contourDist = SWA_Ariadne_Gui_Mazes_ContourImageAccessor.ContourDistance;
            int blurDist    = SWA_Ariadne_Gui_Mazes_ContourImageAccessor.BlurDistanceMax;

            SWA_Ariadne_Gui_Mazes_ContourImageAccessor.PrepareInfluenceRegions(contourDist + blurDist);

            int[,] alpha = new int[width, height];
            List <int>[] objectXs, contourXs, borderXs;
            SWA_Ariadne_Gui_Mazes_ContourImageAccessor.InitializeScanLines(width, height, out objectXs, out contourXs, out borderXs);

            #region Create a complicated pattern of border scan lines.

            Point[] points =
            {
                new Point(50,   50), new Point(250, 250),
                new Point(200, 100), new Point(100, 200),
            };

            g.FillRectangle(new SolidBrush(backgroundColor), 0, 0, image.Width, image.Height);

            for (int i = 0, j = i + 1; j < points.Length; i++, j++)
            {
                g.DrawLine(fgPen, points[i], points[j]);
            }

            #endregion

            ContourImage target = new ContourImage(image);
            SWA_Ariadne_Gui_Mazes_ContourImageAccessor accessor = new SWA_Ariadne_Gui_Mazes_ContourImageAccessor(target);
            accessor.image = image;

            int y0 = image.Height / 2;
            #region Find the leftmost object pixel on the scan line at y0.

            int x0        = 0;
            int fuzziness = (int)(0.1F * SWA_Ariadne_Gui_Mazes_ContourImageAccessor.MaxColorDistance);
            while (accessor.ColorDistance(image.GetPixel(x0, y0)) <= fuzziness)
            {
                x0++;
            }

            #endregion

            accessor.ScanObject(x0, y0, fuzziness, alpha, objectXs, contourXs, borderXs);

            TestBorderScanlines(testObject, borderXs);
        }
Пример #16
0
        private static void TestScan(string testObject, Bitmap image, Color backgroundColor, int y0, int maxContourScanRegions)
        {
            testObject += " @ " + y0.ToString();
            int fuzziness = (int)(0.1F * SWA_Ariadne_Gui_Mazes_ContourImageAccessor.MaxColorDistance);

            int frameWidth = SWA_Ariadne_Gui_Mazes_ContourImageAccessor.ContourDistance;

            SWA_Ariadne_Gui_Mazes_ContourImageAccessor.PrepareInfluenceRegions(frameWidth);

            ContourImage target = new ContourImage(image);
            SWA_Ariadne_Gui_Mazes_ContourImageAccessor accessor = new SWA_Ariadne_Gui_Mazes_ContourImageAccessor(target);

            accessor.image = image;

            #region Find the leftmost object pixel on the scan line at y0.

            int x0 = 0;
            while (accessor.ColorDistance(image.GetPixel(x0, y0)) <= fuzziness)
            {
                x0++;
                if (x0 >= image.Width)
                {
                    return;
                }
            }

            #endregion

            #region Prepare required data structures.

            int width = image.Width, height = image.Height;
            int[,] alpha = new int[width, height];
            List <int>[] objectXs, contourXs, borderXs;
            SWA_Ariadne_Gui_Mazes_ContourImageAccessor.InitializeScanLines(width, height, out objectXs, out contourXs, out borderXs);

            #endregion

            accessor.ScanObject(x0, y0, fuzziness, alpha, objectXs, contourXs, borderXs);

            #region Test if the object map is well formed.
            for (int i = 0; i < height; i++)
            {
                int nEntries = objectXs[i].Count;
                int m        = nEntries % 2;
                Assert.AreEqual(1, m, testObject + string.Format(" - objectXs[{0}] must be an odd number: {1}", i, nEntries));

                int nRegions = (nEntries - 1) / 2;
                Assert.IsTrue(nRegions <= maxContourScanRegions, testObject + string.Format(" - objectXs[{0}] regions = {1} must be less than {2}", i, nRegions, maxContourScanRegions));
            }
            #endregion

            #region Test if the object map is complete.
            int imageArea  = ImageArea(image, backgroundColor, (float)fuzziness / SWA_Ariadne_Gui_Mazes_ContourImageAccessor.MaxColorDistance);
            int objectArea = ObjectArea(objectXs);
            Assert.AreEqual(imageArea, objectArea, testObject + string.Format(" - object area and image area must be equal"));
            #endregion

            // Test if the contour map is well formed.
            TestBorderScanlines(testObject + " - contourXs", contourXs);

            // Test if the border map is well formed.
            TestBorderScanlines(testObject + " - borderXs", borderXs);
        }