"Standard" conversion of RGB to grayscale

I am trying to write a converter algorithm that accepts a JPEG image and returns its version of PGM (Portable Gray Map). The problem is that I cannot understand how the “official” JPG-> PGM converters work in terms of what value should be assigned to the final pixel (I think 0-> 255), starting with the classic RGB format.

In the beginning I used this formula (it is also used to convert OpenCV CV_RGB2GRAY):

0.30 * R + 0.59 * G + 0.11 * B = val

I wrote simple code to test my results: it accepts a color image and its version of PGM (already converted using GIMP). He then converts the color image using the previous formula. The goal is to have a grayscale image that is pixel by pixel equal to the PGM input signal.

At this point, it does not return the same values. Can you help me?

+10
algorithm image jpeg pgm file-conversion
source share
6 answers

The problem is that I cannot understand how the “official” JPG-> PGM converters work in terms of what value should be assigned to the last pixel (I think 0-> 255), starting with the classic RGB format.

There is probably a gamma correction in the conversion that these "official" tools use. That is, it is not just a linear transformation.

For more information, see Wikipedia: Converting colors to grayscale.

I believe that you want to use the formula for C srgb .
Try and see if it matches the expected results.

Basically, you will do this:

  • Take the color R, G, B (each in the range [0,1] )
    • If they are in the range 0..255 instead, just divide by 255.0
  • Calculate C linear = 0.2126 R + 0.7152 G + 0.0722 B
    • This is most likely a linear transformation that you applied before
  • Calculate C srgb according to its formula based on C linear
    • This is a non - linear gamma correction that you were missing
    • Tick this graph. WolframAlpha
    • C srgb = 12.92 C linear when C linear <= 0.0031308
    • C srgb = 1.055 C linear 1/2.4 - 0.055 when C linear > 0.0031308
+12
source share

To reflect a point around the “Y plane”: standard color JPEGs are encoded using the YCbCr color space, where Y is the luminance of the component (ie luminance), and Cb and Cr are the color components with a blue difference and a red difference. Thus, one way to turn color JPEG into shades of gray is to simply drop the Cb and Cr components.

There is a utility called jpegtran that can do this without loss using the -grayscale option. (The lossless part really only matters if you want to get JPEG, not PGM, to avoid losing generation ). In any case, it would probably be the fastest way to do this conversion, because it does not even decode the image in pixels, much less do the math on each of them.

+4
source share

The middle method is the simplest. You just need to take an average of three colors. Since this is an RGB image, this means you must add r with g to b and then divide it by 3 to get the desired image in grayscale.

This is done in this way.

 Grayscale = (R + G + B / 3) 

If you have a color image like the one above and want to convert it to shades of gray using the averaging method.

+2
source share

In theory, with a few pixels (3, in this case), you can determine what their algorithm does. Juste select three pixels (p1, p2, p3), their RGB value and their gray PGM value, and you have:

RedConstant * p1.redValue + GreenConstant * p1.greenValue + BlueConstant * p1.blueValue = p1.grayValue

RedConstant * p2.redValue + GreenConstant * p2.greenValue + BlueConstant * p2.blueValue = p2.grayValue

RedConstant * p3.redValue + GreenConstant * p3.greenValue + BlueConstant * p3.blueValue = p3.grayValue.

Then solve this problem (find the "equation solver" or something else) and see what constants they use.

+1
source share

A SIMPLE ALGORITHM FOR CONVERTING RGB-IMAGES TO GRAYSKALL IN EXPERIENCED PYTHON!

I used comments, so the code requires no explanation. But it works fast.

 import cv2 import numpy as np img1 = cv2.imread('opencvlogo.png') row,col,ch = img1.shape g = [ ] #the list in which we will stuff single grayscale pixel value inplace of 3 RBG values #this function converts each RGB pixel value into single Grayscale pixel value and appends that value to list 'g' def rgb2gray(Img): global g row,col,CHANNEL = Img.shape for i in range(row) : for j in range(col): a = ( Img[i,j,0]*0.07 + Img[i,j,1]*0.72 + Img[i,j,2] *0.21 ) #the algorithm i used id , G = B*0.07 + G*0.72 + R* 0.21 #I found it online g.append(a) rgb2gray(img1) #convert the img1 into grayscale gr = np.array(g) #convert the list 'g' containing grayscale pixel values into numpy array cv2.imwrite("test1.png" , gr.reshape(row,col)) #save the image file as test1.jpg 

SO I used this image file ... enter image description here

My program created after the Grayscale file.

enter image description here

+1
source share

Converts a single input pixel in RGB ColorModel by default to one gray pixel.

 /* Convertation function * @param x the horizontal pixel coordinate * @param y the vertical pixel coordinate * @param rgb the integer pixel representation in the default RGB color model * @return a gray pixel in the default RGB color model.*/ public int filterRGB(int x, int y, int rgb) { // Find the average of red, green, and blue. float avg = (((rgb >> 16) & 0xff) / 255f + ((rgb >> 8) & 0xff) / 255f + (rgb & 0xff) / 255f) / 3; // Pull out the alpha channel. float alpha = (((rgb >> 24) & 0xff) / 255f); // Calculate the average. // Formula: Math.min(1.0f, (1f - avg) / (100.0f / 35.0f) + avg); // The following formula uses less operations and hence is faster. avg = Math.min(1.0f, 0.35f + 0.65f * avg); // Convert back into RGB. return (int) (alpha * 255f) << 24 | (int) (avg * 255f) << 16 | (int) (avg * 255f) << 8 | (int) (avg * 255f); } 
+1
source share

All Articles