Count how many pixels of a color the image has

Asked

Viewed 2,411 times

7

I am working on a solution for tattoo studios. I would like to know how it would be possible to determine how many pixels a certain color exists in the image inserted in pictureBox1.

In this image, for example, would it be possible to count only the diamond, that is, not counting the white space? or count only the white space (so it would be possible to subtract the value of the total area)?

Also show the count result in a textbox.

private void button3_Click(object sender, EventArgs e)
    {

        Form2 form = new Form2();

        form.Show();
        OpenFileDialog file = new OpenFileDialog();
        file.Filter = "jpg|*.jpg|png|*.png";
        if (file.ShowDialog() == DialogResult.OK)
        {
            form.pictureBox1.ImageLocation = file.FileName;
            var count = 0;
            var searchColor = Color.FromName("SlateBlue");
            for (var x = 0; x < form.pictureBox1.Image.Width; x++)
            {
                for (var y = 0; y < form.pictureBox1.Image.Height; y++)
                {
                    Color pixelColor = form.pictureBox1.Image.GetPixel(x, y);
                    if (pixelColor == searchColor)
                    {
                        count++;
                    }
                }
            }

It did not work. He does not accept ". Getpixel"

  • Guys, thank you very much, here are more details: I would need to press a button that would count how many pixels there are in the drawing, that is without the background, it is not necessary to define the color, just without counting the background. Request more details as needed. Obg

2 answers

8


EDIT: Another question came up with a similar problem, but using Java. So I essentially translated the code I created here (and even used the same example). If by chance any reader eventually need a solution also in the Java language, please reference this answer.

Well, since your image is not captured from the real world (a very important detail that you didn’t put in the original question), it’s much simpler to use a method like the limiarization to do the job automatically. The limiarization (thresholding in English) is a process in which you transform any image into a binary image (containing only two colors) replacing all pixels in the original image with one of the binary colors depending on their brightness being greater or less than a defined threshold.

As in your case the tattoo region is very distinct from the background, an average threshold value (0,5) is enough for an interesting result. But note that you may need to adjust it for a better effect on other images. The comparison is made with the brightness in the image, and the lower the brightness the closer the color is to black (so the code only counts the pixels in which the brightness is minor than the threshold).

Here is an example program:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Teste
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog file = new OpenFileDialog();
            file.Filter = "jpg|*.jpg|png|*.png";
            if (file.ShowDialog() == DialogResult.OK)
            {
                pictureBox1.ImageLocation = file.FileName;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            var limiar = 0.5;

            var count = 0;
            Bitmap img = new Bitmap(pictureBox1.Image);

            for (var x = 0; x < img.Width; x++)
            {
                for (var y = 0; y < img.Height; y++)
                {
                    Color pixelColor = img.GetPixel(x, y);
                    if (pixelColor.GetBrightness() < limiar)
                    {
                        count++;
                        img.SetPixel(x, y, Color.Red);
                    }
                }
            }
            pictureBox1.Image = img;

            var percent = ((float) count / (img.Width * img.Height)) * 100;
            label1.Text = String.Format("A tattoo contém {0:d} pixels (ou seja, uma área equivalente a {1:f}%)", count, percent);
        }
    }
}

The home screen has the Picture Box, two buttons (one to load the image and display it and one to process it) and a label to display the result:

inserir a descrição da imagem aqui

After processing, the code not only counts the pixels (and also the percentage, a value that is more effective because it is normalized independently to the dimensions of the image) but also changes the pixels of the tattoo to red to effectively demonstrate what has been calculated. Upshot:

inserir a descrição da imagem aqui

Note: The processing uses the class Bitmap not the Picture Box to access the raw pixels.

  • 1

    thank you very much man!!!!

8

As the question has no details, I will answer without details. It would be some more or less like this.

var count = 0;
var searchColor = Color.FromName("SlateBlue");
for (var x = 0; x < pictureBox1.Image.Width; x++) {
    for (var y = 0; y < pictureBox1.Image.Height; y++) {
        Color pixelColor = pictureBox1.Image.GetPixel(x, y);
        if (pixelColor == searchColor) count++;
    }
}

I put in the Github for future reference.

  • 1

    I would suggest adding to the answer something about normalizing the output. Because the images may have different sizes (Yes, the AP does not mention anything, but it is very likely that he can not guarantee the same size and focus of tattoo images), it must make more sense to return something like the percentage of the area with the color relative to the total area of the image than directly a count. :)

  • I don’t quite know the subject and maybe you could give a better answer. I can even help c/o C# if necessary. I just know that, naively, I would have to give the color a margin of tolerance and not get so exact. The percentage is easy, I could even put, is that it’s basic math. I wanted him to say something to better direct.

  • 1

    Guys, thank you very much, here are more details: I would need to press a button that would count how many pixels there are in the drawing, ie without the background, not being necessary to define the color, just not counting the background.

  • If more details are needed, I’ll be here

  • @bigown, the answer is great based on what the AP provided. And such normalization is even basic mathematics in the sense that put. :)

  • @Emanuelborges, in this case maybe it would be more interesting if you click on the color you want to count, capture the pixel clicked and use it as searchColor in the algorithm of this answer. Automatically differentiating background object is not such a trivial task. If the background is "skin", maybe this other question will give you an idea of the difficulties involved: http://answall.com/questions/104656/algoritmo-para-detectar-nudez-com-boa-precis%C3%A3o

  • @Emanuelborges for me was even more confused now :) I don’t know if Luiz understood better since he dominates the subject more.

  • @Emanuelborges: Edit the question and add details of the problem. If possible, mainly post an example image, and a diagram detailing which exact region you want to account for.

  • @Luizvieira:@Emanuelborges, in this case it might be more interesting to click on the color you want to count, capture the clicked pixel and use it as a searchColor in the algorithm of this answer. Automatically differentiating background object is not such a trivial task. If the background is "skin", maybe this other question will give you an idea of the difficulties involved. In this case, how would you do it in the code?

  • oh the @bigown popping in the answers!

  • Okay, I gave a new answer, based on the idea of this @bigown answer and the new issues of the question. :)

Show 6 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.