如何做一个图片筛选器——关于图像模糊程度检测

更新点轻松的吧,关于怎么处理图像

拉普拉斯算子

拉普拉斯算子是一种常用的边缘检测算子,它可以用于检测图像中的边缘。在图像处理中,边缘通常表示了图像中物体之间的边界或者重要的特征。

算子的原理是基于图像中的边缘通常是像素值的变化较大的区域。拉普拉斯算子通过计算图像的二阶导数来寻找这些变化较大的区域。在图像中,一个像素的二阶导数可以用来衡量该像素附近的像素值变化的快慢程度。在边缘附近,像素值的变化会显著,因此二阶导数会有较大的值。

具体地,拉普拉斯算子可以通过卷积操作来实现。在一维情况下,拉普拉斯算子可以表示为[-1, 2, -1]的卷积核,即当前像素与相邻像素的值的加权和减去当前像素的两倍。在二维情况下,可以将一维的卷积核分别应用于图像的水平和垂直方向,然后将两个方向的结果相加,即可得到图像的拉普拉斯算子响应。

在实际应用中,一般会取拉普拉斯算子的绝对值作为边缘强度的度量,因为边缘可能是明亮到暗或暗到明的过渡。最后,通过计算边缘强度的平均值或其他统计量来评估图像的模糊程度。

用人话解释一遍就是:

想象一下图像是由许多小方块组成的网格,每个方块代表图像中的一个像素点。在一张黑白图像中,每个像素点可以是黑色(值为0)或白色(值为1)。

我们想知道图像中哪些地方的色块变化最大,因为这些地方往往是图像中的边缘。边缘通常是物体之间或物体与背景之间的界限,它们呈现出像素值的快速变化。

拉普拉斯算子是一种边缘检测算法,它通过对图像进行二阶导数操作来寻找像素值变化率最大的地方。这种操作可以捕获图像中边缘的位置,因为边缘是图像中像素值变化快的区域。

虽然在实际实现时,可能会对图像进行降采样或者使用其他技术来加速计算,但拉普拉斯算子本身不会减少计算像素点的数量。

边缘的数量和强度并不总是直接与图像的清晰程度成正比。有时候,图像中的噪音或其他因素也会导致边缘的出现,而这些边缘并不一定代表图像的清晰度。因此,评估图像的清晰度需要综合考虑边缘的数量、强度以及其他因素。

上实战吧

import cv2
import numpy as np

def calculate_blur_score(image_path):
    # 读取图像
    image = cv2.imread(image_path)

    # 将图像转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 使用拉普拉斯算子计算图像的边缘
    laplacian = cv2.Laplacian(gray, cv2.CV_64F)
    
    # 取绝对值,并转换为8位图像
    laplacian = np.uint8(np.absolute(laplacian))

    # 计算边缘强度
    edge_strength = np.mean(laplacian)

    return edge_strength

# 输入图像路径
image_path = "your_image.jpg"

# 计算图像模糊程度
blur_score = calculate_blur_score(image_path)

print("图像模糊程度:", blur_score)

在这个例子中,拉普拉斯算子的运算被全部封装在了 cv2.Laplacian这个函数中,实际上,如果你用的方法是c++可以更加清晰地看到卷积的过程。

计算出来的laplacian是一个NumPy数组,其中包含了图像中每个像素的拉普拉斯变换后的值,首先,可以对拉普拉斯变换后的图像应用阈值化操作。阈值化可以将图像中像素值大于某个阈值的部分设置为白色(255),小于等于阈值的部分设置为黑色(0)。这样可以将图像中的边缘区域与其他区域分离开来。接着,可以使用边缘检测算法(如Canny边缘检测)来进一步细化边缘。这样可以检测出图像中更细微的边缘特征,并且对于噪声也有一定的抑制效果。

不用理解那么多,在实际运用的时候,我们可以粗略的将其理解为一个存储了可以用于计算边缘数据的数组

比如这两张图片
在这里插入图片描述
在这里插入图片描述
第一张计算出来的值为16.912433624267578
而第二张仅为1.230936050415039,因此可以根据我们检测对象的不同设定阈值来判定图片是否模糊

Saber算子

值得注意的一点是,Sobel算子主要用于边缘检测,而不是模糊程度的评估。Sobel算子更适合于检测图像中的细微边缘特征,而不是评估图像的整体模糊程度。相比之下,Laplacian算子更适合于评估图像的模糊程度,因为它可以直接检测图像中像素值的变化率,包括模糊导致的像素值变化减缓的情况。

但是Saber算子有个比Laplacian更优的一点是其对噪声有一定的抑制效果,这点在特定情况下对检测很有帮助,因为Laplacian再遇到强噪点的图片时可能会检测不准确。(虽然实际测试saber算子受图像噪声的干扰程度依然很大,只是比Laplacian不敏感一点点)

import cv2
import numpy as np

def calculate_blur_score(image_path):
    # 读取图像
    image = cv2.imread(image_path)

    # 将图像转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 使用Sobel算子计算图像的梯度
    sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=5)
    sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=5)
    gradient = np.sqrt(sobelx**2 + sobely**2)

    # 计算梯度的平均值作为模糊程度
    blur_score = np.mean(gradient)

    return blur_score

# 输入图像路径
image_path = "your_image.jpg"

# 计算图像模糊程度
blur_score = calculate_blur_score(image_path)

print("图像模糊程度:", blur_score)

同样上述两张图
清晰图计算出来的值是882.0671758109124,模糊图是412.00405348349574
为了试验的严谨性,我们加入了噪点图
在这里插入图片描述
本质上还是模糊图,在Laplacian的计算中数值来到了96.45854091644287,比清晰图还要清晰!(其实是因为边缘太多了),而saber计算出来的结果略号但还是异常
,结果是1065.1257280712512,也比清晰图大了百分之25.

优化模糊检测

对于不同的图像,大小、噪点程度都不尽相同,有的图片因为很大,所以其边缘就看起来变化率很快,有的图片因为噪点很多,边缘变化率也很大,因此在实际运用中,我们需要先对图片进行归一化处理并降噪才能得到一个相对准确的结论。

import cv2
import numpy as np

def preprocess_image(image_path, target_size=(300, 300), blur_kernel_size=5):
    # 读取图像
    image = cv2.imread(image_path)

    # 将图像缩放到目标大小
    resized_image = cv2.resize(image, target_size)

    # 将图像转换为灰度图
    gray = cv2.cvtColor(resized_image, cv2.COLOR_BGR2GRAY)

    # 使用高斯模糊去除噪点
    blurred = cv2.GaussianBlur(gray, (blur_kernel_size, blur_kernel_size), 0)

    return blurred

def calculate_blur_score(image):
    # 使用拉普拉斯算子计算图像的边缘
    laplacian = cv2.Laplacian(image, cv2.CV_64F)
    
    # 取绝对值,并转换为8位图像
    laplacian = np.uint8(np.absolute(laplacian))

    # 计算边缘强度
    edge_strength = np.mean(laplacian)

    return edge_strength

# 输入图像路径
image_path = "your_image.jpg"

# 预处理图像
processed_image = preprocess_image(image_path)

# 计算图像模糊程度
blur_score = calculate_blur_score(processed_image)

print("图像模糊程度:", blur_score)

对于上面三张图,这个代码的兼容性显然更好了
清晰图的检测结果是9.093655555555555,模糊图是4.4706777777777775,噪点图是6.346288888888889

  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值