# Image graying and its implementation in python

Posted by aviatorisu on Fri, 28 Feb 2020 13:32:08 +0100

# 1, Grayscale

##### Definition of grayscale

In the R, G, B image model, when R=G=B (when the three color component values are the same), then the color represents a gray color, where the value of R=G=B is called gray value, in the gray image, the gray value can also be called brightness value. Gray value range 0-255

##### Grayscale method

For a color image, there are four commonly used methods of graying, which are the component method maximum value method average value method weighted average method.

###### 1. component method

This method is the most simple, that is, in the R, G, B three color components, choose any color as the gray value

###### 2. Maximum method

The method is to find out the value of each pixel's R, G, B three color components, then find the color with the largest value, and then take the maximum value as the gray value
f(x,y)=Max{R(x,y),G(x,y),B(x,y)} f(x,y)=Max\left \{ R(x,y),G(x,y),B(x,y)\right \} f(x,y)=Max{R(x,y),G(x,y),B(x,y)}

###### 3. Average method

This method is to find the component values of R, G and B, and finally set the gray value as the average value of the three component values.
f(x,y)=R(x,y)+G(x,y)+B(x,y)3 f(x,y)=\frac{R(x,y)+G(x,y)+B(x,y)}{3} f(x,y)=3R(x,y)+G(x,y)+B(x,y)​

###### 4. Weighted average method

Because the sensitivity of the human eye to each color is different, in which the human eye has the highest sensitivity to green and the lowest sensitivity to blue, we can use the weighted average method to calculate the gray value, and the formula is as follows

f(x,y)=aiR(i,j)+biG(i,j)+ciB(i,j)f(x,y)=a_iR(i,j)+b_iG(i,j)+c_iB(i,j)f(x,y)=ai​R(i,j)+bi​G(i,j)+ci​B(i,j)

##### Grayscale application scene
1. When a computer recognizes an object through an image, the most important factor is the gradient of the image. With the gradient, we can find the edge of the object and locate the object. However, gradient calculation must use gray-scale image. Color image is very easy to be affected by light and other factors, and there are many changes in the color of similar objects, so color image is difficult to provide some key information
2. After the image is grayed, the dimension of the matrix is reduced, so the operation speed will be greatly improved, and the gradient information can be preserved.

# 2, Algorithm implementation based on python

Because in the process of image graying, it is necessary to scan the image. As for the determination of the value, we can use a single function to get it, so the scanning process is independent, and the acquisition of the value is independent. We use a Values() method alone to get the gray value we need. The parameter is a list with R, G and B values

Method as a whole is very simple, just a few lines of code. Just use all kinds of formulas to calculate the gray value. All that's left is the sweep function

The following is a class for processing BMP image files. The code in the previous section can be integrated to read 8-bit pseudo color and 24 bit true color images

class BmpManager:
def __init__(self,fileName):
self.f_size=None
self.f_width=None
self.f_height=None
self.f_ofset=None
self.f_bitcount=None
self.colorTab=None
self.Img=None
def Parse(self,fileName):
f=open(fileName,'rb')
file_type=str(f.read(2),encoding='utf-8')
assert file_type=='BM',"Wrong file type"
file_size_byte = f.read(4)  # This can be used to read the size of the file. It needs to read 4 bytes
f.seek(f.tell() + 4)  # Skip four useless bytes in the middle
file_ofset_byte = f.read(4)  # Offset to read bitmap data
f.seek(f.tell() + 4)  # Skip two useless bytes
file_wide_byte = f.read(4)  # Read width bytes
file_height_byte = f.read(4)  # Read height bytes
f.seek(f.tell() + 2)  ## Skip two useless bytes in the middle
file_bitcount_byte = f.read(4)  # Get the occupation size of each pixel
#Here is how to convert the bytes read to the specified type
self.f_size,=struct.unpack('l',file_size_byte)
self.f_ofset,=struct.unpack('l',file_ofset_byte)
self.f_width,=struct.unpack('l',file_wide_byte)
self.f_height,=struct.unpack('l',file_height_byte)
self.f_bitcount,=struct.unpack('i',file_bitcount_byte)
# Determine whether there is a color table
if self.f_ofset==1078:
self.__256Image__(fileName)#Processing pseudo color image
else:
self.__24BImage(fileName) #Process true color images
def __256Image__(self,f_name):
'Then read the color table'
f=open(f_name,'rb')
self.colorTab = np.array([],dtype=int)
f.seek(54)  # Skip file and bitmap headers
for i in range(0, 256):
b = struct.unpack('B', f.read(1))[0]
g = struct.unpack('B', f.read(1))[0]
r = struct.unpack('B', f.read(1))[0]
alpha = struct.unpack('B', f.read(1))[0]
self.colorTab=np.append(self.colorTab,np.array([r,g,b,255]))
self.colorTab=self.colorTab.reshape(256,4)
'The following section is for reading BMP Bitmap data area,Store data in numpy array'
# Offset the file pointer first
f.seek(self.f_ofset)
# Because the image is an 8 bit pseudo color image, one pixel takes up one byte, that is, 8 bits
img = np.empty(shape=[self.f_height, self.f_width, 4], dtype=int)
cout = 0
for y in range(0, self.f_height):
for x in range(0, self.f_width):
cout = cout + 1
index = struct.unpack('B', f.read(1))[0]
img[self.f_height - y - 1, x] = self.colorTab[index]
while cout % 4 != 0:
f.read(1)
cout = cout + 1
self.Img=img
def __24BImage(self,f_name):
f=open(f_name,'rb')
f.seek(self.f_ofset)
img=np.empty(shape=[self.f_height,self.f_width,3],dtype=int)
cout=0
for y in range(0,self.f_height):
for x in range(0,self.f_width):
BYTES=f.read(3)
x1,x2,x3=struct.unpack('BBB',BYTES)
cout=cout+3
img[self.f_height - y - 1, x]=np.array([x3,x2,x1])
while cout%4!=0:
cout=cout+1
f.read(1)
self.Img=img
def getHeight(self):
return self.f_height
def getWidth(self):
return self.f_width
def getImage(self):
return self.Img
def getSize(self):
return self.f_size

def grayScale(self,method='AVG'):
#Next, scan the image
for y in  range(0,self.f_height):
for x in range(0,self.f_width):
value=self.Values(method,self.Img[y][x])
self.Img[y][x]=np.array([value,value,value])
def Values(self,methods,v):
if methods=='AVG':
return np.average(v)
if methods=='R':
return v[0]
if methods=='G':
return v[1]
if methods=='B':
return v[2]
if methods=='Max':
return np.max(v)
if methods=='WAvg':
return 0.3*v[0]+0.59*v[1]+0.11*v[2]


### Final operation results

##### Weighted average method
Published 2 original articles, praised 0, visited 84

Topics: Python encoding