基于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))
测试结果:
总结
从结果看来,对于模糊检测有一定效果,结合具体场景可自行调节图像大小和图像切片大小,具体阈值根据实际应用进行测试获取。