hi, i want to convert a color image into a greyscale image. after loading the color image, i have to count pixel by pixel to get the frequency of the color (0-255) to be placed in an array. can anyone help me how to count the frequency? thx in advance.

Recommended Answers

All 12 Replies

by "frequency of the colour" do you mean count how many pixels are, for example red (255,0,0) or some other specified color (230,126,72 for example)? What do you mean when you say "to be placed in an array"? (an array of every colour and their frequencies would be 256^3 (i think) big, ie 16777216 elements, and pretty pointless...)

If this is the case, do you know how to get the colour information from the image (for a particular pixel)?

Do you know how to loop through a 2D array?

Just trying to work out what you are asking (oh, and does this have anything to do with making it grayscale or is that just some information about what you are doing generally?)

hey, yeah it is to convert it to a grayscale image and then set a threshold value so then i can get the detected edge. i got d output now, but it is kinda weird seeing the binarized image after thresholding. i wonder if there is something wrong with my code:

int sum = 0;
for (int x = 0; x < frequency.length; x++)
{
                sum += frequency[x];
                frequency[x] = sum * maxIntensity /(256 *256);
}

:/

I really have no idea how you got a grayscale image from the frequencies of the colours... To get Grayscale image I would:

grayPixel[x,y] = (1/3)*getPixelRed(x,y) + (1/3)*getPixelGreen(x,y) + (1/3)*getPixelBlue(x,y);

where getPixelRed etc is the Red value of the pixel at x,y. (it doesnt have to be 1/3 each tho, just easiest).


Did you check your grayscale image worked before you did thresholding?

yes, i did check the grayscale before i set the threshold value and it works well. here is my code:

process_input = new int[width * height];
        process_grey = new int[width * height];
        counter = 0;

        for (int i = 0; i < 256; i++)
        {
            for (int j = 0; j < 256; j++)
            {
                int clr = buff_grey.getRGB(j,i);
                int red = (clr & 0x00ff0000) >> 16;
                int green = (clr & 0x0000ff00) >> 8;
                int blue = clr & 0x000000ff;
                int grey = (Math.round(0.299f*red + 0.587f*green + 0.114f*blue));
                process_input[counter] = clr;
                process_grey[counter] = grey;
                counter++;
            }
        }

everything works fine and no error but im juz not sure coz diz is my first time doing an image processing.

You are trying to make a histogram like this this? to find the threshold? Is that what the above code is trying to do (and is this the code that doesnt work?)

If that is trying to find the threashold, why are you not inputing the grayscale image you made? I would do the following:

public int[] getIntensityFrequencyHistogram(byte[] inputImage)
{
	//dont need width or height (or 2D array, in fact we dont
	//even need the pixels in order!)
	
	//the returned histogram
	int[] histogram = new int[256];
	
	//go through each pixel's intensity in our image
	for (byte pixelIntensity : inputImage)
	{
		//increase the appropriate pixel Intesnsity's count
		//in the histogram
		histogram[pixelIntensity]++;
	}
	
	return histogram;
}

is that the kind of thing you are trying to do?

yes, it is. but here i dont use a histogram. my system works flow is:
buffer image -> count the frequency of 0-255 -> set threshold value -> binarizing -> show output.

in the class where i put the method for buffer image, i have the following code:

int[] frequency = new int[256]; //freq of every single density
        int maxIntensity = 255;
        for (int x = 0; x < 256; x++)
        {
                for (int y = 0; y < 256; y++)
                {
                        double[] pixel = new double[1];
                        pixel = input.getRaster().getPixel(x,y,pixel);
                        frequency[(int)pixel[0]]++;
                }
        }

        int sum = 0;
        for (int x = 0; x < frequency.length; x++)
        {
                sum += frequency[x];
                frequency[x] = sum * maxIntensity /(256 *256);
        }

        for (int x = 0; x < 256; x++)
        {
                for (int y = 0; y < 256; y++)
                {
                        double[] pixel = new double[1];
                        pixel = input.getRaster().getPixel(x,y,pixel);
                        pixel[0] = frequency[(int)pixel[0]];
                        output.getRaster().setPixel(x, y, pixel);
                }
        }

