/// <summary> /// Runs the motion detection algorithm /// </summary> /// <param name="NewImage">The "new" frame</param> /// <param name="OldImage">The "old" frame</param> /// <param name="Threshold">The threshold used to detect changes in the image</param> /// <param name="DetectionColor">Color to display changes in the images as</param> /// <returns>A bitmap indicating where changes between frames have occurred overlayed on top of the new image.</returns> public static Bitmap Process(Bitmap NewImage, Bitmap OldImage, int Threshold, Color DetectionColor) { NewImage.ThrowIfNull("NewImage"); OldImage.ThrowIfNull("OldImage"); DetectionColor.ThrowIfNull("DetectionColor"); using (Bitmap NewImage1 = NewImage.BlackAndWhite()) { using (Bitmap OldImage1 = OldImage.BlackAndWhite()) { using (Bitmap NewImage2 = NewImage1.SNNBlur(5)) { using (Bitmap OldImage2 = OldImage1.SNNBlur(5)) { using (Bitmap OutputImage = new Bitmap(NewImage2, NewImage2.Width, NewImage2.Height)) { using (Bitmap Overlay = new Bitmap(NewImage, NewImage.Width, NewImage.Height)) { BitmapData NewImage2Data = NewImage2.LockImage(); int NewImage2PixelSize = NewImage2Data.GetPixelSize(); BitmapData OldImage2Data = OldImage2.LockImage(); int OldImage2PixelSize = OldImage2Data.GetPixelSize(); BitmapData OverlayData = Overlay.LockImage(); int OverlayPixelSize = OverlayData.GetPixelSize(); int Width = OutputImage.Width; int Height = OutputImage.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color NewPixel = NewImage2Data.GetPixel(x, y, NewImage2PixelSize); Color OldPixel = OldImage2Data.GetPixel(x, y, OldImage2PixelSize); if (System.Math.Pow((double)(NewPixel.R - OldPixel.R), 2.0) > Threshold) { OverlayData.SetPixel(x, y, Color.FromArgb(100, 0, 100), OverlayPixelSize); } else { OverlayData.SetPixel(x, y, Color.FromArgb(200, 0, 200), OverlayPixelSize); } } }); Overlay.UnlockImage(OverlayData); NewImage2.UnlockImage(NewImage2Data); OldImage2.UnlockImage(OldImage2Data); using (Bitmap Overlay2 = Overlay.EdgeDetection(25, DetectionColor)) { BitmapData Overlay2Data = Overlay2.LockImage(); int Overlay2PixelSize = Overlay2Data.GetPixelSize(); Width = OutputImage.Width; Height = OutputImage.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color Pixel1 = Overlay2Data.GetPixel(x, y, Overlay2PixelSize); if (Pixel1.R != DetectionColor.R || Pixel1.G != DetectionColor.G || Pixel1.B != DetectionColor.B) { Overlay2Data.SetPixel(x, y, Color.FromArgb(200, 0, 200), Overlay2PixelSize); } } }); Overlay2.UnlockImage(Overlay2Data); return(OutputImage.Watermark(Overlay2, 1.0f, 0, 0, Color.FromArgb(200, 0, 200))); } } } } } } } }
public static Bitmap EdgeDetection(this Bitmap OriginalImage, float Threshold, Color EdgeColor, string FileName = "") { OriginalImage.ThrowIfNull("OriginalImage"); EdgeColor.ThrowIfNull("EdgeColor"); ImageFormat FormatUsing = FileName.GetImageFormat(); Bitmap NewBitmap = new Bitmap(OriginalImage, OriginalImage.Width, OriginalImage.Height); BitmapData NewData = NewBitmap.LockImage(); BitmapData OldData = OriginalImage.LockImage(); int NewPixelSize = NewData.GetPixelSize(); int OldPixelSize = OldData.GetPixelSize(); int Width = NewBitmap.Width; int Height = NewBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color CurrentColor = OldData.GetPixel(x, y, OldPixelSize); if (y < Height - 1 && x < Width - 1) { Color TempColor = OldData.GetPixel(x + 1, y + 1, OldPixelSize); if (Distance(CurrentColor.R, TempColor.R, CurrentColor.G, TempColor.G, CurrentColor.B, TempColor.B) > Threshold) NewData.SetPixel(x, y, EdgeColor, NewPixelSize); } else if (y < Height - 1) { Color TempColor = OldData.GetPixel(x, y + 1, OldPixelSize); if (Distance(CurrentColor.R, TempColor.R, CurrentColor.G, TempColor.G, CurrentColor.B, TempColor.B) > Threshold) NewData.SetPixel(x, y, EdgeColor, NewPixelSize); } else if (x < Width - 1) { Color TempColor = OldData.GetPixel(x + 1, y, OldPixelSize); if (Distance(CurrentColor.R, TempColor.R, CurrentColor.G, TempColor.G, CurrentColor.B, TempColor.B) > Threshold) NewData.SetPixel(x, y, EdgeColor, NewPixelSize); } } }); NewBitmap.UnlockImage(NewData); OriginalImage.UnlockImage(OldData); if (!string.IsNullOrEmpty(FileName)) NewBitmap.Save(FileName, FormatUsing); return NewBitmap; }
public static Bitmap DrawRoundedRectangle(this Bitmap Image, Color BoxColor, int XPosition, int YPosition, int Height, int Width, int CornerRadius, string FileName = "") { Image.ThrowIfNull("Image"); BoxColor.ThrowIfNull("BoxColor"); ImageFormat FormatUsing = FileName.GetImageFormat(); Bitmap NewBitmap = new Bitmap(Image, Image.Width, Image.Height); using (Graphics NewGraphics = Graphics.FromImage(NewBitmap)) { using (Pen BoxPen = new Pen(BoxColor)) { using (GraphicsPath Path = new GraphicsPath()) { Path.AddLine(XPosition + CornerRadius, YPosition, XPosition + Width - (CornerRadius * 2), YPosition); Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition, CornerRadius * 2, CornerRadius * 2, 270, 90); Path.AddLine(XPosition + Width, YPosition + CornerRadius, XPosition + Width, YPosition + Height - (CornerRadius * 2)); Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90); Path.AddLine(XPosition + Width - (CornerRadius * 2), YPosition + Height, XPosition + CornerRadius, YPosition + Height); Path.AddArc(XPosition, YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90); Path.AddLine(XPosition, YPosition + Height - (CornerRadius * 2), XPosition, YPosition + CornerRadius); Path.AddArc(XPosition, YPosition, CornerRadius * 2, CornerRadius * 2, 180, 90); Path.CloseFigure(); NewGraphics.DrawPath(BoxPen, Path); } } } if (!string.IsNullOrEmpty(FileName)) NewBitmap.Save(FileName, FormatUsing); return NewBitmap; }
private static float GetHeight(Color Color) { Color.ThrowIfNull("Color"); return (float)Color.R / 255.0f; }
/// <summary> /// Sets a pixel at the x,y coords /// </summary> /// <param name="Data">Bitmap data</param> /// <param name="x">X coord</param> /// <param name="y">Y coord</param> /// <param name="PixelColor">Pixel color information</param> /// <param name="PixelSizeInBytes">Pixel size in bytes</param> public static unsafe void SetPixel(this BitmapData Data, int x, int y, Color PixelColor, int PixelSizeInBytes) { Data.ThrowIfNull("Data"); PixelColor.ThrowIfNull("PixelColor"); byte* DataPointer = (byte*)Data.Scan0; DataPointer = DataPointer + (y * Data.Stride) + (x * PixelSizeInBytes); if (PixelSizeInBytes == 3) { DataPointer[2] = PixelColor.R; DataPointer[1] = PixelColor.G; DataPointer[0] = PixelColor.B; return; } DataPointer[3] = PixelColor.A; DataPointer[2] = PixelColor.R; DataPointer[1] = PixelColor.G; DataPointer[0] = PixelColor.B; }
/// <summary> /// Runs a simplistic motion detection algorithm /// </summary> /// <param name="NewImage">The "new" frame</param> /// <param name="OldImage">The "old" frame</param> /// <param name="Threshold">The threshold used to detect changes in the image</param> /// <param name="DetectionColor">Color to display changes in the images as</param> /// <returns>A bitmap indicating where changes between frames have occurred overlayed on top of the new image.</returns> public static Bitmap MotionDetection(this Bitmap NewImage, Bitmap OldImage, int Threshold, Color DetectionColor) { NewImage.ThrowIfNull("NewImage"); OldImage.ThrowIfNull("OldImage"); DetectionColor.ThrowIfNull("DetectionColor"); using (Bitmap NewImage1 = NewImage.BlackAndWhite()) { using (Bitmap OldImage1 = OldImage.BlackAndWhite()) { using (Bitmap NewImage2 = NewImage1.SNNBlur(5)) { using (Bitmap OldImage2 = OldImage1.SNNBlur(5)) { using (Bitmap OutputImage = new Bitmap(NewImage2, NewImage2.Width, NewImage2.Height)) { using (Bitmap Overlay = new Bitmap(NewImage, NewImage.Width, NewImage.Height)) { BitmapData NewImage2Data = NewImage2.LockImage(); int NewImage2PixelSize = NewImage2Data.GetPixelSize(); BitmapData OldImage2Data = OldImage2.LockImage(); int OldImage2PixelSize = OldImage2Data.GetPixelSize(); BitmapData OverlayData = Overlay.LockImage(); int OverlayPixelSize = OverlayData.GetPixelSize(); int Width = OutputImage.Width; int Height = OutputImage.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color NewPixel = NewImage2Data.GetPixel(x, y, NewImage2PixelSize); Color OldPixel = OldImage2Data.GetPixel(x, y, OldImage2PixelSize); if (System.Math.Pow((double)(NewPixel.R - OldPixel.R), 2.0) > Threshold) { OverlayData.SetPixel(x, y, Color.FromArgb(100, 0, 100), OverlayPixelSize); } else { OverlayData.SetPixel(x, y, Color.FromArgb(200, 0, 200), OverlayPixelSize); } } }); Overlay.UnlockImage(OverlayData); NewImage2.UnlockImage(NewImage2Data); OldImage2.UnlockImage(OldImage2Data); using (Bitmap Overlay2 = Overlay.EdgeDetection(25, DetectionColor)) { BitmapData Overlay2Data = Overlay2.LockImage(); int Overlay2PixelSize = Overlay2Data.GetPixelSize(); Width = OutputImage.Width; Height = OutputImage.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color Pixel1 = Overlay2Data.GetPixel(x, y, Overlay2PixelSize); if (Pixel1.R != DetectionColor.R || Pixel1.G != DetectionColor.G || Pixel1.B != DetectionColor.B) { Overlay2Data.SetPixel(x, y, Color.FromArgb(200, 0, 200), Overlay2PixelSize); } } }); Overlay2.UnlockImage(Overlay2Data); return OutputImage.Watermark(Overlay2, 1.0f, 0, 0, Color.FromArgb(200, 0, 200)); } } } } } } } }