What have you done and where are you stuck? If you haven't done anything, you don't know that you can't do it yourself yet.
What have you done and where are you stuck? If you haven't done anything, you don't know that you can't do it yourself yet.
I'm trying to find these markers through the webcam, but I can't do anything, the program finds unnecessary itemsPlease post just the relevant code as text in code tags.
Yes, the entire project is helpful for people who want to do try to fully reproduce the problem, but for more casual users of this forum, or those of us just reading on mobile devices, being able to read the code to focus on (if you'll pardon the pun) helps get more attention on your problem.
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)
{
}
}
}
Please post just the relevant code as text in code tags.
As @jmcilhinney , noted there still too much code that you dumped on us.
Just scanning the code, it looks like you are just looking for edges within a certain number of pixels away from each other, but you are not truly looking for that comb pattern that you are looking for.
Furthermore, it looks like you are only searching the top left third of the incoming image. I assume that's just leftover debugging code for the sake of speed, and eventually you'll want to search the entire image.
Choose an image processing algorithm and either implement it, or pull in a library that has an implementation. There's no need to roll your own algorithm from scratch unless this is schoolwork where you are being asked to design your own algorithm.
I don't know how well suited this algorithm is for what you need. I just happened to be the among the first that Google returned. But on the right side of screen, you'll also see a bunch of other well known algorithms that may suit your problem better:
Histogram of oriented gradients - Wikipedia
en.wikipedia.org
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;
private Rectangle? foundMarker = null;
private int currentThreshold = 50;
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();
BlackThresholdTrackBar.Value = currentThreshold;
}
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)
{
/*Bitmap image = (Bitmap)eventArgs.Frame.Clone();
Bitmap grayscaleImage = MakeGrayscale((Bitmap)image);
Bitmap binaryImage = Binarize(grayscaleImage, CalculateBlackThreshold(grayscaleImage));
ProcessImage(binaryImage);*/
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);
int centerX = width / 2;
int centerY = height / 2;
g.DrawLine(Pens.Blue, centerX - 10, centerY, centerX + 10, centerY);
g.DrawLine(Pens.Blue, centerX, centerY - 10, centerX, centerY + 10);
}
if (searchPixels)
{
ProcessImage((Bitmap)image);
}
VideoImage.Image = image;
}
private void ProcessImage(Bitmap image)
{
//Bitmap binaryImage = Binarize(image, CalculateBlackThreshold(image));
Bitmap binaryImage = Binarize(image, currentThreshold);
using (Graphics g = Graphics.FromImage(image))
{
Rectangle? markerRect = FindMarker(binaryImage);
if (markerRect.HasValue)
{
if (IsSurroundedByWhite(binaryImage, markerRect.Value))
{
g.DrawRectangle(Pens.Yellow, markerRect.Value);
}
/*else
{
g.DrawRectangle(Pens.Red, markerRect.Value);
}*/
}
}
}
private Rectangle? FindMarker(Bitmap binaryImage)
{
int width = binaryImage.Width;
int height = binaryImage.Height;
// Определение границ первого квадранта
int firstQuadrantStartX = 0;
int firstQuadrantStartY = 0;
int firstQuadrantEndX = width / 3;
int firstQuadrantEndY = height / 3;
// Определение границ девятого квадранта
int ninthQuadrantStartX = 2 * (width / 3);
int ninthQuadrantStartY = 2 * (height / 3);
int ninthQuadrantEndX = width;
int ninthQuadrantEndY = height;
int maxDistance = 5;
// Поиск маркера в первом квадранте
foundMarker = SearchInQuadrant(binaryImage, firstQuadrantStartX, firstQuadrantStartY, firstQuadrantEndX, firstQuadrantEndY, maxDistance);
if (foundMarker.HasValue)
{
return foundMarker;
}
// Поиск маркера в девятом квадранте
foundMarker = SearchInQuadrant(binaryImage, ninthQuadrantStartX, ninthQuadrantStartY, ninthQuadrantEndX, ninthQuadrantEndY, maxDistance);
if (foundMarker.HasValue)
{
return foundMarker;
}
return null;
}
private Rectangle? SearchInQuadrant(Bitmap binaryImage, int startX, int startY, int endX, int endY, int maxDistance)
{
int? minX = null, minY = null, maxX = null, maxY = null;
bool inMarker = false;
for (int y = startY; y < endY; y++)
{
int lastX = -1; // Последний найденный X
for (int x = startX; x < endX; x++)
{
int pixelColor = binaryImage.GetPixel(x, y).R;
if (pixelColor == 0) // Черный
{
if (!inMarker)
{
inMarker = true; // Начинаем новый маркер
minX = x; // Устанавливаем начальные границы
minY = y;
}
lastX = x; // Обновляем последний X
}
else if (pixelColor == 255 && inMarker) // Белый после черного
{
if (lastX != -1 && x - lastX <= maxDistance)
{
maxX = x; // Обновляем границы
maxY = y;
}
else
{
inMarker = false; // Заканчиваем текущий маркер
}
}
}
}
// Проверка по вертикали
for (int x = startX; x < endX; x++)
{
int lastY = -1; // Последний найденный Y
for (int y = startY; y < endY; y++)
{
int pixelColor = binaryImage.GetPixel(x, y).R;
if (pixelColor == 0) // Черный
{
if (!inMarker)
{
inMarker = true; // Начинаем новый маркер
minX = x; // Устанавливаем начальные границы
minY = y;
}
lastY = y; // Обновляем последний Y
}
else if (pixelColor == 255 && inMarker) // Белый после черного
{
if (lastY != -1 && y - lastY <= maxDistance)
{
maxY = y; // Обновляем границы
}
else
{
inMarker = false; // Заканчиваем текущий маркер
}
}
}
}
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];
// Используем порог для каждого канала
byte newColor = ((red < threshold) && (green < threshold) && (blue < threshold)) ? (byte)0 : (byte)255;
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 CalculateDynamicThreshold(Bitmap image, int startX, int startY, int endX, int endY)
{
double averageBrightness = CalculateAverageBrightnessInRegion(image, startX, startY, endX, endY);
double standardDeviation = CalculateStandardDeviationInRegion(image, startX, startY, endX, endY, averageBrightness);
return (int)(averageBrightness - 2 * standardDeviation);
}
private double CalculateAverageBrightnessInRegion(Bitmap image, int startX, int startY, int endX, int endY)
{
int sumBrightness = 0;
int count = 0;
for (int y = startY; y < endY; y++)
{
for (int x = startX; x < endX; 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 CalculateStandardDeviationInRegion(Bitmap image, int startX, int startY, int endX, int endY, double averageBrightness)
{
double sumSquaredDifference = 0;
int count = 0;
for (int y = startY; y < endY; y++)
{
for (int x = startX; x < endX; 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)
{
currentThreshold = BlackThresholdTrackBar.Value;
}
private bool IsSurroundedByWhite(Bitmap binaryImage, Rectangle marker)
{
bool isInFirstQuadrant = marker.Left < binaryImage.Width / 3 && marker.Top < binaryImage.Height / 3;
bool isInNinthQuadrant = marker.Left >= 2 * (binaryImage.Width / 3) && marker.Top >= 2 * (binaryImage.Height / 3);
if (isInFirstQuadrant)
{
// Проверка для первого квадранта
for (int x = marker.Left; x <= marker.Right; x++)
{
if (x < 0 || x >= binaryImage.Width) continue;
if (binaryImage.GetPixel(x, marker.Bottom + 1).R == 0) return false; // Проверка снизу
}
for (int y = marker.Top; y <= marker.Bottom; y++)
{
if (marker.Right + 1 >= binaryImage.Width) return false;
if (binaryImage.GetPixel(marker.Right + 1, y).R == 0) return false; // Проверка справа
}
}
else if (isInNinthQuadrant)
{
// Проверка для девятого квадранта
if (marker.Top > 0)
{
for (int x = marker.Left - 1; x <= marker.Right + 1; x++)
{
if (x < 0 || x >= binaryImage.Width) continue;
if (binaryImage.GetPixel(x, marker.Top - 1).R == 0) return false; // Проверка сверху
}
}
if (marker.Bottom + 1 < binaryImage.Height)
{
for (int x = marker.Left - 1; x <= marker.Right + 1; x++)
{
if (x < 0 || x >= binaryImage.Width) continue;
if (binaryImage.GetPixel(x, marker.Bottom + 1).R == 0) return false; // Проверка снизу
}
}
if (marker.Left > 0)
{
for (int y = marker.Top; y <= marker.Bottom; y++)
{
if (marker.Left - 1 < 0) return false;
if (binaryImage.GetPixel(marker.Left - 1, y).R == 0) return false; // Проверка слева
}
}
if (marker.Right + 1 < binaryImage.Width)
{
for (int y = marker.Top; y <= marker.Bottom; y++)
{
if (marker.Right + 1 >= binaryImage.Width) return false;
if (binaryImage.GetPixel(marker.Right + 1, y).R == 0) return false; // Проверка справа
}
}
}
return true;
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
}
}
}
Why is realtime processing needed? That looks like a static target typically used for air rifle or smallbore rifle -- neither of which is a dynamic environment to shoot in.