在位图C#的中心创建一个点

时间:2018-05-08 17:23:18

标签: c# image bitmap

我试过寻找这个,但我似乎无法找到任何代码来处理位图或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;



                    }
                }
            }

        }
    }

2 个答案:

答案 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]");