DIP 数字图像处理:探讨不同西格玛对LoG算法的影响
- LoG:高斯函数的拉普拉斯变换;
- 用于求图像边缘;
- 结构元的大小应该是奇数保证有中心点;
1. 实验题目:
鉴于LoG算法在历史中的地位,进行较深入的实验研究探讨不同σ(西格玛)对LoG 算法的影响。
1)取σ =1.2然后求零交叉的结果;
2)取σ =2.8的然后求零交叉的结果;
3)讨论和结论:零交叉对σ的依赖性;
2. 实验环境:
win10 + Python3.7 + OpenCV4.1
3. 实验步骤:
3.1 将原始图片转为灰度图,高斯降噪;
3.2 构造LoG算子(根据sigma和kernel大小);
3.3 灰度图与LoG算子计算卷积;
3.4 找零交叉点,确定边缘;
4. 实验结果:
4.1 设置sigma = 1.2, kernel size = (9, 9)时,零交叉的结果如下:
4.2 设置sigma = 2.8, kernel size = (17, 17)时,零交叉的结果如下:
4.3 设置sigma = 5, kernel size = (31, 31)时,零交叉的结果如下:
4.4 设置sigma = 10, kernel size = (61, 61)时,零交叉的结果如下:
5. 实验结果分析:
5.1 从实验的效果可以看出,随着sigma的增大,得到的边缘尺度越来越大,边缘细节原来越不明显,显得更加粗略。
5.2 重点理解:二阶的交叉零点处的值,就是一阶的极大值,即边缘。二维高斯函数的拉普拉斯变换是二阶微分。
6. 所有程序代码:
#! -*- coding: utf-8 -*-
# py37
# 时间:2019年4月28日21:46:42
# DIP第三次作业:二阶微分增强作业(分析LoG算子)
import cv2
from scipy import signal
import numpy as np
def createLoGKernel(sigma, size): # 创建核(结构元)
"""
:param sigma: 浮点型
:param size: 整型,且为两个奇数
:return: 矩阵,log算子
"""
H, W = size
r, c = np.mgrid[0:H:1, 0:W:1]
r -= int((H-1)/2)
c -= int((W-1)/2)
sigma2 = pow(sigma, 2.0)
norm2 = np.power(r, 2.0) + np.power(c, 2.0)
LoGKernel = (norm2 / sigma2 - 2) * np.exp(- norm2 / (2 * sigma2))
return LoGKernel
def LoG(image, sigma, size, _boundary="symm"):
"""
:param image: 矩阵 灰度图
:param sigma: 浮点型 sigma
:param size: 整型 结构元
:param _boundary: 字符串 提供给 scipy 卷积的边界扩充类型 ,scipy 中的“symm”, 和opecv中的对称那种效果完全相同。
:return: 卷积后的矩阵(矩阵中有正有负)
"""
loGkernel = createLoGKernel(sigma, size)
img_conv_log = signal.convolve2d(image, loGkernel, 'same', boundary=_boundary)
return img_conv_log
if __name__ == "__main__":
fileName = "Chapter3_1.pgm" # 作业图片
image = cv2.imread(fileName)
image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # 转成灰度图
image = cv2.GaussianBlur(image, (5, 5), 0.05) # 平滑去燥
sigma = 1.2 # 调参
size = int(6*sigma + 1)
if size % 2 == 0: # size 只能取奇数,保证有中心点
size = size + 1
print(size)
img_con_log = LoG(image, sigma, (size, size), 'symm')
# 找零交叉并二值化
edge_binary = np.copy(img_con_log)
edge_binary[edge_binary > 0] = 255
edge_binary[edge_binary < 0] = 0
edge_binary = edge_binary.astype(np.uint8) # 数据类型转为整型
# 显示边缘检测后的图片
cv2.imshow("edge_binary", edge_binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
print("THE END")
THE END