am i on the right path?

The above is frequency counting and it looks similar to mine, is it a conicidence that your image is 256 by 256? or is that a mistake, (image.getWidth() and image.getHeight() would be better)

Looks fine to me, almost identical to this i found 5 :P

ohh i feel relieve now. :) thanks so much hanvyj! hmm yea, it should be image.getWidth() and image.getHeight()
by the way i cant access the link u gave me, it says d post is no longer there :-/
so now its working and it shows the black and white image (binarizing) :)
and then i wanna do it further by getting the red, green, and blue component from the image and set the threshold value to get the binarized images. from those 3 binarized images, i combine them become one binarized image. my question is, do i need other methods to count the frequency or i can use the one i have done?

I would have a look at the double[] returned by the raster, I can't find any info on what that actually is - its an array, but only 1 big??? strange also why is it double if its 0-255?? I've never used it before - maybe you are only getting the red values and if you set double[] pixel = double[3] and check pixel[0]=red pixel[1]=green pixel[2]=blue with some block colour images or something you could work it out...

otherwise there are loads of ways to get pixel info, for example if its a bufferedImage

int[] pixels = img.getRGB(0,0, img.getWidth(), img.getHeight, null, 0, img.getWidth());

or a raster:

Raster r = img.getData();
int[] pixels = r.getPixels(0,0,r.getWidth(), r.getHeight());

then you can just use what you have done on each pixel colour to create the three different threasholds you want

Have a look at the PixelGrabber class for getting pixels from images in general

i've changed the double to int and it gives no difference so i used int instead since, yeah, it's 0-255.

anyway, i feel like im almost done but it doesnt seem to show the output after combination of the three. here is my code to be clear;

//class Freq.java
     private void processActionPerformed(java.awt.event.ActionEvent evt) {                                        
        width = inputimage.getWidth(null);
        height = inputimage.getHeight(null);

        buff_grey = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
        Graphics gr = buff_grey.getGraphics();
        gr.drawImage(inputimage,0,0,null);
        gr.dispose();

        process_input = new int[width * height];
        process_grey = new int[width * height];
        counter = 0;

        for (int i = 0; i < 256; i++)
        {
            for (int j = 0; j < 256; j++)
            {
                int clr = buff_grey.getRGB(j,i);
                int red = (clr & 0x00ff0000) >> 16;
                int green = (clr & 0x0000ff00) >> 8;
                int blue = clr & 0x000000ff;
                int grey = (Math.round(0.299f*red + 0.587f*green + 0.114f*blue));
                process_input[counter] = clr;
                process_grey[counter] = grey;
                counter++;
            }
        }

        int threshold = 180;

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                int bin = (buff_grey.getRGB(x, y) & 0x000000ff);
                if (bin < threshold)
                    bin = 0;
                else
                    bin = 255;
                buff_grey.setRGB(x,y, 0xff000000 | bin << 16 | bin << 8 | bin);
            }
        } 
        repaint();

        buff_red = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        buff_green = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        buff_blue = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

        Graphics r = buff_red.getGraphics();
        Graphics g = buff_green.getGraphics();
        Graphics b = buff_blue.getGraphics();

        r.drawImage(inputimage,0,0,null);
        g.drawImage(inputimage,0,0,null);
        b.drawImage(inputimage,0,0,null);

        r.dispose();
        g.dispose();
        b.dispose();

        process_red = new int[width * height];
        counter = 0;
        for(int i = 0; i < 256; i++)
        {
                for(int j = 0; j < 256; j++)
                {
                        int clr = buff_red.getRGB(j, i);
                        int red = (clr & 0x00ff0000) >> 16;
                        red = (0xFF<<24)|(red<<16)|(red<<8)|red;
                        process_red[counter] = red;
                        counter++;
                }
        }

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                int bin = (buff_red.getRGB(x, y) & 0x000000ff);
                if (bin < threshold)
                    bin = 0;
                else
                    bin = 255;
                buff_red.setRGB(x,y, 0xff000000 | bin << 16 | bin << 8 | bin);
            }
        }

        /* here is d part for green and blue
         * which i did d same way as 2 fors function above
         * on the red element 
         */  

        process_combine = new int[width * height];
        counter = 0;
        for(int i = 0; i < 256; i++)
        {
                for(int j = 0; j < 256; j++)
                {
                   int clr_a = buff_red.getRGB(j, i);
                   int ar = clr_a & 0x000000ff;
                   int clr_b = buff_green.getRGB(j, i);
                   int bg = clr_b & 0x000000ff;
                   int clr_c = buff_blue.getRGB(j, i);
                   int cb = clr_b & 0x000000ff;
                   int alpha = 0xff000000;
                   int combine = alpha|(ar<<16)|(bg<<8)|cb;
                   process_combine[counter] = combine;
                   counter++;
                }
        }

        buff_rgb = new BufferedImage(width,height, BufferedImage.TYPE_INT_ARGB);
        Graphics rgb;
        rgb = buff_rgb.getGraphics();
        rgb.drawImage(output_rgb, 0, 0, null);
        rgb.dispose();
        repaint();
    }

  public void paint(Graphics g)
  {
        g.drawImage(inputimage,100,100,this);
        g.drawImage(buff_grey,450,100,this);
        g.drawImage(buff_rgb,800,100,this);
  }
