使用OpenCV进行图像恢复以增强细节

4

我正在尝试恢复和增强几张照片上的图像细节。我试过使用 cv2.filter2D() 和一些简单核增加锐度以展现更多细节。

我还试过使用边缘检测核。

[-1 -1 -1]
[-1  9 -1]
[-1 -1 -1]

以及锐化卷积核

[ 0 -1  0]
[-1  5 -1]
[ 0 -1  0]

但是结果看起来过于粗糙和不自然。为了消除噪点,我尝试了模糊技术,例如cv2.medianBlur()cv2.GaussianBlur(),但是结果并不理想。图片有朦胧的背景或者很暗,这使得特征很难辨认。是否有更好的方法来突出更多的细节,特别是在背景中?欢迎使用Python或C++。
输入图片: enter image description here 目前的结果: 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)

你可以使用pyTorch获得更好的结果:https://github.com/pytorch/examples/tree/master/super_resolution - Stephen Meschke
4个回答

6

直方图均衡化 可以通过拉伸灰度图像的强度范围来改善其对比度。以下是输入图像直方图的可视化展示:

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])

像素集中在中间强度范围内。为了增加图像对比度,直方图均衡化将强度值沿整个范围拉伸以获得更广泛和更均匀的分布。您可以使用内置函数 cv2.equalizeHist() 来执行此操作。

equalize = cv2.equalizeHist(image)
plt.hist(equalize.ravel(), 256, [0,256])

强度范围现在均匀分布。 直方图均衡化考虑图像的全局对比度,当图像的直方图限制在特定区域内时,效果很好。 这是结果。 enter image description here 在一些情况下,如果存在跨越大区域的强度变化,则CLAHE(受限自适应直方图均衡化)可能更好。 在OpenCV中,CLAHE实现为 cv2.createCLAHE()
clahe = cv2.createCLAHE().apply(image)
plt.hist(clahe.ravel(), 256, [0,256])

这个变化将像素分成小块,然后执行自适应直方图均衡化。
下面是两种方法的可视化对比:
图片链接1:enter image description here 图片链接2:enter image description here

CLAHE需要一个更大的窗口来避免过多的暗和亮晕影。 - fmw42

3

您可以尝试应用保边高斯滤波代替 GaussianBlur

例如,您可以尝试 双边滤波器引导滤波器

有OpenCV实现,但我从未尝试过。

以下MATLAB代码演示了这些滤波器:

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

双边滤波器:
enter image description here


3

仅供比较,我有一个ImageMagick脚本,可以进行空间自适应对比度增强(称为space)。请参见http://www.fmwconcepts.com/imagemagick

输入:

enter image description here

space -c 2 -w 20 img.jpg result.png


enter image description here

更详细,但有点粗糙。

这是我变化后的结果,space2,可能会更令您满意。

space2 -w 5 -m 10 img.jpg result_space2_w5_m10.jpg


enter image description here

解释:

SPACE2是一种自适应技术,用于增强图像的亮度和对比度。SPACE是SPacially Adaptive Contrast Enhancement的缩写。

自适应公式 R = M + G*(I-M)。这里的 R 是结果图像。I 是输入图像。M 是均值图像,是输入图像的低通滤波版本。它通过将输入图像块调整为输入大小的某个分数来生成。调整量从窗口大小计算得出。然后将该图像重新扩展到其原始大小。调整大小技术是应用大块大小移动窗口平均的快速方法。术语 (I-M) 是输入图像的高通滤波版本。G 是增益图像,其中包括 S,输入图像的标准偏差,由与创建均值图像 M 使用的相同调整大小技术生成。G 还包括所需的标准偏差(dstd)和最大增益因子。增益图像 G 用于设置输出中的细节(锐度)以及限制失控增益。最大增益通常在 1-10 的数量级上,缺省值为 2.5。块窗口大小通常是图像大小的 5-20% ,名义上为 8%。有时,当尝试从模糊的图片中提取信息时,可能希望将最大增益值推高至默认值以上。该算法具有控制亮度、对比度和饱和度的选项。亮度和对比度具有自动计算的与图像相关的默认值。它们通过 S 型非线性函数应用。饱和度是 LAB 颜色空间中的线性调整,默认值为不变。

看起来这是目前最擅长去除图像顶部雾霾的方法。也许在您的回答中包括脚本描述会更好。此外,您能否做些什么来恢复原始图像中某些物体的深度和暗度? - Junuxx
1
请查看我的附加答案,使用我的变量脚本space2。 - fmw42

2
你可以将过滤器变得更弱,例如:

您可以将过滤器变得更弱,例如:


sharpen_kernel = np.array([[0,-.5,0], [-.5,3,-.5], [0,-.5,0]])

Or maybe try unsharp masking

gaussian_3 = cv2.GaussianBlur(grayscale, (9,9), 10.0)
img = cv2.addWeighted(img, 1.5, gaussian_3, -0.5, 0, img)

1
你的“较弱”滤镜会产生非常暗的图像,因为权重没有加起来等于1。把“-1”改成“-0.5”就会平衡了。 - Junuxx
你也改变了中心值。权重仍然不等于1。考虑到一个完全没有作用的滤波器看起来像[[0,0,0],[0,1,0],[0,0,0]]。 - Junuxx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接