예제 #1
0
        // Return whether the image is mostly dark. This is done by counting the number of pixels that are
        // below a certain tolerance (i.e., mostly black), and seeing if the % of mostly dark pixels are
        // at or higher than the given darkPercent.
        // We also check to see if the image is predominantly color. We do this by checking to see if pixels are grey scale
        // (where r=g=b, with a bit of slop added) and then check that against a threshold.
        public static bool IsDark(BitmapSource bmap, int darkPixelThreshold, double darkPixelRatio, out double darkPixelRatioFound, out bool isColor)
        {
            PixelBitmap image1 = new PixelBitmap(bmap);
            int dark_counted = 0;
            int total_counted = 0;

            int color_slop = 40; // A grey scale pixel has r = g = b. But we will allow some slop in here just in case a bit of color creeps in
            int grey_scale_counted = 0;
            double greyScalePixelRatio = .9; // A greyscale image (given the above slop) will typically have about 90% of its pixels as grey scale

            const int SKIPPIXELS = 20;
            for (int i = 0; i < image1.Pixels.Length; i += SKIPPIXELS) // Check only every 20 pixels, as otherwise its a very expensive operation
            {
                byte b = (byte)image1.Pixels[i].Blue;
                byte g = (byte)image1.Pixels[i].Green;
                byte r = (byte)image1.Pixels[i].Red;

                total_counted++;

                // The numbers below convert a particular color to its greyscale equivalent
                // Colors are not weighted equally. Since pure green is lighter than pure red and pure blue, it has a higher weight.
                // Pure blue is the darkest of the three, so it receives the least weight.
                byte brightness = (byte)Math.Round((0.299 * r + +0.5876 * g + 0.114 * b));
                if (brightness <= darkPixelThreshold) dark_counted++;

                // Check if the pixel is a grey scale vs. color pixel. Note the heuristic.
                // Normally we should check r = g = b, but we allow a bit of slop as some cameras actually
                // have a bit of color in their dark shots (don't ask me why, it just happens).
                // i.e. if the total delta is less than the color slop, then we consider it a grey level.
                if (GetRgbDelta(r, g, b) <= color_slop) grey_scale_counted++;
            }

            // Check if its a grey scale image, i.e., at least 90% of the pixels in this image (given this slop) are grey scale.
            // If not, its a color image so judge it as not dark
            double greyScalePixelRatioFound = (1d * grey_scale_counted / total_counted);
            if (greyScalePixelRatioFound < greyScalePixelRatio)
            {
                darkPixelRatioFound = 1 - greyScalePixelRatioFound;
                isColor = true;
                return false;
            }
            darkPixelRatioFound = (1d * dark_counted / total_counted);
            isColor = false;
            return (darkPixelRatioFound >= darkPixelRatio);
        }
