我试过寻找这个,但我似乎无法找到任何代码来处理位图或png。我正在做一些计算,以从二值化图像中找到一组黑点的中心。我想通过在中心点画一个红点来了解中心是否正确。我使用的所有图形方法都在表单上绘制红点而不是保存的图像本身。如何在二值化图像上绘制红点? (二值化基本上意味着对图像应用阈值以获得光的位置)。我将在下面附上我的代码。基本上我按下按钮然后发生一些灰度算法然后我应用Bernsen阈值,并将该图像保存为“结果”。然后我查看图像结果并进行计算。我想在结果上用XCenter和YCenter画一个红点。
//Function for going through the image in windows of 2 pixels
private ArrayList getNeighbours(int xPos, int yPos, Bitmap bitmap)
{
ArrayList neighboursList = new ArrayList();
int xStart, yStart, xFinish, yFinish;
int pixel;
xStart = xPos - 2;
yStart = yPos - 2;
xFinish = xPos + 2;
yFinish = yPos + 2;
for (int y = yStart; y <= yFinish; y++)
{
for (int x = xStart; x <= xFinish; x++)
{
if (x < 0 || y < 0 || x > (bitmap.Width - 1) || y > (bitmap.Height - 1))
{
continue;
}
else
{
pixel = bitmap.GetPixel(x, y).R;
neighboursList.Add(pixel);
}
}
}
return neighboursList;
}
private void button5_Click_1(object sender, EventArgs e)
{
for (int i = 48; i < 49; i++)
{
BlackPoints = 0;
SumX = 0;
SumY = 0;
Xcenter = 0;
Ycenter = 0;
pictureBox2.Image = System.Drawing.Image.FromFile(@"C:\Users\Salma\Desktop\Images\" + i + ".png");
Bitmap image = new Bitmap(pictureBox2.Image);
/////////////Gray Scale First////////////////////
byte red, green, blue, grayscale;
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x < image.Width; x++)
{
red = image.GetPixel(x, y).R;
green = image.GetPixel(x, y).G;
blue = image.GetPixel(x, y).B;
grayscale = Convert.ToByte((red + green + blue) / 3);
image.SetPixel(x, y, Color.FromArgb(grayscale, grayscale, grayscale));
}
}
//////////////////////////////////////////////
//////////////Bernsen Threshold///////////////
Bitmap result = new Bitmap(pictureBox2.Image);
int iMin, iMax, t, c, contrastThreshold, pixel;
contrastThreshold = 110;
ArrayList list = new ArrayList();
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x < image.Width; x++)
{
list.Clear();
pixel = image.GetPixel(x, y).R;
list = getNeighbours(x, y, image);
list.Sort();
iMin = Convert.ToByte(list[0]);
iMax = Convert.ToByte(list[list.Count - 1]);
t = ((iMax + iMin) / 2);
c = (iMax - iMin);
if (c < contrastThreshold)
{
pixel = ((t >= 160) ? 0 : 255);
}
else
{
pixel = ((pixel >= t) ? 0 : 255);
}
result.SetPixel(x, y, Color.FromArgb(pixel, pixel, pixel));
}
}
pictureBox3.Image = result;
result.Save("C:\\Users\\Salma\\Desktop\\Threshold\\" + i + ".png");
for (int h = 0; h < result.Height; h++)
{
for (int w = 0; w < result.Width; w++)
{
//Get the color at each pixel
Color now_color = result.GetPixel(w, h);
//Compare Pixel's Color ARGB property with the picked color's ARGB Property
if (now_color.ToArgb() == Color.Black.ToArgb())
{
SumX += w;
SumY += h;
BlackPoints++;
Xcenter = SumX / BlackPoints;
Ycenter = SumY / BlackPoints;
}
}
}
}
}
答案 0 :(得分:1)
我认为错误在于计算中心。对于您在循环中执行的Xcenter = SumX / BlackPoints;
和Ycenter = SumY / BlackPoints;
。还有许多其他问题,例如:
Consequitive Assignments
bool flag = false;
flag = true;
或
ArrayList list = new ArrayList();
// inside the loop
list = getNeighbours(x, y, image);
和不必要的多次调用缓慢功能
red = image.GetPixel(x, y).R;
green = image.GetPixel(x, y).G;
blue = image.GetPixel(x, y).B;
使用ArrayList 代替推荐的List<byte>
或getNeighbours()
返回的任何类型。
我冒昧地试图在某种程度上清理代码:
private void button_Click(object sender, EventArgs e)
{
GrayScaleFirst();
BernsenThreshold();
if(GetBlackPixelCenter(out int xc, out int yc))
{
// use xc, yc
}
}
void GrayScaleFirst()
{
/////////////Gray Scale First////////////////////
byte grayscale;
Bitmap image=new Bitmap(pictureBox1.Image);
if(image==null)
{
return;
}
for(int y=0; y<image.Height; y++)
{
for(int x=0; x<image.Width; x++)
{
Color color=image.GetPixel(x, y);
grayscale=Convert.ToByte((color.R+color.G+color.B)/3);
image.SetPixel(x, y, Color.FromArgb(grayscale, grayscale, grayscale));
}
}
pictureBox1.Image=image;
}
void BernsenThreshold()
{
Bitmap gray=pictureBox1.Image as Bitmap;
Bitmap image=new Bitmap(pictureBox1.Image);
int iMin, iMax, t, c, contrastThreshold, pixel;
contrastThreshold=110;
for(int y=0; y<image.Height; y++)
{
for(int x=0; x<image.Width; x++)
{
Color color=gray.GetPixel(x, y);
pixel=color.R;
var list=GetNeighboursSorted(x, y, image);
iMin=list[0];
iMax=list[list.Count-1];
t=((iMax+iMin)/2);
c=(iMax-iMin);
if(c<contrastThreshold)
{
pixel=((t>=160)?0:255);
}
else
{
pixel=((pixel>=t)?0:255);
}
image.SetPixel(x, y, Color.FromArgb(pixel, pixel, pixel));
}
}
pictureBox1.Image=image;
}
bool GetBlackPixelCenter(out int x_center, out int y_center)
{
Bitmap image=pictureBox1.Image as Bitmap;
int black=Color.Black.ToArgb();
x_center=0; y_center=0;
int count = 0;
for(int h=0; h<image.Height; h++)
{
for(int w=0; w<image.Width; w++)
{
//Get the color at each pixel
Color now_color=image.GetPixel(w, h);
//Compare Pixel's Color ARGB property with the picked color's ARGB Property
if(now_color.ToArgb()==black)
{
x_center+=w;
y_center+=h;
count++;
}
}
}
x_center=count>0?x_center/count:0;
y_center=count>0?y_center/count:0;
return count>0;
}
static List<byte> GetNeighboursSorted(int x, int y, Bitmap image)
{
var list=new List<byte>();
int i1=Math.Max(0, y-1), i2=Math.Min(y+1, image.Height-1);
int j1=Math.Max(0, x-1), j2=Math.Min(x+1, image.Width-1);
for(int i=i1; i<=i2; i++)
{
for(int j=j1; j<=j2; j++)
{
if(i!=y && j!=x)
{
list.Add( Convert.ToByte(image.GetPixel(j, i).GetBrightness()*255));
}
}
}
list.Sort();
return list;
}
答案 1 :(得分:0)
我使用的所有图形方法都在图像上绘制红点而不是保存图像本身。
如何在二值化图像上绘制红点?
这是一个实现,如何在图像上绘制圆圈。
这很糟糕但是有效。
public void DrawCircl(Point index, Bitmap img,int Radius)
{
for (int i = 0; i < 360; i++)
{
double x = index.X - Radius * Math.Cos(2 * Math.PI / 360 * i);
double y = index.Y - Radius * Math.Sin(2 * Math.PI / 360 * i);
img.SetPixel((int)x, (int)y, Color.Red);
}
}
//This is your image from the pictureBox1
Bitmap img = new Bitmap(pictureBox1.Image);
// I am targeting the middle of the image, Your case would be the binarized image
Point index = new Point(img.Size.Width / 2, img.Size.Height / 2);
// Calling Draw Cirle Method, the last parameter is the radius.
DrawCircl(index,img,40);
// After the circle been drawn you save the image where you want
img.Save(@"[Path to Save IMG]");