예제 #1
0
        static void Main(string[] args)
        {
            Directory.CreateDirectory("SECOND_FIX");

            string[] files       = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*_cloudmask.png", SearchOption.TopDirectoryOnly);
            Point    biggestSize = new Point(0, 0);

            foreach (string file in files)
            {
                Console.WriteLine("Processing: " + Path.GetFileName(file));
                Bitmap cloudMaskV1     = (Bitmap)Image.FromFile(file);
                Bitmap streetviewImage = (Bitmap)Image.FromFile(file.Substring(0, file.Length - 14) + "_trim.jpg");

                string streetviewID = Path.GetFileName(file).Substring(0, Path.GetFileName(file).Length - 14);

                //Cut out the clouds from all our data, based on our cloud mask
                List <ValidCloudSquare> validCloudRegions = new List <ValidCloudSquare>();
                for (int x = 0; x < cloudMaskV1.Width; x++)
                {
                    for (int y = 0; y < cloudMaskV1.Height; y++)
                    {
                        //If this pixel isn't black, it's a cloud mask
                        Color thisPixel = cloudMaskV1.GetPixel(x, y);
                        if (!(thisPixel.R == 0 && thisPixel.G == 0 && thisPixel.B == 0))
                        {
                            //Double check this pixel isn't within a cloud bound we've already done
                            bool shouldCheck = true;
                            foreach (ValidCloudSquare thisArea in validCloudRegions)
                            {
                                if (thisArea.Contains(new Point(x, y)))
                                {
                                    shouldCheck = false;
                                    break;
                                }
                            }
                            if (!shouldCheck)
                            {
                                continue;
                            }

                            //Work out the bounds of the cloud mask this pixel is within
                            FloodResult  regionResult      = ThisRegion(cloudMaskV1, x, y);
                            List <Point> linkedContents    = regionResult.pointlist;
                            Point        boundsTopLeft     = GetMin(linkedContents);
                            Point        boundsBottomRight = GetMax(linkedContents);

                            //Work out the mask dimensions, and pull the section from our Streeview image
                            Point maskDims = new Point(boundsBottomRight.X - boundsTopLeft.X, boundsBottomRight.Y - boundsTopLeft.Y);
                            if (maskDims.X == 0 || maskDims.Y == 0)
                            {
                                regionResult.shouldoutput = false;
                            }
                            if (maskDims.X <= 40 || maskDims.Y <= 40)
                            {
                                regionResult.shouldoutput = false;
                            }
                            validCloudRegions.Add(
                                new ValidCloudSquare(
                                    boundsTopLeft,
                                    boundsBottomRight,
                                    (regionResult.shouldoutput) ? PullRegionLDR(streetviewImage, boundsTopLeft, maskDims) : null,
                                    regionResult.shouldoutput
                                    )
                                );
                        }
                    }
                }

                //Evaluate the cut-out clouds
                foreach (ValidCloudSquare thisRegion in validCloudRegions)
                {
                    if (!thisRegion.ShouldKeep)
                    {
                        continue;
                    }

                    Point imgDims          = new Point(0, 0);
                    float lowestBrightness = int.MaxValue;
                    float avgBrightness    = 0.0f;
                    float avgRed           = 0.0f;
                    float avgGreen         = 0.0f;
                    float avgBlue          = 0.0f;

                    for (int x = 0; x < thisRegion.StreetviewImg.Width; x++)
                    {
                        for (int y = 0; y < thisRegion.StreetviewImg.Height; y++)
                        {
                            Color thisPixel = thisRegion.StreetviewImg.GetPixel(x, y);
                            if (thisPixel.GetBrightness() < lowestBrightness)
                            {
                                lowestBrightness = thisPixel.GetBrightness();
                            }
                            avgBrightness += thisPixel.GetBrightness();
                            avgRed        += thisPixel.R;
                            avgGreen      += thisPixel.G;
                            avgBlue       += thisPixel.B;
                        }
                    }
                    imgDims.X      = thisRegion.StreetviewImg.Width; imgDims.Y = thisRegion.StreetviewImg.Height;
                    avgBrightness /= (thisRegion.StreetviewImg.Width * thisRegion.StreetviewImg.Height);
                    avgRed        /= (thisRegion.StreetviewImg.Width * thisRegion.StreetviewImg.Height);
                    avgGreen      /= (thisRegion.StreetviewImg.Width * thisRegion.StreetviewImg.Height);
                    avgBlue       /= (thisRegion.StreetviewImg.Width * thisRegion.StreetviewImg.Height);

                    thisRegion.ShouldKeep = (avgBrightness > 0.5 && /*pixelsWithZeroBr < ((imgDims.X * imgDims.Y) / 6) &&*/ lowestBrightness > 0.2 && ((avgBlue >= avgGreen) && (avgBlue >= avgRed)));
                }

                //Using the clouds we've determined are good enough, keep these bits of the mask and remove the others
                Bitmap cloudMaskV2 = new Bitmap(cloudMaskV1.Width, cloudMaskV1.Height);
                for (int x = 0; x < cloudMaskV2.Width; x++)
                {
                    for (int y = 0; y < cloudMaskV2.Height; y++)
                    {
                        cloudMaskV2.SetPixel(x, y, Color.Black);
                    }
                }
                foreach (ValidCloudSquare thisRegion in validCloudRegions)
                {
                    if (!thisRegion.ShouldKeep)
                    {
                        continue;
                    }

                    for (int x = 0; x < thisRegion.StreetviewImg.Width; x++)
                    {
                        for (int y = 0; y < thisRegion.StreetviewImg.Height; y++)
                        {
                            cloudMaskV2.SetPixel(thisRegion.TopLeft.X + x, thisRegion.TopLeft.Y + y, cloudMaskV1.GetPixel(thisRegion.TopLeft.X + x, thisRegion.TopLeft.Y + y));
                        }
                    }
                }
                streetviewImage.Save("SECOND_FIX/" + streetviewID + ".SKY_LDR.jpg");
                cloudMaskV2.Save("SECOND_FIX/" + streetviewID + ".CLOUD_MASK.png");
                File.Copy(AppDomain.CurrentDomain.BaseDirectory + "/" + streetviewID + "_sky_trim.hdr", "SECOND_FIX/" + streetviewID + ".SKY_MODEL.hdr", true);
                File.Copy(AppDomain.CurrentDomain.BaseDirectory + "/" + streetviewID + "_trim.hdr", "SECOND_FIX/" + streetviewID + ".SKY_HDR.hdr", true);
            }
        }
