我如何使用OpenCV来增强图像的清晰度?
有许多平滑或模糊的方法,但似乎没有任何增强清晰度的方法。
一般的步骤可以在维基百科关于反遮罩处理中找到:
使用高斯平滑滤波器,并以加权方式从原始图像中减去平滑版本(使常量区域的值保持不变)。
要将frame
的锐化版本转换为image
: (两者均为cv::Mat
类型)
cv::GaussianBlur(frame, image, cv::Size(0, 0), 3);
cv::addWeighted(frame, 1.5, image, -0.5, 0, image);
那里的参数需要您自行调整。
还有拉普拉斯锐化,在谷歌上搜索应该能找到相关内容。
你可以尝试一个简单的内核和filter2D函数,例如在Python中:
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
im = cv2.filter2D(im, -1, kernel)
Wikipedia提供了一个良好的内核概述,其中包含一些更多示例 - https://en.wikipedia.org/wiki/Kernel_(image_processing)
在图像处理中,内核(也称卷积矩阵或掩模)是一个小矩阵。它用于模糊、锐化、浮雕、边缘检测等操作。这是通过对内核和图像进行卷积实现的。
您可以使用锐化掩蔽(unsharp mask)来锐化图像。您可以在这里找到有关锐化掩蔽的更多信息。以下是使用OpenCV的Python实现代码:
import cv2 as cv
import numpy as np
def unsharp_mask(image, kernel_size=(5, 5), sigma=1.0, amount=1.0, threshold=0):
"""Return a sharpened version of the image, using an unsharp mask."""
blurred = cv.GaussianBlur(image, kernel_size, sigma)
sharpened = float(amount + 1) * image - float(amount) * blurred
sharpened = np.maximum(sharpened, np.zeros(sharpened.shape))
sharpened = np.minimum(sharpened, 255 * np.ones(sharpened.shape))
sharpened = sharpened.round().astype(np.uint8)
if threshold > 0:
low_contrast_mask = np.absolute(image - blurred) < threshold
np.copyto(sharpened, image, where=low_contrast_mask)
return sharpened
def example():
image = cv.imread('my-image.jpg')
sharpened_image = unsharp_mask(image)
cv.imwrite('my-sharpened-image.jpg', sharpened_image)
amount
只是锐化的程度。例如,2.0 的 amount
值相对于默认值 1.0 给出了更清晰的图像。threshold
是低对比度掩膜的阈值。换句话说,输入和模糊图像之间差异小于 threshold
的像素将保持不变。 - Soroush任何图像都是由各种频率的信号集合组成的。高频率控制边缘,低频率控制图像内容。当相邻单元格中的像素值发生突然变化(如0和255)时,就会形成边缘。显然这是一个急剧的变化,因此产生了边缘和高频率。为了锐化图像,这些转换可以进一步增强。
一种方法是将自制的滤波器核与图像卷积。
import cv2
import numpy as np
image = cv2.imread('images/input.jpg')
kernel = np.array([[-1,-1,-1],
[-1, 9,-1],
[-1,-1,-1]])
sharpened = cv2.filter2D(image, -1, kernel) # applying the sharpening kernel to the input image & displaying it.
cv2.imshow('Image Sharpening', sharpened)
cv2.waitKey(0)
cv2.destroyAllWindows()
另一种从图像的明亮版本中减去模糊版本的方法有助于锐化图像。但是应该小心使用,因为我们只是增加像素值。想象一下灰度像素值为190,如果乘以2的权重,就会变成380,但由于最大允许的像素范围而被截断为255。这是信息损失,会导致图像变得发白。
addWeighted(frame, 1.5, image, -0.5, 0, image);
sigma
,threshold
和amount
的值将产生不同的结果。// sharpen image using "unsharp mask" algorithm
Mat blurred; double sigma = 1, threshold = 5, amount = 1;
GaussianBlur(img, blurred, Size(), sigma, sigma);
Mat lowContrastMask = abs(img - blurred) < threshold;
Mat sharpened = img*(1+amount) + blurred*(-amount);
img.copyTo(sharpened, lowContrastMask);
为了更好地理解本主题,需要明确以下几点:
您也可以尝试使用这个筛选器
sharpen_filter = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
sharped_img = cv2.filter2D(image, -1, sharpen_filter)
kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32)
kernel /= denominator * kernel
当分母为1时,它将达到最大值,并随着增加而减小(2.3..)
最常用的是分母为3时。
以下是实现方法。
kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32)
kernel = 1/3 * kernel
dst = cv2.filter2D(image, -1, kernel)
frame
是 float32 类型,而不是 int8。否则将输出一个具有混乱舍入的图像,这在视觉上不会引起注意,但在每个通道的直方图上会清晰可见。 - apatsekin