I'm trying to restore and enhance image details on several photos. I've tried to bring out details by increasing sharpness with cv2.filter2D()
and simple kernels.
I've tried an edge detection kernel
[-1 -1 -1]
[-1 9 -1]
[-1 -1 -1]
and a sharpen kernel
[ 0 -1 0]
[-1 5 -1]
[ 0 -1 0]
but the results look grainy and unnatural. To smooth out the noise, I've tried blurring techniques such as cv2.medianBlur()
and cv2.GaussianBlur()
but the results don't come out that great. The images have hazy backgrounds or are dark which makes the features hard to distinguish. Is there a better way to bring out more details especially in the background? Open to both Python or C++
Input images
Current results
import numpy as np
import cv2
img = cv2.imread('people.jpg')
grayscale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# edge_kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
sharpen_kernel = np.array([[0,-1,0], [-1,5,-1], [0,-1,0]])
img = cv2.filter2D(grayscale, -1, sharpen_kernel)
# Smooth out image
# blur = cv2.medianBlur(img, 3)
blur = cv2.GaussianBlur(img, (3,3), 0)
cv2.imshow('img',img)
cv2.imwrite('img.png',img)
cv2.imshow('blur',blur)
cv2.waitKey(0)
Histogram equalization may work here to improve the contrast of the grayscale image by stretching out the intensity range. Here's a visualization of the input image's histogram
from matplotlib import pyplot as plt
import cv2
# Load in image as grayscale
image = cv2.imread('1.jpg', 0)
plt.hist(image.ravel(), 256, [0,256])
The pixels are clustered around the mid range intensities. To increase the contrast of the image, histogram equalization stretches out the intensity values over the whole range to obtain a wider and more uniform distribution. You can do this with the built-in function, cv2.equalizeHist()
equalize = cv2.equalizeHist(image)
plt.hist(equalize.ravel(), 256, [0,256])
The intensity ranges are now evenly distributed. Histogram equalization considers the global contrast of the image and works great when the histogram of the image is confined to a particular region. Here's the result
In some cases where there are intensity variations across a large region, CLAHE (Contrast Limited Adaptive Histogram Equalization) may be better. CLAHE is implemented in OpenCV as cv2.createCLAHE()
clahe = cv2.createCLAHE().apply(image)
plt.hist(clahe.ravel(), 256, [0,256])
This variation divides pixels into small blocks before performing adaptive histogram equalization.
Here's a visualization between the two methods
You may try applying edge-preserving gaussian filtering instead of GaussianBlur
.
For example, you can try bilateral filter or guided filter
There are OpenCV implementations, but I never tried them.
Following MATLAB code demonstrates the filters:
I = rgb2gray(im2double(imread('I.jpg')));
G = imguidedfilter(I, 'DegreeOfSmoothing', 0.005);
J = imsharpen(G, 'Amount', 2);
figure;imshow(J)
B = imbilatfilt(I);
K = imsharpen(B, 'Amount', 2);
figure;imshow(K)
Guided filter:
Bilateral Filter:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With