Ejemplo n.º 1
0
        static void GroupFlood(GroupFloodData gfd, Location pixel, int depth)
        {
            // add current pixel to the group
            gfd.groupHash.Add(pixel.key(), pixel);
            //if (gfd.groupHash.Count % 1000 == 0)
            //    MyDebug("groupSize now is " + gfd.groupHash.Count.ToString() + "     " + pixel.x.ToString() + "," + pixel.y.ToString());


            //if (depth % 100 == 0)
            //MyDebug("Recursive Depth now is " + depth.ToString());

            //Debug.WriteLine("added to group: " + pixel.x.ToString() + "," + pixel.y.ToString());

            // recursive call all neighbors of current pixel that are part of the group
            foreach (var n in gfd.neighbors)
            {
                int      x   = pixel.x + n.x;
                int      y   = pixel.y + n.y;
                Location loc = new Location()
                {
                    x = x, y = y
                };
                //MyDebug("trying neighbor: " + x.ToString() + "," + y.ToString());
                // first check the potential neighbor is in the bitmap
                if (x >= 0 && x <= gfd.bmpWidth - 1 && y >= 0 && y <= gfd.bmpHeight - 1)
                {
                    //MyDebug("neighbor in bitmap: " + x.ToString() + "," + y.ToString());

                    // now check it is a new group memeber
                    byte r = gfd.rgbValues[(y * gfd.stride) + (x * 3)];
                    byte g = gfd.rgbValues[(y * gfd.stride) + (x * 3) + 1];
                    byte b = gfd.rgbValues[(y * gfd.stride) + (x * 3) + 2];
                    byte e = gfd.elp[y * gfd.bmpWidth + x];

                    //MyDebug("rgbe: " + r.ToString() + "," + g.ToString() + "," + b.ToString() + "," + e.ToString());

                    // check the pixel color is OK, that pixel is not part of an alread detected
                    // elephant (group thatr is not an ant) and that this pixel is not already part
                    // of the current group
                    if (r < gfd.blackThreshHold && g < gfd.blackThreshHold && b < gfd.blackThreshHold &&
                        e != ELP_MEMBER && !gfd.groupHash.ContainsKey(loc.key()))
                    {
                        // we only collect up to ant group size or a bit more (5) pixels
                        if (depth < antThreshold + 5)
                        {
                            GroupFlood(gfd, loc, depth + 1); // recursive call
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private static void Ants(string[] args)
        {
            // read input file
            // L1: loop over all pixels left -> right , up -> bottom
            // search for pixel to start groupFlood ,needs to be "black" (have func isBlack())
            // create new groupHash, P1: call groupFlood with this pixel
            // groupFlood: add current pixel to groupHash
            // get neighbors  , (8 max) foreach neighbor pixel - check if it is "black" and not
            // already in groupHash and not an elephant member (see below) ,
            // if yes call groupFlood with this pixel to add it and
            // continue flooding
            // when P1 returns in the L1 loop - check the size of groupHash, and decide if
            // group is an Ant (too small).
            // If yes: mark all ant memebers as white in the bitmap array
            // If no - this is an elephant. Mark each pixel in elephant as such - elephant member
            // use additional byte for each pixel for this (so not to destroy its exact color
            // as we are keeping these intact)

            // open debug file
            //sw = File.CreateText("ants_debug.txt");

            string fname = args[1];
            Bitmap bmp   = new Bitmap(fname);

            antThreshold = 100;
            if (args.Length > 2)
            {
                antThreshold = Convert.ToByte(args[2]);
            }


            byte blackThreshHold = 160;

            if (args.Length > 3)
            {
                blackThreshHold = Convert.ToByte(args[3]);
            }

            // Lock the bitmap's bits.
            Rectangle  rect    = new Rectangle(0, 0, bmp.Width, bmp.Height);
            BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            int bytes = bmpData.Stride * bmp.Height;

            byte[] rgbValues = new byte[bytes];

            // Copy the RGB values into the array.
            Marshal.Copy(ptr, rgbValues, 0, bytes);

            // create array for elephant pixel marking, 1 byte per pixel
            int ElpBytes = bmpData.Width * bmp.Height;

            byte[] elp = new byte[ElpBytes];

            List <Location> n = new List <Location>();

            n.Add(new Location()
            {
                x = -1, y = -1
            });
            n.Add(new Location()
            {
                x = -1, y = 0
            });
            n.Add(new Location()
            {
                x = -1, y = 1
            });
            n.Add(new Location()
            {
                x = 0, y = -1
            });
            n.Add(new Location()
            {
                x = 0, y = 1
            });
            n.Add(new Location()
            {
                x = 1, y = -1
            });
            n.Add(new Location()
            {
                x = 1, y = 0
            });
            n.Add(new Location()
            {
                x = 1, y = 1
            });

            // alot of not changing data needed for the GroupFlood recursive function
            GroupFloodData gfd = new GroupFloodData();

            gfd.rgbValues       = rgbValues;
            gfd.elp             = elp;
            gfd.bmpWidth        = bmp.Width;
            gfd.bmpHeight       = bmp.Height;
            gfd.neighbors       = n;
            gfd.stride          = bmpData.Stride;
            gfd.blackThreshHold = blackThreshHold;

            // loop on all pixels
            int stride = bmpData.Stride;

            for (int x = 0; x < bmpData.Width; x++)
            {
                for (int y = 0; y < bmpData.Height; y++)
                {
                    byte r = rgbValues[(y * stride) + (x * 3)];
                    byte g = rgbValues[(y * stride) + (x * 3) + 1];
                    byte b = rgbValues[(y * stride) + (x * 3) + 2];
                    byte e = elp[y * bmpData.Width + x];



                    // find a pixel to start flooding a group from
                    // check colors bellow threshHold and
                    // not neighbor of elp (if neighbor of elp - make him an elp as well)
                    bool isBlack = (r < blackThreshHold && g < blackThreshHold && b < blackThreshHold);
                    if (isBlack)
                    {
                        // following block checks if the pixel is an elp group member due to neighboehood with other elp member
                        bool isElpMember = false;
                        foreach (var nn in gfd.neighbors)
                        {
                            int xn = x + nn.x;
                            int yn = y + nn.y;
                            if (xn >= 0 && xn <= bmp.Width - 1 && yn >= 0 && yn <= bmp.Height - 1)
                            {
                                // I think it is OK not test on himself
                                isElpMember = elp[yn * bmpData.Width + xn] == ELP_MEMBER;
                                if (isElpMember)
                                {
                                    elp[y * bmpData.Width + x] = ELP_MEMBER; // make him an elp member if he has an elp neighbor
                                    break;
                                }
                            }
                        }
                        if (!isElpMember)
                        {
                            if (x % 100 == 0 && y % 100 == 0)
                            {
                                MyDebug("First Pixel of Group: " + x.ToString() + "," + y.ToString());
                            }


                            // new dictionary list for each group under test
                            Dictionary <string, Location> groupHash = new Dictionary <string, Location>();
                            gfd.groupHash = groupHash;
                            GroupFlood(gfd, new Location()
                            {
                                x = x, y = y
                            }, depth: 0);

                            int  groupSize = groupHash.Count;
                            bool isAnt     = groupSize < antThreshold;
                            //    MyDebug("new group with groupSize: " + groupSize.ToString() + (isAnt ? " ANT!!!!" : ""));
                            if (isAnt) // we have an ant
                            {
                                foreach (var item in groupHash)
                                { // set all ant pixels to white
                                    Location p = item.Value;
                                    rgbValues[(p.y * stride) + (p.x * 3)]     = 255;
                                    rgbValues[(p.y * stride) + (p.x * 3) + 1] = 255;
                                    rgbValues[(p.y * stride) + (p.x * 3) + 2] = 255;
                                }
                            }
                            else
                            {
                                foreach (var item in groupHash)
                                { // mark all pixels as elephant members, leave them as is in original image
                                    Location p = item.Value;
                                    elp[p.y * bmpData.Width + p.x] = ELP_MEMBER;
                                }
                            }
                        }
                    }
                }
            }


            // create bitmap back from new values
            // Commit the changes, and unlock the 50x30 portion of the bitmap.
            Marshal.Copy(rgbValues, 0, ptr, bytes);
            bmp.UnlockBits(bmpData);


            string[] s       = fname.Split('.');
            string   newName = string.Concat(s[0], "_size_", antThreshold.ToString(), "_blackLevel_", blackThreshHold.ToString(), ".", s[1]);

            bmp.Save(newName, ImageFormat.Jpeg);

            MyDebug("done!!");
        }