예제 #2
0
        // TODO: This needs to be fixed.
        public void ViewDifferencesCombined()
        {
            // If we are in any state other than the unaltered state, go to the unaltered state, otherwise the combined diff state
            if (whichImageState == (int)whichImage.NextDiff || whichImageState == (int)whichImage.PreviousDiff || whichImageState == (int) whichImage.CombinedDiff)
            {
                whichImageState = (int)whichImage.Unaltered;
            }
            else
            {
                whichImageState = (int)whichImage.CombinedDiff;
            }

            // If we are on the unaltered image
            if (whichImageState == (int)whichImage.Unaltered)
            {
                this.markableCanvas.imgToDisplay.Source = this.cachedImages[whichImageState];
                this.markableCanvas.imgToMagnify.Source = this.cachedImages[whichImageState];
                StatusBarUpdate.ClearMessage(this.statusBar);
                return;
            }

            // If we are on  the first image, or the last image, then don't do anything
            if (this.dbData.CurrentRow == 0 || this.dbData.CurrentRow == dbData.ImageCount - 1)
            {
                whichImageState = (int) whichImage.Unaltered;
                StatusBarUpdate.Message(this.statusBar, "Can't show combined differences without three good images");
                return;
            }

            // If any of the images are corrupted, then don't do anything
            if (!dbData.RowIsImageDisplayable() || !dbData.RowIsImageDisplayable(dbData.CurrentRow + 1) || !dbData.RowIsImageDisplayable(dbData.CurrentRow - 1))
            {
                whichImageState = (int) whichImage.Unaltered;
                StatusBarUpdate.Message(this.statusBar, "Can't show combined differences without three good images");
                return;
            }

            if (null == this.cachedImages[whichImageState])
            {
                // We need three valid images: the current one, the previous one, and the next one.
                // The current image is always in the cache. Create a PixeBitmap from it
                PixelBitmap currImage = new PixelBitmap((BitmapSource)cachedImages[(int)whichImage.Unaltered]);

                // Get the previous and next image
                int idx = dbData.CurrentRow - 1;

                string path = System.IO.Path.Combine(this.FolderPath, dbData.RowGetValueFromType((string)this.dbData.DataLabelFromType[Constants.FILE], idx));
                if (!File.Exists(path))
                {
                    StatusBarUpdate.Message(this.statusBar, "Can't show combined differences without three good images");
                    return;
                }
                BitmapImage prevImage = new BitmapImage(new Uri(path));

                idx = dbData.CurrentRow + 1; ;
                path = System.IO.Path.Combine(this.FolderPath, dbData.RowGetValueFromType((string)this.dbData.DataLabelFromType[Constants.FILE], idx));
                if (!File.Exists(path))
                {
                    StatusBarUpdate.Message(this.statusBar, "Can't show combined differences without three good images");
                    return;
                }
                BitmapImage nextImage = new BitmapImage(new Uri(path));

                // Generate the differenced image and dislay it
                PixelBitmap differencedImage = PixelBitmap.Difference(cachedImages[(int)whichImage.Unaltered], prevImage, nextImage, differenceThreshold);
                this.cachedImages[whichImageState] = differencedImage.ToBitmap();
            }

            whichImageState = (int)whichImage.CombinedDiff;
            this.markableCanvas.imgToDisplay.Source = this.cachedImages[whichImageState];
            StatusBarUpdate.Message(this.statusBar, "Viewing surrounding differences");
        }
예제 #3
0
        // Given three images, return an image that highlights the differences in common betwen the main image and the first image,
        // and the main image and a second image.
        //public static PixelBitmap Difference(PixelBitmap mainImg, PixelBitmap img1, PixelBitmap img2, byte threshold)
        public static PixelBitmap Difference(BitmapSource mainImgBM, BitmapSource img1BM, BitmapSource img2BM, byte threshold)
        {
            PixelBitmap mainImg = new PixelBitmap((BitmapSource)mainImgBM);
            PixelBitmap img1 = new PixelBitmap((BitmapSource)img1BM);
            PixelBitmap img2 = new PixelBitmap((BitmapSource)img2BM);
            // if images are not same size , use the smaller of their dimensions
            int width = Math.Min(mainImg.Width, img1.Width);
            width = Math.Min(width, img2.Width);
            int height = Math.Min(mainImg.Height, img1.Height);
            height = Math.Min(height, img2.Height);

            PixelColor[] pixelColor = new PixelColor[width * height]; //CHECK THIS - BOUNDS MAY NOT BE RIGHT
            for (int i = 0; i < pixelColor.Length; i++)
            {
                byte b1 = (byte)Math.Abs(mainImg.Pixels[i].Blue - img1.Pixels[i].Blue);
                byte b2 = (byte)Math.Abs(mainImg.Pixels[i].Blue - img2.Pixels[i].Blue);
                byte b = PixelBitmap.TempCalc(threshold, b1, b2);

                byte g1 = (byte)Math.Abs(mainImg.Pixels[i].Green - img1.Pixels[i].Green);
                byte g2 = (byte)Math.Abs(mainImg.Pixels[i].Green - img2.Pixels[i].Green);
                byte g = PixelBitmap.TempCalc(threshold, g1, g2);

                byte r1 = (byte)Math.Abs(mainImg.Pixels[i].Red - img1.Pixels[i].Red);
                byte r2 = (byte)Math.Abs(mainImg.Pixels[i].Red - img2.Pixels[i].Red);
                byte r = PixelBitmap.TempCalc(threshold, r1, r2);

                byte a = byte.MaxValue; // opaque
                var diff = (byte)(b / 3 + g / 3 + r / 3);
                var pixel = new PixelColor() { Alpha = a, Red = diff, Blue = diff, Green = diff };
                pixelColor[i] = pixel;
            }
            return new PixelBitmap() { Width = width, Height = height, Pixels = pixelColor };
        }
