利用小波分解进行模糊检测pywt.dwt2
文章目录
- 1. 什么是Dirac-Structure 和 Astep-Structure, Gstep-Structure和Roof-Structure
- ✅ 各边缘结构的定义与特点:
- ✅ 边缘结构与模糊检测的关系:
- ✅ 小波变换中的作用:
- ✅ 总结一句话:
- 2. Blur Detection for Digital Images Using Wavelet Transform
- 一、论文主要思想
- 二、算法流程
- 三、Python代码实现
- 四、代码说明
- 五、使用建议
1. 什么是Dirac-Structure 和 Astep-Structure, Gstep-Structure和Roof-Structure
在图像处理和计算机视觉领域,边缘结构(edge structure)是描述图像中像素值变化模式的重要概念。论文中提到的四种边缘结构——Dirac-Structure、Astep-Structure、Gstep-Structure 和 Roof-Structure——是根据边缘在空间中的形态和灰度变化特性分类的。它们在小波变换下的响应不同,因此可用于图像清晰度或模糊检测。
✅ 各边缘结构的定义与特点:
边缘类型 | 描述 | 模糊后的变化 |
---|---|---|
Dirac-Structure | 极窄的脉冲型边缘,灰度值突变非常剧烈(类似理想边缘)。常见于锐利边界。 | 模糊后消失或变为 Roof-Structure。 |
Astep-Structure | 突然的阶跃型边缘,灰度值在短时间内发生显著变化。 | 模糊后变为 Gstep-Structure。 |
Gstep-Structure | 渐变的阶跃型边缘,灰度值变化较缓慢。 | 模糊后仍为 Gstep-Structure,但锐度下降。 |
Roof-Structure | 屋脊型边缘,灰度值先上升后下降,形成“尖顶”状结构。 | 模糊后仍为 Roof-Structure,但锐度下降。 |
✅ 边缘结构与模糊检测的关系:
- 清晰图像:通常包含所有四种类型的边缘,尤其是 Dirac 和 Astep 占一定比例。
- 模糊图像:
- Dirac 和 Astep 边缘消失(因为它们对模糊最敏感);
- Gstep 和 Roof 边缘锐度下降(表现为小波系数能量分布变化);
- 因此可以通过检测这些边缘类型的比例变化来判断图像是否模糊,以及模糊程度。
✅ 小波变换中的作用:
在使用 Haar 小波变换进行边缘检测时,这些边缘类型在不同尺度下的能量响应不同:
- Dirac/Astep:在**细尺度(小波第1层)**能量最强;
- Gstep/Roof:在**中尺度或粗尺度(第2、3层)**能量更强;
- 利用这些响应规律,可以设计规则来识别边缘类型,并进一步判断图像是否模糊。
✅ 总结一句话:
Dirac 和 Astep 是“锐利边缘”的代表,模糊时会消失;Gstep 和 Roof 是“缓变边缘”的代表,模糊时会变钝。
2. Blur Detection for Digital Images Using Wavelet Transform
code: https://github.com/pedrofrodenas/blur-Detection-Haar-Wavelet/blob/master/README.md
paper:http://tonghanghang.org/pdfs/icme04_blur.pdf
这篇论文提出了一种基于Haar小波变换的图像模糊检测方法,主要应用于数字图像的质量评估。以下是对论文主要思想、算法流程的梳理,以及相应的Python代码实现。
一、论文主要思想
论文提出了一种直接的图像模糊检测方法,无需重建模糊函数,而是通过分析图像边缘类型和边缘锐度来判断图像是否模糊以及模糊程度。
-
边缘类型分析:自然图像通常包含多种类型的边缘(如Dirac-Structure、Astep-Structure、Gstep-Structure、Roof-Structure)。
当图像发生模糊时,Dirac-Structure和Astep-Structure边缘会消失,
而Gstep-Structure和Roof-Structure边缘会变得不那么锐利。 -
边缘锐度分析:通过Haar小波变换,可以检测边缘的锐度变化,从而判断图像的模糊程度。
二、算法流程
算法主要分为以下几个步骤:
- 对图像进行三层Haar小波变换,得到不同尺度的边缘图。
- 边缘点检测:根据阈值判断边缘点。
- 边缘类型分类:
- 根据小波系数在不同尺度的分布,区分Dirac-Structure/Astep-Structure与Gstep-Structure/Roof-Structure。
- 进一步区分Roof-Structure与Gstep-Structure。
- 模糊判断:
- 如果图像中仍然存在Dirac-Structure或Astep-Structure,则认为图像不模糊。
- 否则,认为图像模糊。
- 模糊程度计算:计算模糊的Gstep-Structure和Roof-Structure边缘占总边缘的比例,作为模糊程度指标。
三、Python代码实现
以下是基于上述思想的简化版Python代码实现:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 1 20:22:32 2019@author: pedrofRodenas
"""import pywt
import cv2
import numpy as np
import os
import argparse
import jsonimport skimage
from matplotlib import pyplot as plt
from skimage.measure import block_reducedef blur_detect(img, threshold):# Convert image to grayscaleY = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)M, N = Y.shape# Crop input image to be 3 divisible by 2Y = Y[0:int(M/16)*16, 0:int(N/16)*16]# Step 1, compute Haar wavelet of input imageLL1,(LH1,HL1,HH1)= pywt.dwt2(Y, 'haar')# Another application of 2D haar to LL1LL2,(LH2,HL2,HH2)= pywt.dwt2(LL1, 'haar') # Another application of 2D haar to LL2LL3,(LH3,HL3,HH3)= pywt.dwt2(LL2, 'haar')# Construct the edge map in each scale Step 2E1 = np.sqrt(np.power(LH1, 2)+np.power(HL1, 2)+np.power(HH1, 2))E2 = np.sqrt(np.power(LH2, 2)+np.power(HL2, 2)+np.power(HH2, 2))E3 = np.sqrt(np.power(LH3, 2)+np.power(HL3, 2)+np.power(HH3, 2))M1, N1 = E1.shapeprint(E1.shape, E2.shape, E3.shape)fast1 = 1fast2 = 0if fast1:Emax1 = block_reduce(E1, (8, 8), np.max).reshape(-1)Emax2 = block_reduce(E2, (4, 4), np.max).reshape(-1)Emax3 = block_reduce(E3, (2, 2), np.max).reshape(-1)elif fast2:MK, NL = M1 // 8, N1 // 8Emax1 = E1.reshape(MK, 8, NL, 8).max(axis=(1, 3)).reshape(-1)Emax2 = E2.reshape(MK, 4, NL, 4).max(axis=(1, 3)).reshape(-1)Emax3 = E3.reshape(MK, 2, NL, 2).max(axis=(1, 3)).reshape(-1)# print(Emax1[:10])# print(Emax2[:10])# Step 3EdgePoint1 = Emax1 > thresholdEdgePoint2 = Emax2 > thresholdEdgePoint3 = Emax3 > threshold# Rule 1 Edge PojntsEdgePoint = EdgePoint1 + EdgePoint2 + EdgePoint3 # +类似求或n_edges = EdgePoint.shape[0]print(n_edges)# Rule 2 Dirak-Structure or Astep-StructureDAstructure = EdgePoint * (Emax1 > Emax2) * (Emax2 > Emax3)# Rule 3 Roof-Structure or Gstep-StructureRGstructure = EdgePoint * (Emax1 < Emax2) * (Emax2 < Emax3)# Rule 4 Roof-StructureRSstructure = EdgePoint * (Emax1 < Emax2) * (Emax2 > Emax3)# Rule 5 Edge more likely to be in a blurred imageBlurC = (Emax1 < threshold) * (RGstructure + RSstructure)print(np.sum(EdgePoint), np.sum(DAstructure), np.sum(RGstructure), np.sum(RSstructure), np.sum(BlurC))# Step 6Per = np.sum(DAstructure)/np.sum(EdgePoint)# Step 7if (np.sum(RGstructure + RSstructure)) == 0:BlurExtent = 100else:BlurExtent = np.sum(BlurC) / (np.sum(RGstructure + RSstructure))print(Per, BlurExtent)return Per, BlurExtentdef find_images(input_dir):extensions = [".jpg", ".png", ".jpeg"]for root, dirs, files in os.walk(input_dir):for file in files:if os.path.splitext(file)[1].lower() in extensions:yield os.path.join(root, file)if __name__ == '__main__':process_single = 1if process_single:threshold = 35file = r'D:\code\fft\blur-Detection-Haar-Wavelet-master\images\blur\Original_292.jpg'file = r'D:\code\fft\blur-Detection-Haar-Wavelet-master\images\noblur\DSC01910.JPG'img = cv2.imread(file)per, blure = blur_detect(img, threshold)img1 = cv2.blur(img, [3,3])img2 = cv2.blur(img, [9,9])img3 = cv2.blur(img, [17,17])per1, blure1 = blur_detect(img1, threshold)per2, blure2 = blur_detect(img2, threshold)per3, blure3 = blur_detect(img3, threshold)print(per, blure,per1, blure1,per2, blure2,per3, blure3,)plt.figure()plt.subplot(221)plt.imshow(img)plt.subplot(222)plt.imshow(img1)plt.subplot(223)plt.imshow(img2)plt.subplot(224)plt.imshow(img3)plt.show()else:parser = argparse.ArgumentParser(description='run Haar Wavelet blur detection on a folder')parser.add_argument('-i', '--input_dir', dest="input_dir", type=str, required=True, help="directory of images")parser.add_argument('-s', '--save_path', dest='save_path', type=str, help="path to save output")parser.add_argument("-t", "--threshold", dest='threshold', type=float, default=35, help="blurry threshold")parser.add_argument("-d", "--decision", dest='MinZero', type=float, default=0.001, help="MinZero Decision Threshold")args = parser.parse_args()results = []for input_path in find_images(args.input_dir):try:I = cv2.imread(input_path)per, blurext = blur_detect(I, args.threshold)if per < args.MinZero:classification = Trueelse:classification = Falseresults.append({"input_path": input_path, "per": per, "blur extent": blurext, "is blur": classification})print("{0}, Per: {1:.5f}, blur extent: {2:.3f}, is blur: {3}".format(input_path, per, blurext, classification))except Exception as e:print(e)passif args.save_path:assert os.path.splitext(args.save_path)[1] == ".json", "You must include the extension .json on the end of the save path"with open(args.save_path, 'w') as outfile:json.dump(results, outfile, sort_keys=True, indent=4)outfile.write("\n")
四、代码说明
- 依赖库:
pywt
:用于小波变换。skimage
:用于图像读取和处理。
- 阈值设定:论文中建议阈值为35(灰度值范围0~255),代码中进行了归一化处理。
- 模糊判断:根据Dirac-Structure和Astep-Structure的比例判断是否模糊。
- 模糊程度:通过计算模糊的Gstep-Structure和Roof-Structure边缘的比例来衡量。
五、使用建议
- 你可以根据需要调整阈值
threshold
和MinZero
参数,以适应不同的图像集和应用场景。 - 以上代码为简化实现,实际应用中可能需要进一步优化和扩展。