如何在OpenCV中锐化图像?


Answers:


160

维基百科有关不清晰遮罩的文章提出了一种通用过程:

使用高斯平滑滤波器,并从原始图像中减去平滑版本(以加权方式,使恒定区域的值保持恒定)。

要获得锐化形式frameimage:(两者cv::Mat

cv::GaussianBlur(frame, image, cv::Size(0, 0), 3);
cv::addWeighted(frame, 1.5, image, -0.5, 0, image);

您需要自己调整一些参数。

还有Laplacian锐化功能,您在Google上应该会发现一些东西。


1
有没有办法复制Photoshop的“锐化蒙版”结果?
罗伊2014年

@Drazick您是否在问,因为它无法复制?上面已经给出了到维基百科的链接。digital_unsharp_masking要具体
tilaprimera

@tilaprimera,我问是因为Photoshop的USM与“经典” USM不同。
罗伊2014年

50

您可以尝试使用简单的内核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)

在图像处理中,核,卷积矩阵或掩码是小矩阵。它用于模糊,锐化,压纹,边缘检测等。这是通过在内核和映像之间进行卷积来实现的。


14

您可以在OpenCV Documentation上找到有关使用“锐化蒙版”算法锐化图像的示例代码。

改变的值sigmathresholdamount会得出不同的结果。

// 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);

这很漂亮!
罗斯福

12

您可以使用不清晰的蒙版来锐化图像。您可以在此处找到有关锐化遮罩的更多信息。这是使用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)

这似乎是一个非常方便的版本。您能否添加一些有关参数的更多信息。可以在opencv中查询内核大小和sigma,但是数量和阈值呢?谢谢!
选择

2
@choise amount只是锐化程度。例如,amount与默认值1.0相比,值为2.0可以提供更清晰的图像。threshold是低对比度蒙版的阈值。换句话说,输入图像和模糊图像之间的差异小于的像素threshold将保持不变。
Soroush

10

任何图像都是各种频率信号的集合。较高的频率控制边缘,较低的频率控制图像内容。当从一个像素值到另一个像素值(如相邻单元中的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);

5

为了使本主题更加清晰,实际上应该提出几点:

  1. 锐化图像是一个不适的问题。换句话说,模糊是有损的操作,通常不可能从中返回。

  2. 要锐化单个图像,您需要以某种方式添加对想要的图像种类以及图像变得模糊的限制(假设)。这是自然图像统计的领域。进行锐化的方法将这些统计信息显式或隐式地保存在其算法中(深度学习是最隐式编码的算法)。布莱恩·伯恩斯(Brian Burns)回答的一般化方法是对DOG或拉普拉斯金字塔分解的某些级别进行加权的常见方法是,假设高斯模糊会破坏图像,并且加权的方式与关于首先是图片

  3. 其他信息来源可能使问题更加突出。此类信息的常见来源是运动对象的视频或多视图设置。在这种情况下锐化通常被称为超分辨率(这是一个很不好的名字,但它一直被学术界所困扰)。很长一段时间以来,OpenCV中就有超分辨率方法了。。。尽管它们通常不能很好地解决实际问题,但最后我还是检查了它们。我希望深度学习在这里也能产生出色的结果。也许有人会发表评论,说明那里值得做什么。


3

要锐化图像,我们可以使用滤镜(与之前的许多答案一样)

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)

“最会”附近似乎缺少某些东西。
Peter Mortensen

是的,彼得,谢谢!
kaustubhd9

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.