예제 #4
0
        // Cycle through the  image enhancements in the order current, then previous and next differenced images.
        // Create the differenced image if needed
        // For display efficiency, cache the differenced image.
        private void ViewDifferencesCycleThrough()
        {
            // Note:  No matter what image we are viewing, the source image will have already been cached before entering this function
            // Go to the next image in the cycle we want to show.
            NextInCycle();

            // If we are supposed to display the unaltered image, do it and get out of here.
            // The unaltered image will always be cached at this point, so there is no need to check.
            if (whichImageState == (int) whichImage.Unaltered)
            {
                 this.markableCanvas.imgToMagnify.Source = cachedImages[(int) whichImage.Unaltered];
                 this.markableCanvas.imgToDisplay.Source = cachedImages[(int) whichImage.Unaltered];

                 // Check if its a corrupted image
                 if (!dbData.RowIsImageDisplayable()) //TO DO AS WE MAY HAVE TO GET THE INDEX OF THE NEXT IN CYCLE IMAGE???
                 {
                     StatusBarUpdate.Message(this.statusBar, "Image is corrupted");
                 }
                 else
                 {
                     StatusBarUpdate.ClearMessage(this.statusBar);
                 }
                 return;
            }

            // If we don't have the cached difference image, generate and cache it.
            if (cachedImages[whichImageState] == null)
            {
                // Decide which comparison image to use for differencing.
                int idx;
                if ( whichImageState == (int)whichImage.PreviousDiff )
                {
                    idx = this.dbData.CurrentRow - 1;   // Find the previous image (unless we are already at the beginning)
                    if (idx < 0) idx = this.dbData.CurrentRow;
                }
                else
                {
                    idx = this.dbData.CurrentRow + 1;
                    if (idx >= dbData.ImageCount) idx = this.dbData.CurrentRow;
                }

                // Generate the differenced image.
                string fullFileName = System.IO.Path.Combine(this.FolderPath, this.dbData.RowGetValueFromDataLabel((string) this.dbData.DataLabelFromType [Constants.FILE], idx));
                // Check if that file actually exists
                if (!File.Exists (fullFileName))
                {
                    StatusBarUpdate.Message(this.statusBar, "Difference Image is missing");
                    return;
                }
                var otherImage = new BitmapImage(new Uri(fullFileName));
                var image1 = new PixelBitmap((BitmapSource)cachedImages[(int)whichImage.Unaltered]);
                var image2 = new PixelBitmap((BitmapSource)otherImage);
                var difference = image1 - image2;
                BitmapSource img = difference.ToBitmap();

                // and now cache the differenced image
                cachedImages[(int)whichImageState] = (BitmapSource)img;
            }
            // display the differenced image
            this.markableCanvas.imgToDisplay.Source = cachedImages[whichImageState];
            StatusBarUpdate.Message(this.statusBar, "Viewing " + ( (whichImageState == (int) whichImage.PreviousDiff) ? "previous" : "next") + " differenced image");
        }