Article directory
-
- digital image enhancement
-
- Brightness and Contrast Conversion
- geometric transformation
-
- Image cropping
- size transformation
- image rotation
- Noise processing
-
- add noise
- Dealing with noise
Digital image enhancement
Brightness and contrast conversion
Image transformation can be divided into the following two types:
- Point operator: Based on pixel transformation, in this type of image transformation, the corresponding output pixel value is calculated only based on the input pixel value.
- Neighborhood operator: transform based on image area
Two commonly used point operators use constants to multiply or add point pixel values, which can be expressed as:
g
(
i
,
j
)
=
α
?
f
(
i
,
j
)
+
β
g(i, j) = \alpha * f(i, j) + \beta
g(i,j)=α?f(i,j) + β
Among them, the position of the midpoint of the image is
(
i
,
j
)
(i,j)
(i,j), the α
value represents gain, and the β
value represents bias. Transforming the brightness and contrast of the image is a point operator. These two parameters can be used to control contrast and brightness respectively. You can adjust the contrast or brightness of the image by adjusting the values of these two parameters. That is, adding a bias constant to each pixel in the original image can make the image brighter. Similarly, multiplying the pixels in the original image by a gain coefficient can adjust the contrast of the image.
Note
The pixel value range of image pixels is [0, 255]. Be sure not to let it overflow. You can use
np.clip
to truncate it.
Example image:
import cv2 import numpy as np #Method 1: Implemented based on addWeighted() function def convert_img1(img, alpha, beta): blank = np.zeros(img.shape, img.dtype) return cv2.addWeighted(img, alpha, blank, 0, beta) #Method 2: Manual implementation through for loop def convert_img2(img, alpha, beta): rows, cols, chs = img.shape new_img = np.zeros(img.shape, img.dtype) for i in range(rows): for j in range(cols): for k in range(chs): new_img[i, j, k] = np.clip(alpha * img[i, j, k] + beta, 0, 255) return new_img img = cv2.imread('woman.png') cv2.imwrite('convert_img1.jpg', convert_img1(img, 2.2, 50)) cv2.imwrite('convert_img2.jpg', convert_img2(img, 2.2, 50))
In the above code, the parameter list of the addWeighted()
function in the function convert_img1()
is: [img1,alpha,img2,beta,gamma]
means performing the following calculations on the two images:
n
e
w
_
i
m
g
=
a
l
p
h
a
?
i
m
g
1
+
b
e
t
a
?
i
m
g
2
+
g
a
m
m
a
new\_img = alpha * img1 + beta * img2 + gamma
new_img=alpha?img1 + beta?img2 + gamma
The process implemented by the function convert_img2()
is to modify the pixel value of the original image through a for loop, which is the same as the process of the function convert_img1()
, except that The convert_img1()
function calls the addWeighted()
function. The pixel values of the image in the img2 parameter are all 0.
Geometric transformation
The geometric transformation of an image refers to an operation that transforms the positions of image pixels in a picture. It maps the coordinate positions in an image to new coordinate positions, that is, changes the spatial position of the pixels, and also changes the spatial position of the pixels. Estimate the pixel value at the new spatial location.
Image cropping
Cut out part of the matrix from the matrix of image data as new image data, thereby realizing cropping of the image.
import cv2 import numpy as np # Image cropping img = cv2.imread('woman.png') print(img.shape) new_img = img[20:300, 20:400] cv2.imwrite('crop_img.jpg', new_img)
The process implemented by the above code is to crop the original image from the (20, 20)
pixel position to the (300, 400)
position. The cropped shape is rectangle.
Size transformation
Modifying the size of the image means modifying the size of the image. OpenCV’s resize()
function can achieve this function. When resizing an image, some pixels will inevitably be lost or added. It is recommended to use area interpolation cv2.INTER_AREA
when zooming to avoid ripples; it is recommended to use cubic spline interpolation cv2.INTER_CUBIC
when zooming in, but its calculation speed is relatively slow . Linear interpolation cv2.INTER_LINEAR
can also be used. By default, the interpolation method used by all operations that change the image size is linear interpolation.
# Image scaling small_resize_img = cv2.resize(img, (200, 200), interpolation=cv2.INTER_AREA) cv2.imwrite('small_resize.jpg', small_resize_img) small_resize_img2 = cv2.resize(img, None, fx=0.5, fy=0.6, interpolation=cv2.INTER_AREA) # The width of the image corresponds to the number of columns, and the height corresponds to the number of rows cv2.imwrite('small_resize2.jpg', small_resize_img2)
Image rotation
Rotation is implemented through the getRotationMatrix2D()
function.
# Image rotation img = cv2.imread('woman.png') rows, cols, _ = img.shape rotated_mat = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 1) # The first parameter is the rotation center, the second parameter is the rotation angle, and the third parameter is the scale factor after rotation rotated_img = cv2.warpAffine(img, rotated_mat, dsize=(cols, rows)) cv2.imwrite('rot45.jpg', rotated_img)
Noise processing
Adding an appropriate amount of noise to the training data can make the trained model more robust and help improve the performance of the model. Eliminating noise can increase image quality.
Add noise
There are two common ways to add noise to images:
- salt and pepper noise
- Gaussian noise
import cv2 import random import numpy as np # Add salt and pepper noise def salt_and_pepper_noise(img, percentage): rows, cols, chs = img.shape num = int(percentage * rows * cols) for i in range(num): x = random.randint(0, rows-1) y = random.randint(0, cols-1) z = random.randint(0, chs-1) if random.randint(0, 1) == 0: img[x, y, z] = 0 # black noise else: img[x, y, z] = 255 # white noise return img # Add Gaussian random noise def gaussian_noise(img, mu, sigma, delta): rows, cols, chs = img.shape for i in range(rows): for j in range(cols): for k in range(chs): # Generate random numbers from Gaussian distribution, which must be rounded when added to the original data. value = int(img[i, j, k] + delta*random.gauss(mu=mu, sigma=sigma)) value = np.clip(a_max=255, a_min=0, a=value) img[i, j, k] = value return img img = cv2.imread('woman.png') cv2.imwrite('saltPepper.jpg', salt_and_pepper_noise(img, 0.3)) cv2.imwrite('gaussain.jpg', gaussian_noise(img, 0, 1, 100))
You can see the above methods of adding salt and pepper noise and Gaussian noise to images. For Gaussian noise, the mu
parameter in the function gaussian_noise()
represents the average of the random number Gaussian distribution, and sigma
represents the random number Gaussian. The standard deviation of the distribution, while the parameter delta
represents a coefficient indicating the intensity of added Gaussian noise.
Handling noise
OpenCV provides several filtering methods, such as median filtering, bilateral filtering, Gaussian blur, two-dimensional convolution, etc.
import cv2 import random import numpy as np # Blur and filter salt_and_pepper_img = cv2.imread('saltPepper.jpg') gaussain_img = cv2.imread('gaussain.jpg') # 2D convolution kernel = np.ones((5, 5), np.float32) / 25 # Each value is 0.04 conv_2d_img = cv2.filter2D(salt_and_pepper_img, -1, kernel) cv2.imwrite('filter_2d_img.jpg', conv_2d_img) # Median filter median_blur_img = cv2.medianBlur(salt_and_pepper_img, 5) # Parameter 5 represents the area pixel value of size 5x5 for calculation cv2.imwrite('median_blur_img.jpg', median_blur_img) # Gaussian blur gaussian_blur_img = cv2.GaussianBlur(gaussian_img, (5, 5), 0) cv2.imwrite('gaussian_blur_img.jpg', gaussian_blur_img) # Bilateral filtering bilateral_filter_img = cv2.bilateralFilter(gaussain_img, 9, 75, 75) # 9 represents the neighborhood diameter, and the two parameters 75 represent the value range and spatial standard deviation respectively. cv2.imwrite('bilateral_filter_img.jpg', bilateral_filter_img)
It can be seen that the median filter has the best effect.