Profile
This paper mainly introduces several methods of grayscale, and how to use Java to achieve grayscale. At the same time, this paper analyzes a common but inappropriate Java grayscale implementation, and proves that the grayscale of OPENCV is using "weighted grayscale" method.
24-bit color graphs and 8-bit grayscale graphs
First, let's introduce a 24-bit color image, in a 24-bit color image, each pixel is represented by three bytes, usually expressed as RGB. In general, many 24-bit color images are stored as 32-bit images, and the extra bytes per pixel are stored as an alpha value, which displays information that has special effects [1].
In the RGB model, if r=g=b, color represents a grayscale color, where the value of r=g=b is called a grayscale value, so grayscale images each pixel only need one byte to hold the grayscale value (also called intensity value, luminance value), grayscale range is 0-255[2]. This will get a grayscale image of a picture.
Several methods of grayscale
- Component method: Use one of the RGB three components as the grayscale value of the grayscale graph.
- Max value: Use the maximum or minimum value in RGB three components as the grayscale value of the grayscale graph.
- Mean: Use the average of the RGB three components as the grayscale value of the grayscale graph.
- Weighted method: Due to the different color sensitivity of the human eye, a reasonable gray image can be obtained by weighted average of the RGB three components according to a certain weight value. The general situation is as follows:
Y = 0.30R + 0.59G + 0.11B
.
[note] The weighting method actually takes a picture's luminance value as the gray value to calculate, has used the YUV model. In [3] it is found that the author used Y = 0.21 * r + 0.71 * g + 0.07 * b
to calculate the gray value (obviously the sum of three weights is not equal to 1, possibly the author's error?). )。 In fact, this difference should be related to whether gamma correction is used [1].
A method of implementing grayscale in Java
If you search for "Java implementation Grayscale", nine to Ten is a Method (code):
public void Grayimage () throws ioexception{ File File = new file (System.getproperty ("User.dir") + "/test.jpg"); BufferedImage image = Imageio.read (file); int width = image.getwidth (); int height = image.getheight (); BufferedImage grayimage = new BufferedImage (width, height, bufferedimage.type_byte_gray); for (int i= 0; i < width; i++) { for (int j = 0; j < height; J + +) { int rgb = Image.getrgb (i, j); Grayimage.setrgb (i, J, RGB); } } File NewFile = new file (System.getproperty ("User.dir") + "/method1.jpg"); Imageio.write (grayimage, "JPG", newFile); }
Test.jpg's original image is:
Grayscale graphs obtained using the above method:
It may seem like a good way to see this grayscale, but if we use OPENCV to grayscale or use PIL (Python), you will find that the effect is quite different:
img = cv2.imread (' test.jpg ', Cv2. Imread_color) Gray = Cv2.cvtcolor (img,cv2. Color_bgr2gray) cv2.imwrite (' pythonmethod.jpg ', gray)
It can be clearly seen that using OpenCV (PiL is the same) to get a grayscale map than the above Java method to get a lot better, a lot of detail can be seen. This shows that this popular method of online has always been a problem, but has been neglected.
OpenCV How to achieve grayscale
If read OPENCV related books or code, probably can know OpenCV gray use is weighted method, the reason is probably, because we do not know why OpenCV grayscale image so good, whether there are other processing details are ignored?
Verifying our conjecture is simple, just look at the changes in pixel values before and after grayscale, and you can test it as follows:
img = cv2.imread (' test.jpg ', Cv2. Imread_color) H, w = Img.shape[:2]gray = Cv2.cvtcolor (img,cv2. Color_bgr2gray) for J in Range (W): For I in range (h):p rint str (i) + ":" + str (j) + "+ str (gray[i][j]) print img[h-1][w-1 ][0:3]
It's hard to tell how many pixels are printed below, but we can find out if we focus on the last pixel: the RGB value of the last pixel of the original is 44,67,89, and the value after grayscale is 71. Exactly the gray value calculated by the weighted method. If you examine the pixel values of a previously grayscale image, you will find that not only the pixel values do not conform to this formula, they are even far apart.
In this way, we suspect that OpenCV (also including PIL) is a grayscale implemented using the weighted method.
Java implementation of weighted method grayscale
How can we use Java to achieve grayscale if the popular method is not available online? In fact [3] has successfully implemented (a variety of methods of) grayscale (foreign friends engage in technology is still very strong), here only to extract the necessary code:
private static int Colortorgb (int alpha, int red, int green, int blue) {int newpixel = 0;newpixel + = Alpha;newpixel = Newp Ixel << 8;newpixel + = Red;newpixel = Newpixel << 8;newpixel + green;newpixel = newpixel << 8;newpixel + = Blue;return Newpixel;} public static void Main (string[] args) throws IOException {BufferedImage bufferedimage = imageio.read (New File (system.get Property ("User.dir" + "/test.jpg")); BufferedImage grayimage = new BufferedImage (Bufferedimage.getwidth (), Bufferedimage.getheight (), Bufferedimage.gettype ()); for (int i = 0; i < bufferedimage.getwidth (); i++) {for (int j = 0; J < bufferedimage.gethe Ight (); J + +) {Final int color = Bufferedimage.getrgb (i, j); final int r = (color >>) & 0xff;final int g = (color >& Gt 8) & 0xff;final int b = color & 0xff;int Gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);; SYSTEM.OUT.PRINTLN (i + ":" + j + "+ gray); int newpixel = Colortorgb (255, gray, Gray, gray); Grayimage.setrgb (I, J, new PIxel);}} File NewFile = new file (System.getproperty ("User.dir") + "/ok.jpg"), Imageio.write (grayimage, "JPG", newFile);}
The above code will print out the grayscale pixel values, and if you compare it to the Python code above, you will find that the pixel values correspond completely. The color graph in the Colortorgb method is handled exactly 4 bytes, one of which is the Alpha parameter (described above), which is the grayscale image of this code:
For other methods, the same can be done in turn.
Summarize
The cause of this article is to use Java to achieve a few grayscale operations, and use OPENCV to verify the conversion of the right and wrong, but in the actual test found some problems (after the conversion of the picture is different, and how to generate gray-scale image after conversion, etc.), and this has been a certain reflection and validation.
It is important to note that some articles on the web are more or less not doing further thinking (even many are copied, especially in the domestic article), and for these practical problems, hands-on implementation and validation is a very significant method. I hope this article is helpful to everyone.
Reference
- [1] "Multimedia Technology course" Ze-nian li,mark s.drew, Machinery Industry press.
- [2] Baidu Encyclopedia: Grayscale Values
- [3] Java color image to grayscale conversion algorithm (s)
Analysis of the implementation process of grayscale of Java image