/// <summary> /// Search region of mokkans in image /// </summary> public static unsafe Rectangle SearchMokkanRegion(Bitmap image, Rectangle rect) { Bitmap bin = Binarization.Threshold(image, rect, MkaDefine.THRESHOLD); BitmapData bmd = bin.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.WriteOnly, bin.PixelFormat); // calculate projection profiles int wid = image.Width; int hei = image.Height; int stride = bmd.Stride; int[] hProj = new int[wid]; int[] vProj = new int[hei]; int left = rect.Left; int right = rect.Right; int top = rect.Top; int bottom = rect.Bottom; // search vertical range byte *ptr = (byte *)bmd.Scan0.ToPointer(); Histogram.VerHistB(ptr, bmd.Stride, rect, vProj); SearchMokkanRegion(vProj, ref top, ref bottom); // remove upper part ptr = (byte *)bmd.Scan0.ToPointer(); for (int y = 0; y <= top; y++) { SystemTools.SetUnmanagedMemory(ptr, 255, wid); ptr += wid; } // remove lower part ptr = (byte *)bmd.Scan0.ToPointer() + (bottom - 1) * stride; for (int y = 0; y < hei - bottom; y++) { SystemTools.SetUnmanagedMemory(ptr, 255, wid); ptr += wid; } // search horizontal range ptr = (byte *)bmd.Scan0.ToPointer(); Histogram.HorHistB(ptr, bmd.Stride, rect, hProj); SearchMokkanRegion(hProj, ref left, ref right); bin.UnlockBits(bmd); bin.Dispose(); return(Rectangle.FromLTRB(left, top, right, bottom)); }
/// <summary> /// Color filtering in YCbCr color space. /// </summary> public static unsafe Bitmap YCbCrFilter(Bitmap image, Rectangle rect, DoubleRange Y, DoubleRange Cb, DoubleRange Cr) { Bitmap dest = new Bitmap(image.Width, image.Height, PixelFormat.Format8bppIndexed); BitmapData source = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat); BitmapData destination = dest.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, dest.PixelFormat); int startX = rect.Left; int startY = rect.Top; int stopX = rect.Right; int stopY = rect.Bottom; // get pixel size int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; int srcOffset = source.Stride - rect.Width * pixelSize; int dstOffset = destination.Stride - rect.Width; RGB rgb = new RGB(); YCbCr ycbcr = new YCbCr(); // do the job byte *src = (byte *)source.Scan0 + startY * source.Stride + startX * pixelSize; byte *dst = (byte *)destination.Scan0 + startY * destination.Stride + startX; // for each row for (int y = startY; y < stopY; y++) { // for each pixel for (int x = startX; x < stopX; x++, src += pixelSize, dst++) { rgb.Red = src[RGB.R]; rgb.Green = src[RGB.G]; rgb.Blue = src[RGB.B]; // convert to YCbCr ycbcr = YCbCr.FromRGB(rgb); // check YCbCr values if (Y.IsInside(ycbcr.Y) & Cb.IsInside(ycbcr.Cb) && Cr.IsInside(ycbcr.Cr)) { *dst = 0; } else { *dst = 255; } } src += srcOffset; dst += dstOffset; } int width = image.Width; int height = image.Height; int stride = destination.Stride; // remove upper part for (int y = 0; y < startY; y++) { dst = (byte *)destination.Scan0.ToPointer() + y * stride; SystemTools.SetUnmanagedMemory(dst, 255, stride); } // remove lower part for (int y = stopY; y < height; y++) { dst = (byte *)destination.Scan0.ToPointer() + y * stride; SystemTools.SetUnmanagedMemory(dst, 255, stride); } for (int y = startY; y < stopY; y++) { // remove left part dst = (byte *)destination.Scan0.ToPointer() + y * stride; SystemTools.SetUnmanagedMemory(dst, 255, startX); // remove right part dst += stopX; SystemTools.SetUnmanagedMemory(dst, 255, stride - stopX); } image.UnlockBits(source); dest.UnlockBits(destination); return(dest); }