public class FreqCounting {
    public static BufferedImage Image(BufferedImage input)
    {
        BufferedImage output = new BufferedImage(256,256,BufferedImage.TYPE_INT_RGB);
        
        //freq of every single density
        int[] frequency = new int[256]; 
        int maxIntensity = 255;

        //get pixel information from input image
        for (int x = 0; x < input.getWidth(); x++)
        {
                for (int y = 0; y < input.getHeight(); y++)
                {
                        int[] pixel = new int[1];
                        pixel = input.getRaster().getPixel(x,y,pixel);
                        frequency[pixel[0]]++;
                }
        }

        //count the frequency of color (0-255)
        for (int x = 0; x < frequency.length; x++)
        {
             int sum = 0;
             sum = sum + frequency[x];
             frequency[x] = sum * maxIntensity /(256 * 256);
        }

        //get the pixel information from output image
        for (int x = 0; x < output.getWidth(); x++)
        {
                for (int y = 0; y < output.getHeight(); y++)
                {
                        int[] pixel = new int[1];
                        pixel = output.getRaster().getPixel(x,y,pixel);
                        pixel[0] = frequency[(int)pixel[0]];
                        output.getRaster().setPixel(x, y, pixel);
                }
        }
        return output;
   }

since i already have a method to count the freq color (0-255), isn't it supposed to show 2 outputs which are the binarized image from grayscaling and another binarized image after combining? (right now i just have one output which is from the greyscaling process). or is it something wrong with the parameter passed in the 3rd drawimage method?

mmm okay, i've found out which part i got wrong for displaying the last output. but now my problem is, i dont get the edge map after the combination of the 3, i guess it's the problem with my combine function and i've been trying to fix it but it didnt work. instead of showing me the edge map i got the original image. anyone pls help me :( thx in advance.

process_combine = new int[width * height];
        counter = 0;
        for(int i = 0; i < 256; i++) {
            for(int j = 0; j < 256; j++) {
                int clr_a = buff_red.getRGB(j, i);
                int ar = clr_a & 0x000000ff;
                int clr_b = buff_green.getRGB(j, i);
                int bg = clr_b & 0x000000ff;
                int clr_c = buff_blue.getRGB(j, i);
                int cb = clr_b & 0x000000ff;
                int alpha = 0xff000000;
                int combine = (clr_a * clr_b * clr_c) * alpha;
                combine =(alpha|(ar<<16)|(bg<<8)|cb);
                process_input[counter] = (clr_a * clr_b * clr_c);
                process_combine[counter] = combine;
                counter++;
            }
        }
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.