c# - 在位图 C# 的中心制作一个点
问题描述
我试过寻找这个,但我似乎找不到任何代码来处理位图或 png。我正在做一些计算以从二值化图像中找到一组黑点的中心。我想通过在中心点画一个红点来知道中心是否正确。我使用的所有图形方法都在表单上而不是在保存的图像本身上绘制红点。如何在二值化图像上绘制红点?(二值化基本上意味着对图像应用阈值以获得光线所在的位置)。我将在下面附上我的代码。基本上我按下一个按钮,然后发生一些灰度算法,然后我应用伯恩森阈值,并将该图像保存为“结果”。然后我检查图像结果并进行计算。我想在结果上用 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;
}
}
}
}
}
解决方案
我认为错误在于中心的计算。对于一个你正在做的事情Xcenter = SumX / BlackPoints;
,并且Ycenter = SumY / BlackPoints;
在循环中。还有很多其他问题,比如:
后续作业
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;
}
推荐阅读
- c# - 将 GetFieldValueAsync 与 GetFieldType 中的类型一起使用
- python - 如何为给定数据添加边和顶点?
- spring-security - 为什么添加 Spring Security 后会出现空指针异常?
- android - 转换 LiveData
- rundeck - Rundeck PSRP 插件
- nativescript - 如何减小 Nativescript BottomNavigation Tab 的图标大小
- r - Why is R converting dates to integer?
- java - 学习 For 和 While 循环,我对此代码的输出感到困惑
- r - 如何在 R 中整理凌乱的日期
- android - 如何通过 Android Cloud firestore 中的集合过滤器获取文档数