using AForge.Imaging.Filters;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Drawing.Imaging;
namespace Shooting
{
public partial class Form1 : Form
{
private FilterInfoCollection CaptureDevices;
private VideoCaptureDevice FinalFrame;
private bool searchPixels = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
CaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo Device in CaptureDevices)
{
DeviceNameToolStripMenuItem.Items.Add(Device.Name);
}
DeviceNameToolStripMenuItem.SelectedIndex = 0;
StartVideoImage();
}
private void StartVideoImage()
{
FinalFrame = new VideoCaptureDevice(CaptureDevices[DeviceNameToolStripMenuItem.SelectedIndex].MonikerString);
FinalFrame.NewFrame += new NewFrameEventHandler(FinalFrame_NewFrame);
FinalFrame.Start();
}
private void FinalFrame_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
System.Drawing.Image image = (Bitmap)eventArgs.Frame.Clone();
image = MakeGrayscale((Bitmap)image);
using (Graphics g = Graphics.FromImage(image))
{
int width = image.Width;
int height = image.Height;
int thirdWidth = width / 3;
int thirdHeight = height / 3;
g.DrawLine(Pens.Red, thirdWidth, 0, thirdWidth, height);
g.DrawLine(Pens.Red, 2 * thirdWidth, 0, 2 * thirdWidth, height);
g.DrawLine(Pens.Red, 0, thirdHeight, width, thirdHeight);
g.DrawLine(Pens.Red, 0, 2 * thirdHeight, width, 2 * thirdHeight);
}
if (searchPixels)
{
ProcessImage((Bitmap)image);
}
VideoImage.Image = image;
}
private void ProcessImage(Bitmap image)
{
Bitmap binaryImage = Binarize(image, CalculateBlackThreshold(image));
using (Graphics g = Graphics.FromImage(image))
{
Rectangle? markerRect = FindMarker(binaryImage);
if (markerRect.HasValue)
{
g.DrawRectangle(Pens.Yellow, markerRect.Value);
}
}
}
private Rectangle? FindMarker(Bitmap binaryImage)
{
int width = binaryImage.Width / 3;
int height = binaryImage.Height / 3;
int maxDistance = 5;
int? minX = null, minY = null, maxX = null, maxY = null;
for (int y = 0; y < height; y++)
{
int horizontalCurrentColor = -1;
int horizontalCount = 0;
int horizontalLastX = -1;
for (int x = 0; x < width; x++)
{
int pixelColor = binaryImage.GetPixel(x, y).R;
if (pixelColor != horizontalCurrentColor)
{
if (horizontalCurrentColor != -1)
{
if ((horizontalCurrentColor == 0 && pixelColor == 255) || (horizontalCurrentColor == 255 && pixelColor == 0) ||
(Math.Abs(horizontalCurrentColor - pixelColor) <= 1))
{
if (horizontalLastX != -1 && (x - horizontalLastX) <= maxDistance)
{
horizontalCount++;
}
else
{
horizontalCount = 1;
}
}
else
{
horizontalCount = 0;
}
}
horizontalCurrentColor = pixelColor;
horizontalLastX = x;
if (horizontalCount >= 3)
{
if (!minX.HasValue || x < minX) minX = x;
if (!maxX.HasValue || x > maxX) maxX = x;
if (!minY.HasValue || y < minY) minY = y;
if (!maxY.HasValue || y > maxY) maxY = y;
}
}
}
}
for (int x = 0; x < width; x++)
{
int verticalCurrentColor = -1;
int verticalCount = 0;
int verticalLastY = -1;
for (int y = 0; y < height; y++)
{
int pixelColor = binaryImage.GetPixel(x, y).R;
if (pixelColor != verticalCurrentColor)
{
if (verticalCurrentColor != -1)
{
if ((verticalCurrentColor == 0 && pixelColor == 255) || (verticalCurrentColor == 255 && pixelColor == 0) ||
(Math.Abs(verticalCurrentColor - pixelColor) <= 1))
{
if (verticalLastY != -1 && (y - verticalLastY) <= maxDistance)
{
verticalCount++;
}
else
{
verticalCount = 1;
}
}
else
{
verticalCount = 0;
}
}
verticalCurrentColor = pixelColor;
verticalLastY = y;
if (verticalCount >= 3)
{
if (!minX.HasValue || x < minX) minX = x;
if (!maxX.HasValue || x > maxX) maxX = x;
if (!minY.HasValue || y < minY) minY = y;
if (!maxY.HasValue || y > maxY) maxY = y;
}
}
}
}
if (minX.HasValue && minY.HasValue && maxX.HasValue && maxY.HasValue)
{
return new Rectangle(minX.Value, minY.Value, maxX.Value - minX.Value, maxY.Value - minY.Value);
}
return null;
}
private Bitmap Binarize(Bitmap original, int threshold)
{
Bitmap binarizedBmp = new Bitmap(original.Width, original.Height);
Rectangle rect = new Rectangle(0, 0, original.Width, original.Height);
BitmapData originalData = original.LockBits(rect, ImageLockMode.ReadOnly, original.PixelFormat);
BitmapData binarizedData = binarizedBmp.LockBits(rect, ImageLockMode.WriteOnly, binarizedBmp.PixelFormat);
unsafe
{
byte* originalPtr = (byte*)originalData.Scan0;
byte* binarizedPtr = (byte*)binarizedData.Scan0;
for (int y = 0; y < original.Height; y++)
{
for (int x = 0; x < original.Width; x++)
{
int pixelIndex = y * originalData.Stride + x * 4;
byte blue = originalPtr[pixelIndex];
byte green = originalPtr[pixelIndex + 1];
byte red = originalPtr[pixelIndex + 2];
int brightness = (int)(red * 0.3 + green * 0.59 + blue * 0.11);
byte newColor = (byte)(brightness >= threshold ? 255 : 0);
binarizedPtr[pixelIndex] = newColor;
binarizedPtr[pixelIndex + 1] = newColor;
binarizedPtr[pixelIndex + 2] = newColor;
binarizedPtr[pixelIndex + 3] = 255;
}
}
}
original.UnlockBits(originalData);
binarizedBmp.UnlockBits(binarizedData);
return binarizedBmp;
}
private int CalculateBlackThreshold(Bitmap image)
{
double averageBrightness = CalculateAverageBrightness(image);
double standardDeviation = CalculateStandardDeviation(image, averageBrightness);
return (int)(averageBrightness - 2 * standardDeviation);
}
private double CalculateAverageBrightness(Bitmap image)
{
int sumBrightness = 0;
int count = 0;
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x < image.Width; x++)
{
Color pixelColor = image.GetPixel(x, y);
int brightness = (int)(pixelColor.R * 0.3 + pixelColor.G * 0.59 + pixelColor.B * 0.11);
sumBrightness += brightness;
count++;
}
}
return (double)sumBrightness / count;
}
private double CalculateStandardDeviation(Bitmap image, double averageBrightness)
{
double sumSquaredDifference = 0;
int count = 0;
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x < image.Width; x++)
{
Color pixelColor = image.GetPixel(x, y);
int brightness = (int)(pixelColor.R * 0.3 + pixelColor.G * 0.59 + pixelColor.B * 0.11);
double squaredDifference = Math.Pow(brightness - averageBrightness, 2);
sumSquaredDifference += squaredDifference;
count++;
}
}
return Math.Sqrt(sumSquaredDifference / count);
}
public Bitmap MakeGrayscale(Bitmap original)
{
Bitmap newBmp = new Bitmap(original.Width, original.Height);
using (Graphics g = Graphics.FromImage(newBmp))
{
ColorMatrix colorMatrix = new ColorMatrix(new float[][]
{
new float[] {0.3f, 0.3f, 0.3f, 0, 0},
new float[] {0.59f, 0.59f, 0.59f, 0, 0},
new float[] {0.11f, 0.11f, 0.11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
ImageAttributes imgAttr = new ImageAttributes();
imgAttr.SetColorMatrix(colorMatrix);
g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, imgAttr);
}
return newBmp;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (FinalFrame != null)
{
if (FinalFrame.IsRunning)
{
FinalFrame.SignalToStop();
FinalFrame.WaitForStop();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
searchPixels = true;
}
private void BlackThresholdTrackBar_Scroll(object sender, EventArgs e)
{
}
}
}