基于DCT算法的图像模糊检测


基于DCT算法的图像模糊检测

转载: https://yinguobing.com/dct-blur-image/
github链接: https://github.com/yinguobing/image_utility
论文名称: 《Blur determination in the compressed domain using DCT information》
论文链接: https://www.researchgate.net/publication/3835246_Blur_determination_in_the_compressed_domain_using_DCT_information
利用离散余弦变换DCT来估计图像模糊度的图像质量评价算法


1.离散余弦变换DCT

  DCT是Discrete Cosine Transform的缩写,即离散余弦变换。简单的说,有限的一连串数可以使用不同频率的余弦信号来叠加表示。
OpenCV提供了DCT的实现。对于二维图像的正变换公式为:
  在这里插入图片描述
其中的C为:
  在这里插入图片描述
由于输入为二维矩阵,按照公式我们获得的输出将会是一个同等维度的二维矩阵。注意公式中的 k 与 j 分别是图像的行与列数,默认图像的原点在左上角,因此变换后的二维矩阵从左上角到右下角代表的频率逐渐增大。

例:对图像进行DCT变换
代码:

import cv2
import numpy as np

if __name__ == "__main__":
    img = cv2.imread('./test1/5.jpg')
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    img_float = np.float32(img)
    dct = cv2.dct(img_float)
    
    cv2.imshow('dct', dct)
    cv2.imwrite('result.jpg',dct)
    cv2.waitKey()

输出结果:
在这里插入图片描述
注: 通常图像中的边界和噪声是图像中的高频分量。

2.基于离散余弦变换DCT来估计图像模糊度的图像质量评价算法

代码:

"""A demonstration code of image blurness detection. The algorithm is from the 
technical paper:
Marichal, Xavier & Ma, Wei-Ying & Zhang, HongJiang. (1999). Blur determination 
in the compressed domain using DCT information. IEEE International Conference on
Image Processing. 2. 386 - 390 vol.2. 10.1109/ICIP.1999.822923. 
"""
import cv2
import numpy as np
import time

class BlurDetector(object):

    def __init__(self):
        """Initialize a DCT based blur detector"""
        self.dct_threshold = 8.0
        self.max_hist = 0.1
        self.hist_weight = np.array([8, 7, 6, 5, 4, 3, 2, 1,
                                     7, 8, 7, 6, 5, 4, 3, 2,
                                     6, 7, 8, 7, 6, 5, 4, 3,
                                     5, 6, 7, 8, 7, 6, 5, 4,
                                     4, 5, 6, 7, 8, 7, 6, 5,
                                     3, 4, 5, 6, 7, 8, 7, 6,
                                     2, 3, 4, 5, 6, 7, 8, 7,
                                     1, 2, 3, 4, 5, 6, 7, 8
                                     ]).reshape(8, 8)
        self.weight_total = 344.0

    def check_image_size(self, image, block_size=8):
        """Make sure the image size is valid.
        Args:
            image: input image as a numpy array.
            block_size: the size of the minimal DCT block.
        Returns:
            result: boolean value indicating whether the image is valid.
            image: a modified valid image.
        """
        result = True
        height, width = image.shape[:2]
        _y = height % block_size
        _x = width % block_size

        pad_x = pad_y = 0

        if _y != 0:
            pad_y = block_size - _y
            result = False
        if _x != 0:
            pad_x = block_size - _x
            result = False

        image = cv2.copyMakeBorder(
            image, 0, pad_y, 0, pad_x, cv2.BORDER_REPLICATE)

        return result, image

    def get_blurness(self, image, block_size=8):
        """Estimate the blurness of an image.
        Args:
            image: image as a numpy array of shape [height, width, channels].
            block_size: the size of the minimal DCT block size.
        Returns:
            a float value represents the blurness.
        """
        # A 2D histogram.
        hist = np.zeros((8, 8), dtype=int)

        # Only the illumination is considered in blur.
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

        # Split the image into patches and do DCT on the image patch.
        height, width = image.shape
        round_v = int(height / block_size)
        round_h = int(width / block_size)
        for v in range(round_v):
            for h in range(round_h):
                v_start = v * block_size
                v_end = v_start + block_size
                h_start = h * block_size
                h_end = h_start + block_size

                image_patch = image[v_start:v_end, h_start:h_end]
                image_patch = np.float32(image_patch)
                patch_spectrum = cv2.dct(image_patch)
                patch_none_zero = np.abs(patch_spectrum) > self.dct_threshold
                hist += patch_none_zero.astype(int)

        _blur = hist < self.max_hist * hist[0, 0]
        _blur = (np.multiply(_blur.astype(int), self.hist_weight)).sum()
        return _blur/self.weight_total


if __name__ == "__main__":
    bd = BlurDetector()
    image = cv2.imread('./test1/1.jpg')
    start = time.time()
    result, image = bd.check_image_size(image)
    if not result:
        print("Image expanded.")
    
    blur = bd.get_blurness(image)
    print('end:',time.time()-start)
    print("Blurness: {:.2f}".format(blur))

测试结果:
在这里插入图片描述


总结

  从结果看来,对于模糊检测有一定效果,结合具体场景可自行调节图像大小和图像切片大小,具体阈值根据实际应用进行测试获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值