private void buildAnalysisImage(Bitmap bitmapCamera) { bitmapAnalysis = (Bitmap)bitmapCamera.Clone(); Graphics g = Graphics.FromImage(bitmapAnalysis); g.Clear(Color.Black); unsafe { BitmapData bitmapDataCamera = null; BitmapData bitmapDataNormal = null; BitmapData bitmapDataTrigger = null; BitmapData bitmapDataAnalysis = null; try { bitmapDataCamera = bitmapCamera.LockBits(new Rectangle(0, 0, bitmapCamera.Width, bitmapCamera.Height), ImageLockMode.ReadOnly, bitmapCamera.PixelFormat); bitmapDataNormal = BitmapNormal.LockBits(new Rectangle(0, 0, BitmapNormal.Width, BitmapNormal.Height), ImageLockMode.ReadOnly, BitmapNormal.PixelFormat); bitmapDataTrigger = BitmapTrigger.LockBits(new Rectangle(0, 0, BitmapTrigger.Width, BitmapTrigger.Height), ImageLockMode.ReadOnly, BitmapTrigger.PixelFormat); bitmapDataAnalysis = BitmapAnalysis.LockBits(new Rectangle(0, 0, BitmapTrigger.Width, BitmapTrigger.Height), ImageLockMode.WriteOnly, BitmapTrigger.PixelFormat); int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(bitmapCamera.PixelFormat) / 8; int heightInPixels = bitmapDataCamera.Height; int widthInBytes = bitmapDataCamera.Width * bytesPerPixel; byte *PtrFirstPixel = (byte *)bitmapDataCamera.Scan0; byte *PtrFirstPixelNormal = (byte *)bitmapDataNormal.Scan0; byte *PtrFirstPixelTrigger = (byte *)bitmapDataTrigger.Scan0; byte *PtrFirstPixelAnalysisImage = (byte *)bitmapDataAnalysis.Scan0; foreach (DetectionObject obj in detectionObjects) { int numPixels = obj.Rectangle.Width * obj.Rectangle.Height; int step = (numPixels / SamplesPerObject); if (step == 0) { step = 1; } int y = obj.Rectangle.Top; float maxDifference = (SamplesPerObject * bytesPerPixel * 256); while (y < obj.Rectangle.Bottom) { byte *currentLine = PtrFirstPixel + (y * bitmapDataCamera.Stride); byte *currentLineNormal = PtrFirstPixelNormal + (y * bitmapDataCamera.Stride); byte *currentLineTrigger = PtrFirstPixelTrigger + (y * bitmapDataCamera.Stride); byte *currentLineAnalysis = PtrFirstPixelAnalysisImage + (y * bitmapDataAnalysis.Stride); for (int x = obj.Rectangle.Left + (y % step); x < obj.Rectangle.Right; x += step) { int offsetX = x * bytesPerPixel; int differenceNormal = Math.Abs(currentLine[offsetX] - currentLineNormal[offsetX]); differenceNormal += Math.Abs(currentLine[offsetX + 1] - currentLineNormal[offsetX + 1]); differenceNormal += Math.Abs(currentLine[offsetX + 2] - currentLineNormal[offsetX + 2]); int differenceTrigger = Math.Abs(currentLine[offsetX] - currentLineTrigger[offsetX]); differenceTrigger += Math.Abs(currentLine[offsetX + 1] - currentLineTrigger[offsetX + 1]); differenceTrigger += Math.Abs(currentLine[offsetX + 2] - currentLineTrigger[offsetX + 2]); if (differenceNormal < differenceTrigger) { byte color = (byte)(255 - (differenceNormal / 3)); // difference is maximum 3*255 = 765. In that case outcome must be 255. currentLineAnalysis[offsetX + 1] = color; } else { byte color = (byte)(255 - (differenceTrigger / 3)); // difference is maximum 3*255 = 765. In that case outcome must be 255. currentLineAnalysis[offsetX + 2] = color; } } y++; } } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { bitmapCamera.UnlockBits(bitmapDataCamera); bitmapNormal.UnlockBits(bitmapDataNormal); bitmapTrigger.UnlockBits(bitmapDataTrigger); bitmapAnalysis.UnlockBits(bitmapDataAnalysis); } } }
unsafe public void analyze(Bitmap bitmapCamera) { var watch = System.Diagnostics.Stopwatch.StartNew(); BitmapData bitmapDataCamera = null; BitmapData bitmapDataNormal = null; BitmapData bitmapDataTrigger = null; try { bitmapDataCamera = bitmapCamera.LockBits(new Rectangle(0, 0, bitmapCamera.Width, bitmapCamera.Height), ImageLockMode.ReadOnly, bitmapCamera.PixelFormat); bitmapDataNormal = BitmapNormal.LockBits(new Rectangle(0, 0, BitmapNormal.Width, BitmapNormal.Height), ImageLockMode.ReadOnly, BitmapNormal.PixelFormat); bitmapDataTrigger = BitmapTrigger.LockBits(new Rectangle(0, 0, BitmapTrigger.Width, BitmapTrigger.Height), ImageLockMode.ReadOnly, BitmapTrigger.PixelFormat); int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(bitmapCamera.PixelFormat) / 8; int heightInPixels = bitmapDataCamera.Height; int widthInBytes = bitmapDataCamera.Width * bytesPerPixel; byte *PtrFirstPixel = (byte *)bitmapDataCamera.Scan0; byte *PtrFirstPixelNormal = (byte *)bitmapDataNormal.Scan0; byte *PtrFirstPixelTrigger = (byte *)bitmapDataTrigger.Scan0; foreach (DetectionObject obj in detectionObjects) { if (!obj.Active) { continue; } int numPixels = obj.Rectangle.Width * obj.Rectangle.Height; // TODO: make property of DetectionObject int step = (numPixels / SamplesPerObject); if (step == 0) { step = 1; } int y = obj.Rectangle.Top; int totalDifferenceNormal = 0; int totalDifferenceTrigger = 0; float maxDifference = ((numPixels / step) * bytesPerPixel * 255); while (y < obj.Rectangle.Bottom) { byte *currentLine = PtrFirstPixel + (y * bitmapDataCamera.Stride); byte *currentLineNormal = PtrFirstPixelNormal + (y * bitmapDataCamera.Stride); byte *currentLineTrigger = PtrFirstPixelTrigger + (y * bitmapDataCamera.Stride); byte *currentLineAnalysis = null; for (int x = obj.Rectangle.Left + (y % step); x < obj.Rectangle.Right; x += step) { int offsetX = x * bytesPerPixel; /* * totalDifferenceNormal += Math.Abs(currentLine[offsetX] - currentLineNormal[offsetX]); * totalDifferenceNormal += Math.Abs(currentLine[offsetX + 1] - currentLineNormal[offsetX + 1]); * totalDifferenceNormal += Math.Abs(currentLine[offsetX + 2] - currentLineNormal[offsetX + 2]); */ totalDifferenceTrigger += Math.Abs(currentLine[offsetX] - currentLineTrigger[offsetX]); totalDifferenceTrigger += Math.Abs(currentLine[offsetX + 1] - currentLineTrigger[offsetX + 1]); totalDifferenceTrigger += Math.Abs(currentLine[offsetX + 2] - currentLineTrigger[offsetX + 2]); } y++; } obj.DifferenceNormal = totalDifferenceNormal / maxDifference; float numSamples = numPixels / step; // When the difference is small enough, we make further investigation /* if (obj.DifferenceNormal < 0.05) * { * obj.SecondLevelDifferenceNormal = secondLevelAnalysis(bitmapDataCamera, bitmapDataNormal, obj, step, bytesPerPixel) / numSamples; * } */ obj.DifferenceTrigger = totalDifferenceTrigger / maxDifference; // When the difference is small enough, we make further investigation if (obj.DifferenceTrigger < 0.05) { obj.SecondLevelDifferenceTrigger = secondLevelAnalysis(bitmapDataCamera, bitmapDataTrigger, obj, step, bytesPerPixel) / numSamples; } obj.updateStatus(); } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { bitmapCamera.UnlockBits(bitmapDataCamera); bitmapNormal.UnlockBits(bitmapDataNormal); bitmapTrigger.UnlockBits(bitmapDataTrigger); } watch.Stop(); analysisTime = watch.ElapsedMilliseconds; if (makeAnalysisImage) { buildAnalysisImage(bitmapCamera); } }