Recently, I learned computer vision in order to find something else to do.
This article introduces two methods of sharpening images using Python + OpenCV:
- Unsharp Masking (Unsharp Masking)
- Laplacian Sharpening
1. Unsharp Masking
USM is a sharpening algorithm that enhances visual effects primarily by increasing the amount of shading in the edges of an image.
1.1 Simple Version
The simple method is as follows:
- Firstly, I is our input image. The first step is to get the output image L after gaussian blur of the input image I
- Then subtract the original image I from the fuzzy image L to get the second image H. Gaussian blur is low-pass filtering, so H obtained after subtraction is an image containing high-pass content.
- Finally, by superposing the original picture I with the high frequency part H, we can get the final result O after sharpening
For example, take the classic Ufly meme:
Enter the image I.jpg
Gaussian blur:
Sigma = 3 kernel_size = (0,0) L = cv2.GaussianBlur(I, kernel_size, sigma)Copy the code
Kernel_size =(0,0) because cv2.GaussianBlur can use sigma to calculate the core size when both ksizes are 0.
And just to make it more obvious, I’m going to set sigma to 3 here
Blurred image L.jpg
Subtract: H = cv2.subtract(I, L)
Enhanced high frequency part h.Jpg
Finally:
A = 1.5 O = cv2. AddWeighted (I, 1, H, a, 0)Copy the code
The output is O.jpg
The parameter A is adjustable and 1.5 is only an experimental value.
Well, you can clearly see the words “eat shit you” with clearly enhanced edges… In addition, ufly’s facial expression has become a little bit ferocious…
The complete code is as follows
def shapen_USM(I):
sigma = 3
kernel_size = (0.0)
L = cv2.GaussianBlur(I, kernel_size, sigma)
L = L.astype(numpy.int32)
I = I.astype(numpy.int32)
H = I - L
a = 1.5
O = I + a*H
O[O > 255] = 255
O[O < 0] = 0
O = O.astype(numpy.uint8)
return O
Copy the code
We can also use cv2.addWeighted or cv2.subtract without casting, but we can make it clearer.
1.2 Improved Version
There is also a more improved method. Instead of directly superimposing high-pass part H and original picture I, this method introduces high-contrast image C of original picture I. The principle is shown in the following figure.
Take this man for example:
Enter the image I.jpg
The Unsharp Mask was obtained using the same method
Unsharp Mask: H.jpg
Then use CLAHE algorithm to get the high contrast version (here I have converted the original image into LAB mode and only made contrast enhancement for L channel to avoid color change)
Last stack:
From left to right are the sharpened images generated by the original Unsharp Mask, the original input image and the sharpened images generated by the improved version.
You can see that the improved sharpening filter looks much more natural when applying the same Gaussian blur.
Of course, in fact, many parameters need to be adjusted, including Sigma in the front and various threshold in the back. I also used a relatively large parameter to make the comparison better.
Talk is cheap:
# Contrast Enhancement
def CLAHE(I):
lab = cv2.cvtColor(I, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8.8))
l = clahe.apply(l)
O = cv2.merge([l, a, b])
O = cv2.cvtColor(O, cv2.COLOR_LAB2BGR)
return O
def shapen_USM_C(I):
row, col, dem = I.shape
sigma = 3
kernel_size = (0.0)
C = CLAHE(I)
L = cv2.GaussianBlur(I, kernel_size, sigma)
L = L.astype(numpy.int32)
I = I.astype(numpy.int32)
H = I - L
H[H > 255] = 255
H[H < 0] = 0
lab_H = cv2.cvtColor(H.astype(numpy.uint8), cv2.COLOR_BGR2LAB)
l_H = cv2.split(lab_H)[0]
threshold = 1
O = I.copy()
for i in range(row):
for j in range(col):
for k in range(dem):
percent = l_H[i, j] / 100
diff = C[i, j, k] - I[i, j, k]
delta = percent * diff
if abs(delta) >= threshold:
O[i, j, k] += delta
O[O > 255] = 255
O[O < 0] = 0
O = O.astype(numpy.uint8)
return O
Copy the code
2. Laplacian Sharpening
Laplacian sharpening image is based on the degree of mutation from the surrounding pixels of an image pixel to this pixel, that is to say, it is based on the degree of change in the image pixel.
This method should be more classical, simply speaking, is to use the Laplace operator to convolve the original graph, obtain a processed image and then superimpose the original graph.
A most basic matrix template:
In fact, this method is quite simple to implement using OpenCV:
def shapen_Laplacian(in_img):
I = in_img.copy()
kernel = numpy.array([[0.- 1.0], [- 1.4.- 1], [0.- 1.0]])
L = cv2.filter2D(I, - 1, kernel)
a = 0.5
O = cv2.addWeighted(I, 1, L, a, 0)
O[O > 255] = 255
O[O < 0] = 0
return O
Copy the code
L = cv2.laplacian (I,-1).
Above are the original picture (I), the processed image (L) and the final superposition result (O) respectively.
Don’t bother.
summary
Or ins and beauty picture xiu xiu with convenient 😂