Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image restoration to enhance details with OpenCV

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

enter image description here

Current results enter image description here

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)
like image 937
coffeewin Avatar asked Dec 10 '22 02:12

coffeewin


2 Answers

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

enter image description here


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.

enter image description here

Here's a visualization between the two methods enter image description here

like image 138
nathancy Avatar answered Jan 01 '23 18:01

nathancy


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:
Guided filter

Bilateral Filter:
enter image description here

like image 32
Rotem Avatar answered Jan 01 '23 18:01

Rotem