/// <summary> /// Fill the holes in the binary image /// </summary> /// <param name="b"></param> protected Bitmap FillHoles( Bitmap b ) { // clone and invert the bitmap ( which turns holes into islands ! ) Bitmap nb = new Bitmap( b ); // invert it BlobMap.InvertImage( nb ); // create a temporary blob map which will capture the former holes as islands BlobMap bm = new BlobMap( nb ); // fill holes bm.FillHoles( nb ); // invert image with holes filled again ! BlobMap.InvertImage( nb ); // return the image with the holes fill return nb; }
/// <summary> /// Create a new image based on the given sub image with the candidate red eye removed /// </summary> /// <param name="b"></param> public Bitmap ProcessImage( Bitmap b ) { // temporary images used to remove red eye Bitmap rednessMask=null, rednessThreshold=null, falseColor=null, noSmallIslands=null, noHoles=null, blured=null; // the image to return Bitmap newImage = null; try { // get a CIEMap of the image and the min/max CIE L values for the image double minL, maxL; CIELab[] cieMap = this.GetCIELABImage( b, out minL, out maxL ); // get redness mask image rednessMask = this.GetMaskImage( cieMap, b.Width, b.Height ); // get a threshold of the redness mask rednessThreshold = this.Threshold( rednessMask ); // create a blob map from the threasholded image BlobMap blobmap = new BlobMap( rednessThreshold ); // create a false color copy of the thresholded images falseColor = (Bitmap)rednessThreshold.Clone(); blobmap.ColorIslands( falseColor ); // remove all islands meeting a certain size criteria noSmallIslands = (Bitmap)rednessThreshold.Clone(); blobmap.RemoveIslands( noSmallIslands ); // create a version with the holes filled noHoles = this.FillHoles( noSmallIslands ); // get a guassian blurred version of the final mask float[] kernel = ImageUtility.GetGaussianBlurKernel( 3, 15 ); blured = ImageUtility.Convolve( noHoles, kernel, 3 ); // create new image newImage = this.GetNewImage( cieMap, // CIE Lab image of the source minL, maxL, // min/max CIE L* values in the map blured ); // the final mask to be used // return new image return newImage; } catch ( Exception ) { } finally { // cleanup any temporaries used if ( rednessMask != null ) rednessMask.Dispose(); if ( rednessThreshold != null ) rednessThreshold.Dispose(); if ( falseColor != null ) falseColor.Dispose(); if ( noSmallIslands != null ) noSmallIslands.Dispose(); if ( noHoles != null ) noHoles.Dispose(); if ( blured != null ) blured.Dispose(); } // return new image return newImage; }