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:

  1. Firstly, I is our input image. The first step is to get the output image L after gaussian blur of the input image I
  2. 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.
  3. 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 😂