예제 #2
0
        /* thanks in part: https://stackoverflow.com/a/14897412 */
        static FloodResult ThisRegion(Bitmap bitmap, int x, int y)
        {
            BitmapData data = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            int[] bits = new int[data.Stride / 4 * data.Height];
            Marshal.Copy(data.Scan0, bits, 0, bits.Length);

            LinkedList <Point> check = new LinkedList <Point>();
            int floodTo   = Color.Black.ToArgb();
            int floodFrom = bits[x + y * data.Stride / 4];

            bits[x + y * data.Stride / 4] = floodTo;

            FloodResult toReturn = new FloodResult();

            if (floodFrom != floodTo)
            {
                check.AddLast(new Point(x, y));
                toReturn.pointlist.Add(new Point(x, y));

                Stopwatch st = new Stopwatch();
                st.Start();
                while (check.Count > 0)
                {
                    if (st.Elapsed.Seconds >= 1) //Don't pull anything that's taking too long - going for quantity here!
                    {
                        toReturn.shouldoutput = false;
                        break;
                    }

                    Point cur = check.First.Value;
                    check.RemoveFirst();

                    foreach (Point off in new Point[] {
                        new Point(0, -1), new Point(0, 1),
                        new Point(-1, 0), new Point(1, 0)
                    })
                    {
                        Point next = new Point(cur.X + off.X, cur.Y + off.Y);
                        if (next.X >= 0 && next.Y >= 0 &&
                            next.X < data.Width &&
                            next.Y < data.Height)
                        {
                            if (bits[next.X + next.Y * data.Stride / 4] == floodFrom)
                            {
                                check.AddLast(next);
                                if (!toReturn.pointlist.Contains(next))
                                {
                                    toReturn.pointlist.Add(next);
                                }
                                bits[next.X + next.Y * data.Stride / 4] = floodTo;
                            }
                        }
                    }
                }
                st.Stop();
            }

            bitmap.UnlockBits(data);
            return(toReturn);
        }