北京哪个网站建设最好asp 英文企业网站 免费

web/2025/9/25 21:58:51/文章来源:
北京哪个网站建设最好,asp 英文企业网站 免费,php购物网站开发实例源码,个人二级网站怎么做文章目录 前言一、噪声种类与生成1.1 椒盐噪声1.2 高斯噪声1.3 彩色噪声 二、卷积操作2.1 卷积基本原理2.2 卷积操作代码实现 三、线性滤波3.1 均值滤波均值滤波原理均值滤波公式均值滤波代码实现 3.2 方框滤波方框滤波原理方框滤波公式方框滤波代码实现 3.3 高斯滤波高斯滤波原… 文章目录 前言一、噪声种类与生成1.1 椒盐噪声1.2 高斯噪声1.3 彩色噪声 二、卷积操作2.1 卷积基本原理2.2 卷积操作代码实现 三、线性滤波3.1 均值滤波均值滤波原理均值滤波公式均值滤波代码实现 3.2 方框滤波方框滤波原理方框滤波公式方框滤波代码实现 3.3 高斯滤波高斯滤波原理高斯滤波公式高斯滤波代码实现 3.4 可分离滤波可分离滤波原理可分离滤波公式可分离滤波代码实现 四、非线性滤波4.1 中值滤波中值滤波原理中值滤波公式中值滤波代码实现 4.2 双边滤波双边滤波原理双边滤波公式双边滤波代码实现 五、 边缘检测5.1 Sobel算子Sobel算子原理Sobel算子公式计算梯度Sobel算子代码实现 5.2 Scharr算子Scharr算子原理Scharr算子公式计算梯度Scharr算子代码实现 5.3 Laplacian算子Laplacian算子原理Laplacian算子公式Laplacian算子代码实现 5.4 Canny算子Canny算子原理Canny算子公式Canny算子代码实现 5.5 自定义边缘检测滤波器自定义边缘检测滤波器原理自定义边缘检测滤波器的一般步骤自定义边缘检测滤波器的例子自定义边缘检测代码实现 总结 前言 在计算机视觉领域图像处理是一个不可或缺的环节。图像滤波和边缘检测是图像处理中的两个关键任务它们在图像增强、特征提取等方面发挥着重要作用。本文将介绍噪声的种类与生成、卷积操作、线性滤波、非线性滤波以及边缘检测原理等内容。 一、噪声种类与生成 在图像处理中噪声是指图像中不希望出现的随机扰动。了解噪声的种类以及如何生成是图像处理中的重要一步。本节将详细介绍两种常见的噪声类型椒盐噪声和高斯噪声。另外追加一种彩色噪声原理与椒盐噪声和高斯噪声相同只是针对每个通道都进行噪声的扰动。并使用 OpenCV 编写示例代码来生成这三种噪声。 1.1 椒盐噪声 椒盐噪声是一种随机出现在图像中的黑白像素点的噪声通常模拟了图像传感器或传输过程中的不确定性。在椒盐噪声中一些像素被设为黑色椒噪声一些像素被设为白色盐噪声从而模拟图像中的随机点噪声。 下面是使用 OpenCV 生成椒盐噪声的示例代码 import cv2 import numpy as npdef add_salt_and_pepper_noise(image, salt_prob, pepper_prob):noisy_image np.copy(image)# 椒噪声salt_noise np.random.rand(*image.shape) salt_probnoisy_image[salt_noise] 255# 盐噪声pepper_noise np.random.rand(*image.shape) pepper_probnoisy_image[pepper_noise] 0return noisy_image# 读取图像 original_image cv2.imread(tulips.jpg, cv2.IMREAD_GRAYSCALE)# 设定椒盐噪声的概率 salt_probability 0.02 pepper_probability 0.02# 生成带有椒盐噪声的图像 noisy_image add_salt_and_pepper_noise(original_image, salt_probability, pepper_probability)# 显示原始图像和带有噪声的图像 cv2.imshow(Noisy Image (Salt and Pepper), cv2.hconcat([original_image, noisy_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中add_salt_and_pepper_noise 函数通过设定椒盐噪声的概率在图像中添加了随机的黑白像素点从而生成了椒盐噪声。 1.2 高斯噪声 高斯噪声是一种连续的随机过程其数学模型符合正态分布。在图像中高斯噪声表现为像素值的随机波动通常是由于环境、设备等因素引起。下面是使用 OpenCV 生成高斯噪声的示例代码 import cv2 import numpy as npdef add_gaussian_noise(image, mean0, sigma25):row, col image.shapegauss np.random.normal(mean, sigma, (row, col))noisy_image np.clip(image gauss, 0, 255)return noisy_image.astype(np.uint8)# 读取图像 original_image cv2.imread(tulips.jpg, cv2.IMREAD_GRAYSCALE)# 生成带有高斯噪声的图像 noisy_image add_gaussian_noise(original_image)# 显示原始图像和带有噪声的图像 cv2.imshow(Noisy Image (Gaussian), cv2.hconcat([original_image, noisy_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中add_gaussian_noise 函数使用 NumPy 生成了服从正态分布的随机数然后将其添加到图像中生成了高斯噪声。通过调整 mean 和 sigma 参数可以控制噪声的均值和标准差。 1.3 彩色噪声 彩色噪声是指在图像中引入的随机彩色扰动。下面是使用 OpenCV 生成彩色噪声的示例代码 import cv2 import numpy as npdef add_colored_noise(image, intensity50):row, col, ch image.shapecolored_noise np.random.randint(-intensity, intensity, (row, col, ch))noisy_image np.clip(image colored_noise, 0, 255)return noisy_image.astype(np.uint8)# 读取图像 original_image cv2.imread(tulips.jpg)# 生成带有彩色噪声的图像 noisy_image add_colored_noise(original_image)# 显示原始图像和带有噪声的图像 cv2.imshow(Original Image, original_image) cv2.imshow(Noisy Image (Colored), noisy_image) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中add_colored_noise 函数通过生成随机彩色扰动并将其添加到图像中实现了彩色噪声的生成。调整 intensity 参数可以控制噪声的强度。 二、卷积操作 卷积操作是图像处理中的核心步骤它通过滤波器与图像进行卷积来实现特征提取、去噪或进行边缘检测等任务。本节将详细说明卷积操作的基本原理并使用 OpenCV 编写示例代码来演示卷积在图像处理中的应用。 2.1 卷积基本原理 卷积操作的基本原理是通过一个滤波器也称为卷积核或卷积矩阵在图像上进行滑动滤波器的每个元素与图像对应位置的像素值相乘然后将所有结果相加最终形成新的图像。这个过程可以用数学公式表示为 ( f ∗ g ) ( x , y ) ∑ i ∑ j f ( x − i , y − j ) ⋅ g ( i , j ) (f * g)(x, y) \sum_{i} \sum_{j} f(x-i, y-j) \cdot g(i, j) (f∗g)(x,y)i∑​j∑​f(x−i,y−j)⋅g(i,j) 其中 f f f 是原始图像 g g g 是滤波器 ( f ∗ g ) (f * g) (f∗g) 是卷积操作的结果。 2.2 卷积操作代码实现 下面是一个简单的示例代码演示如何使用 OpenCV 进行卷积操作。在这个例子中我们将使用一个简单的平均滤波器均值滤波对图像进行卷积以实现图像的平滑效果。 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)def add_colored_noise(image, intensity50):row, col, ch image.shapecolored_noise np.random.randint(-intensity, intensity, (row, col, ch))noisy_image np.clip(image colored_noise, 0, 255)return noisy_image.astype(np.uint8)# 生成带有彩色噪声的图像 noisy_image add_colored_noise(image) # 定义一个均值滤波器卷积核 kernel_size (5, 5) kernel np.ones(kernel_size, np.float32) / (kernel_size[0] * kernel_size[1]) # 应用卷积操作 convolved_image cv2.filter2D(noisy_image, -1, kernel)# 在每张图像的左上角添加文字描述 font cv2.FONT_HERSHEY_SIMPLEX font_scale 1 thickness 1 padding 30 color tuple((0, 255, 0))cv2.putText(image, Original Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(noisy_image, Noisy Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(convolved_image, Convolved Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA)# 显示原始图像和卷积操作的结果 cv2.imshow(Convolved Image, cv2.hconcat([image, noisy_image, convolved_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中cv2.filter2D 函数接受图像、数据类型和卷积核作为参数然后应用卷积操作。在这个例子中我们使用了一个简单的均值滤波器但根据任务的不同可以选择不同的卷积核来实现不同的图像处理效果。 更多卷积操作请参考卷积操作快速入门 三、线性滤波 在图像处理中线性滤波是一种通过卷积操作对图像进行平滑处理的技术其主要目的是去除图像中的噪声。本节将详细介绍四种常见的线性滤波方法均值滤波、方框滤波、高斯滤波和可分离滤波并使用 OpenCV 编写示例代码来演示它们的应用。 3.1 均值滤波 均值滤波原理 均值滤波是一种平滑图像的方法它基于一个简单的思想用图像中某一像素点周围邻域的像素值的平均值来代替该像素点的值。这个邻域可以是一个矩形、圆形或者其他形状的区域其大小由滤波器的大小决定。 均值滤波公式 对于一个大小为 m × n m \times n m×n 的滤波器其中心位于图像的像素位置 ( x , y ) (x, y) (x,y)均值滤波的公式可以表示为 Output ( x , y ) 1 m n ∑ i 0 m − 1 ∑ j 0 n − 1 Input ( x i − ⌊ m / 2 ⌋ , y j − ⌊ n / 2 ⌋ ) \text{Output}(x, y) \frac{1}{mn} \sum_{i0}^{m-1} \sum_{j0}^{n-1} \text{Input}(x i - \lfloor m/2 \rfloor, y j - \lfloor n/2 \rfloor) Output(x,y)mn1​i0∑m−1​j0∑n−1​Input(xi−⌊m/2⌋,yj−⌊n/2⌋) 其中 Output ( x , y ) \text{Output}(x, y) Output(x,y) 是滤波后图像的像素值。 Input ( x i − ⌊ m / 2 ⌋ , y j − ⌊ n / 2 ⌋ ) \text{Input}(x i - \lfloor m/2 \rfloor, y j - \lfloor n/2 \rfloor) Input(xi−⌊m/2⌋,yj−⌊n/2⌋) 是原始图像中邻域内像素的值。 m m m 和 n n n 是滤波器的大小 ⌊ ⋅ ⌋ \lfloor \cdot \rfloor ⌊⋅⌋ 表示向下取整。 这个公式表示了在滤波器覆盖的区域内取所有像素的平均值作为中心像素的新值从而实现图像的平滑效果。 均值滤波代码实现 下面是使用 OpenCV 实现均值滤波的示例代码 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)def add_colored_noise(image, intensity50):row, col, ch image.shapecolored_noise np.random.randint(-intensity, intensity, (row, col, ch))noisy_image np.clip(image colored_noise, 0, 255)return noisy_image.astype(np.uint8)# 生成带有彩色噪声的图像 noisy_image add_colored_noise(image) # 应用均值滤波 kernel_size (5, 5) blurred_image cv2.blur(noisy_image, kernel_size)# 在每张图像的左上角添加文字描述 font cv2.FONT_HERSHEY_SIMPLEX font_scale 1 thickness 1 padding 30 color tuple((0, 255, 0))cv2.putText(image, Original Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(noisy_image, Noisy Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(blurred_image, Blurred Image (Mean), (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA)# 显示原始图像和经过均值滤波的图像 cv2.imshow(Blurred Image (Mean), cv2.hconcat([image, noisy_image, blurred_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中cv2.blur 函数接受图像和卷积核的大小作为参数然后应用均值滤波。 3.2 方框滤波 方框滤波原理 方框滤波是一种线性滤波方法类似于均值滤波它通过在滤波器窗口内对像素进行加权平均来减小图像噪声。 方框滤波公式 对于一个大小为 m × n m \times n m×n 的方框滤波器其中心位于图像的像素位置 ( x , y ) (x, y) (x,y)方框滤波的公式可以表示为 Output ( x , y ) 1 kernel_size ∑ i 0 m − 1 ∑ j 0 n − 1 Input ( x i − ⌊ m / 2 ⌋ , y j − ⌊ n / 2 ⌋ ) \text{Output}(x, y) \frac{1}{\text{kernel\_size}} \sum_{i0}^{m-1} \sum_{j0}^{n-1} \text{Input}(x i - \lfloor m/2 \rfloor, y j - \lfloor n/2 \rfloor) Output(x,y)kernel_size1​i0∑m−1​j0∑n−1​Input(xi−⌊m/2⌋,yj−⌊n/2⌋) 其中 Output ( x , y ) \text{Output}(x, y) Output(x,y) 是滤波后图像的像素值。 Input ( x i − ⌊ m / 2 ⌋ , y j − ⌊ n / 2 ⌋ ) \text{Input}(x i - \lfloor m/2 \rfloor, y j - \lfloor n/2 \rfloor) Input(xi−⌊m/2⌋,yj−⌊n/2⌋) 是原始图像中邻域内像素的值。 m m m 和 n n n 是方框滤波器的大小 ⌊ ⋅ ⌋ \lfloor \cdot \rfloor ⌊⋅⌋ 表示向下取整。 kernel_size m × n \text{kernel\_size} m \times n kernel_sizem×n 是滤波器的大小表示权重的总和。 方框滤波器中的每个像素都具有相同的权重这与均值滤波类似。这种滤波器在减小噪声的同时会导致图像的细节丢失。 方框滤波代码实现 下面是使用 OpenCV 实现方框滤波的示例代码 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)def add_colored_noise(image, intensity50):row, col, ch image.shapecolored_noise np.random.randint(-intensity, intensity, (row, col, ch))noisy_image np.clip(image colored_noise, 0, 255)return noisy_image.astype(np.uint8)# 生成带有彩色噪声的图像 noisy_image add_colored_noise(image) # 应用方框滤波 kernel_size (5, 5) box_filtered_image cv2.boxFilter(noisy_image, -1, kernel_size, normalize1)# 在每张图像的左上角添加文字描述 font cv2.FONT_HERSHEY_SIMPLEX font_scale 1 thickness 1 padding 30 color tuple((0, 255, 0))cv2.putText(image, Original Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(noisy_image, Noisy Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(box_filtered_image, Filtered Image (Box), (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA)# 显示原始图像和经过方框滤波的图像 cv2.imshow(Filtered Image (Box), cv2.hconcat([image, noisy_image, box_filtered_image])) cv2.waitKey(0) cv2.destroyAllWindows()在OpenCV的boxFilter函数中normalize参数控制是否对方框滤波的结果进行归一化。 下面解释一下normalize1和normalize0的情况 normalize1 当normalize参数设置为1时方框滤波器的结果会进行归一化即除以方框滤波器窗口内所有像素的权重之和。这可以防止输出像素值超过原始范围0到255从而保持图像的亮度一致性。归一化后的输出像素值计算公式见上面的公式。 normalize0 当normalize参数设置为0时方框滤波器的结果不进行归一化即直接将窗口内像素值的和作为输出像素值。这可能导致输出像素值超过原始范围因此在使用时需要注意。这种情况适用于特定需求例如在不关心亮度一致性的情况下。 综上选择normalize参数的值取决于具体的应用需求和对输出图像范围的要求。通常情况下如果希望输出图像的亮度与原始图像一致建议使用normalize1。 3.3 高斯滤波 高斯滤波原理 高斯滤波是一种线性滤波方法它使用高斯函数作为核函数对图像进行卷积。高斯滤波的主要思想是对图像的每个像素赋予一个权重权重由高斯分布函数决定距离中心像素越远的像素拥有更小的权重。 高斯滤波公式 对于一个大小为 m × n m \times n m×n 的高斯滤波器其中心位于图像的像素位置 ( x , y ) (x, y) (x,y)高斯滤波的公式可以表示为 Output ( x , y ) 1 ∑ i 0 m − 1 ∑ j 0 n − 1 G ( i , j , σ ) ∑ i 0 m − 1 ∑ j 0 n − 1 G ( i , j , σ ) ⋅ Input ( x i − ⌊ m / 2 ⌋ , y j − ⌊ n / 2 ⌋ ) \text{Output}(x, y) \frac{1}{\sum_{i0}^{m-1} \sum_{j0}^{n-1} G(i, j, \sigma)} \sum_{i0}^{m-1} \sum_{j0}^{n-1} G(i, j, \sigma) \cdot \text{Input}(x i - \lfloor m/2 \rfloor, y j - \lfloor n/2 \rfloor) Output(x,y)∑i0m−1​∑j0n−1​G(i,j,σ)1​i0∑m−1​j0∑n−1​G(i,j,σ)⋅Input(xi−⌊m/2⌋,yj−⌊n/2⌋) 其中 Output ( x , y ) \text{Output}(x, y) Output(x,y) 是滤波后图像的像素值。 Input ( x i − ⌊ m / 2 ⌋ , y j − ⌊ n / 2 ⌋ ) \text{Input}(x i - \lfloor m/2 \rfloor, y j - \lfloor n/2 \rfloor) Input(xi−⌊m/2⌋,yj−⌊n/2⌋) 是原始图像中邻域内像素的值。 m m m 和 n n n 是高斯滤波器的大小 ⌊ ⋅ ⌋ \lfloor \cdot \rfloor ⌊⋅⌋ 表示向下取整。 G ( i , j , σ ) G(i, j, \sigma) G(i,j,σ) 是高斯分布函数表示离中心像素 ( 0 , 0 ) (0, 0) (0,0) 的偏移为 ( i , j ) (i, j) (i,j) 的权重 σ \sigma σ 是高斯函数的标准差。 高斯滤波通过调整标准差 σ \sigma σ 的值可以控制滤波器的形状较大的 σ \sigma σ 值会使滤波器更加平滑而较小的 σ \sigma σ 值则会保留更多细节。 高斯滤波代码实现 下面是使用 OpenCV 实现高斯滤波的示例代码 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)def add_colored_noise(image, intensity50):row, col, ch image.shapecolored_noise np.random.randint(-intensity, intensity, (row, col, ch))noisy_image np.clip(image colored_noise, 0, 255)return noisy_image.astype(np.uint8)# 生成带有彩色噪声的图像 noisy_image add_colored_noise(image) # 应用高斯滤波 kernel_size (5, 5) sigma 1.5 gaussian_blurred_image cv2.GaussianBlur(noisy_image, kernel_size, sigma)# 在每张图像的左上角添加文字描述 font cv2.FONT_HERSHEY_SIMPLEX font_scale 1 thickness 1 padding 30 color tuple((0, 255, 0))cv2.putText(image, Original Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(noisy_image, Noisy Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(gaussian_blurred_image, Blurred Image (Gaussian), (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA)# 显示原始图像和经过高斯滤波的图像 cv2.imshow(Blurred Image (Gaussian), cv2.hconcat([image, noisy_image, gaussian_blurred_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中cv2.GaussianBlur 函数接受图像、卷积核的大小和高斯核的标准差作为参数然后应用高斯滤波。 3.4 可分离滤波 可分离滤波原理 可分离滤波是一种优化的滤波方法它将二维滤波操作分解为两个一维滤波操作从而降低了计算复杂度。这种分解的思想基于卷积操作的结合律即二维卷积可以分解为先在水平方向进行一维卷积然后在垂直方向进行一维卷积。 可分离滤波公式 对于一个大小为 m × n m \times n m×n 的可分离滤波器其中心位于图像的像素位置 ( x , y ) (x, y) (x,y)可分离滤波的公式可以表示为 Output ( x , y ) ∑ i 0 m − 1 H ( i ) ⋅ ( ∑ j 0 n − 1 H ( j ) ⋅ Input ( x i − ⌊ m / 2 ⌋ , y j − ⌊ n / 2 ⌋ ) ) \text{Output}(x, y) \sum_{i0}^{m-1} H(i) \cdot \left( \sum_{j0}^{n-1} H(j) \cdot \text{Input}(x i - \lfloor m/2 \rfloor, y j - \lfloor n/2 \rfloor) \right) Output(x,y)i0∑m−1​H(i)⋅(j0∑n−1​H(j)⋅Input(xi−⌊m/2⌋,yj−⌊n/2⌋)) 其中 Output ( x , y ) \text{Output}(x, y) Output(x,y) 是滤波后图像的像素值。 Input ( x i − ⌊ m / 2 ⌋ , y j − ⌊ n / 2 ⌋ ) \text{Input}(x i - \lfloor m/2 \rfloor, y j - \lfloor n/2 \rfloor) Input(xi−⌊m/2⌋,yj−⌊n/2⌋) 是原始图像中邻域内像素的值。 m m m 和 n n n 是可分离滤波器的大小 ⌊ ⋅ ⌋ \lfloor \cdot \rfloor ⌊⋅⌋ 表示向下取整。 H ( i ) H(i) H(i) 和 H ( j ) H(j) H(j) 是水平和垂直方向的一维滤波核。 通过这种分解可分离滤波器的计算量大大减少因为原始的二维卷积操作被拆分为两个一维卷积操作。这在实际应用中提高了滤波的效率特别是对于大尺寸的滤波器。 可分离滤波代码实现 下面是使用 OpenCV 实现可分离滤波的示例代码 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)def add_colored_noise(image, intensity50):row, col, ch image.shapecolored_noise np.random.randint(-intensity, intensity, (row, col, ch))noisy_image np.clip(image colored_noise, 0, 255)return noisy_image.astype(np.uint8)# 生成带有彩色噪声的图像 noisy_image add_colored_noise(image) # 定义一个一维滤波核 kernel_size 5 kernel_1d cv2.getGaussianKernel(kernel_size, -1)# 将一维核分解为水平和垂直核 kernel_2d np.outer(kernel_1d, kernel_1d.T)# 应用可分离滤波 separable_filtered_image cv2.filter2D(noisy_image, -1, kernel_2d)# 在每张图像的左上角添加文字描述 font cv2.FONT_HERSHEY_SIMPLEX font_scale 1 thickness 1 padding 30 color tuple((0, 255, 0))cv2.putText(image, Original Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(noisy_image, Noisy Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(separable_filtered_image, Filtered Image (Separable), (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA)# 显示原始图像和经过可分离滤波的图像 cv2.imshow(Filtered Image (Separable), cv2.hconcat([image, noisy_image, separable_filtered_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中首先使用 cv2.getGaussianKernel 获取一个一维的高斯核然后通过 np.outer 函数将其分解为二维核最后应用可分离滤波。 四、非线性滤波 在图像处理中非线性滤波是一种通过非线性操作对图像进行处理的方法主要用于去除各种类型的噪声。本节将详细介绍两种常见的非线性滤波方法中值滤波和双边滤波。 4.1 中值滤波 中值滤波原理 中值滤波是一种非线性滤波方法它的基本原理是用像素邻域中的中值来代替该像素的灰度值。这种方法对于去除椒盐噪声图像中突然出现的亮或暗的像素点效果较好因为中值对异常值不敏感。 邻域选择 对于每个像素选择一个邻域通常是一个正方形或矩形区域包含该像素及其周围的一些邻近像素。 中值计算 在选定的邻域中将像素的灰度值按大小排序然后选择中间值作为该像素的新灰度值。 替换 将原始像素的值替换为计算得到的中值。 中值滤波公式 假设有一个大小为 m × n m \times n m×n 的邻域其中 m m m 表示邻域的行数 n n n 表示邻域的列数。对于位置 ( i , j ) (i, j) (i,j) 的像素中值滤波的公式可以表示为 I med ( i , j ) median { I ( p , q ) ∣ i − m 2 ≤ p ≤ i m 2 , j − n 2 ≤ q ≤ j n 2 } I_{\text{med}}(i, j) \text{median}\left\{ I(p, q) \mid i-\frac{m}{2} \leq p \leq i\frac{m}{2},\; j-\frac{n}{2} \leq q \leq j\frac{n}{2} \right\} Imed​(i,j)median{I(p,q)∣i−2m​≤p≤i2m​,j−2n​≤q≤j2n​} 其中 I med ( i , j ) I_{\text{med}}(i, j) Imed​(i,j) 是中值滤波后得到的像素值。 I ( p , q ) I(p, q) I(p,q) 是位置 ( p , q ) (p, q) (p,q) 处的原始像素值。median 表示中值运算即将一组值按大小排序后选择中间的值。 这个公式表示对于图像中的每个像素选择其周围邻域内像素值的中值作为新的像素值。这样的操作对于消除椒盐噪声等突发性噪声效果较好。 中值滤波代码实现 下面是使用 OpenCV 实现中值滤波的示例代码 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)def add_colored_noise(image, intensity50):row, col, ch image.shapecolored_noise np.random.randint(-intensity, intensity, (row, col, ch))noisy_image np.clip(image colored_noise, 0, 255)return noisy_image.astype(np.uint8)# 生成带有彩色噪声的图像 noisy_image add_colored_noise(image)# 应用中值滤波 kernel_size 3 # 可根据需要调整核的大小 median_filtered_image cv2.medianBlur(noisy_image, kernel_size)# 在每张图像的左上角添加文字描述 font cv2.FONT_HERSHEY_SIMPLEX font_scale 1 thickness 1 padding 30 color tuple((0, 255, 0))cv2.putText(image, Original Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(noisy_image, Noisy Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(median_filtered_image, Filtered Image (Median), (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA)# 显示原始图像和经过中值滤波的图像 cv2.imshow(Filtered Image (Median), cv2.hconcat([image, noisy_image, median_filtered_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中cv2.medianBlur 函数接受图像和核的大小作为参数然后应用中值滤波。 4.2 双边滤波 双边滤波原理 双边滤波是一种结合了空间域和灰度值域信息的滤波方法。它考虑了像素之间的空间距离和像素值之间的差异以达到既去噪又保留图像细节的目的。这对于保留边缘信息、维持图像的整体结构很有用。 空间域权重 双边滤波首先计算像素之间的空间距离距离越近的像素其权重越大。这一部分确保了在滤波过程中考虑到像素的相邻关系。 灰度值域权重 双边滤波还考虑了像素值之间的差异。如果两个像素在灰度值上差异很大它们的权重会相应减小。这一部分确保了在滤波过程中对于边缘区域的保护。 综合权重 将空间域权重和灰度值域权重相乘得到综合的权重。 滤波 使用计算得到的权重对邻域内的像素进行加权平均得到最终的滤波结果。 双边滤波公式 对于图像中的每个像素 ( i , j ) (i, j) (i,j)双边滤波的计算可以表示为 I bf ( i , j ) 1 W p ∑ p 1 m ∑ q 1 n w ( i − p , j − q , σ s ) ⋅ w ( I ( i , j ) − I ( p , q ) , σ r ) ⋅ I ( p , q ) I_{\text{bf}}(i, j) \frac{1}{W_{\text{p}}}\sum_{p1}^{m}\sum_{q1}^{n} w(i-p, j-q, \sigma_s) \cdot w(I(i, j) - I(p, q), \sigma_r) \cdot I(p, q) Ibf​(i,j)Wp​1​p1∑m​q1∑n​w(i−p,j−q,σs​)⋅w(I(i,j)−I(p,q),σr​)⋅I(p,q) 其中 I bf ( i , j ) I_{\text{bf}}(i, j) Ibf​(i,j) 是双边滤波后得到的像素值。 W p W_{\text{p}} Wp​ 是归一化因子确保权重和为1。 w ( ⋅ , ⋅ ) w(\cdot, \cdot) w(⋅,⋅) 是权重函数分别表示空间域权重和灰度值域权重。 I ( i , j ) I(i, j) I(i,j) 是位置 ( i , j ) (i, j) (i,j) 处的原始像素值。 I ( p , q ) I(p, q) I(p,q) 表示位置 ( p , q ) (p, q) (p,q) 处的原始像素值。 m m m 和 n n n 是邻域的大小。 σ s \sigma_s σs​ 和 σ r \sigma_r σr​ 是控制空间域和灰度值域权重的两个参数。 这个公式表示对于图像中的每个像素通过计算空间域和灰度值域的权重对邻域内的像素进行加权平均以得到最终的滤波结果。这样可以在去噪的同时保留图像的边缘信息。 双边滤波代码实现 下面是使用 OpenCV 实现双边滤波的示例代码 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)def add_colored_noise(image, intensity50):row, col, ch image.shapecolored_noise np.random.randint(-intensity, intensity, (row, col, ch))noisy_image np.clip(image colored_noise, 0, 255)return noisy_image.astype(np.uint8)# 生成带有彩色噪声的图像 noisy_image add_colored_noise(image) # 应用双边滤波 d 15 # 控制像素值相似性的参数可根据需要调整 sigma_color 75 # 控制空间相似性的参数可根据需要调整 bilateral_filtered_image cv2.bilateralFilter(noisy_image, d, sigma_color, sigma_color)# 在每张图像的左上角添加文字描述 font cv2.FONT_HERSHEY_SIMPLEX font_scale 1 thickness 1 padding 30 color tuple((0, 255, 0))cv2.putText(image, Original Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(noisy_image, Noisy Image, (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA) cv2.putText(bilateral_filtered_image, Filtered Image (Bilateral), (padding, padding), font, font_scale, color, thickness, cv2.LINE_AA)# 显示原始图像和经过双边滤波的图像 cv2.imshow(Filtered Image (Bilateral), cv2.hconcat([image, noisy_image, bilateral_filtered_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中cv2.bilateralFilter 函数接受图像、像素值相似性参数 d、空间相似性参数 sigma_color 作为参数然后应用双边滤波。调整这些参数可以影响滤波效果。 五、 边缘检测 边缘检测用于寻找图像中的物体边界为后续的分析和识别提供了重要的信息。 本节将详细介绍四种常见的边缘检测算子Sobel算子、Scharr算子、Laplacian算子和Canny算子并介绍生成自定义边缘检测滤波器的方法。 5.1 Sobel算子 Sobel算子原理 Sobel算子是一种基于卷积操作的边缘检测算子常用于图像处理中。它的基本原理是通过对图像进行卷积操作计算每个像素点的梯度从而突出图像中的边缘信息。Sobel算子分为水平方向和垂直方向两种分别用于检测图像中的水平边缘和垂直边缘。 Sobel算子公式 垂直方向的Sobel算子Gy G y [ − 1 − 2 − 1 0 0 0 1 2 1 ] G_y \begin{bmatrix} -1 -2 -1 \\ 0 0 0 \\ 1 2 1 \end{bmatrix} Gy​ ​−101​−202​−101​ ​ 这个矩阵即为垂直方向的Sobel算子。通过将这个矩阵与图像进行卷积可以得到每个像素在垂直方向上的梯度。 对于图像中的每个像素 ( i , j ) (i, j) (i,j)计算垂直梯度的公式为 G y ( i , j ) ∑ m − 1 1 ∑ n − 1 1 G y ( m , n ) ⋅ I ( i m , j n ) G_y(i, j) \sum_{m-1}^{1}\sum_{n-1}^{1} G_y(m, n) \cdot I(im, jn) Gy​(i,j)m−1∑1​n−1∑1​Gy​(m,n)⋅I(im,jn) 其中 G y ( m , n ) G_y(m, n) Gy​(m,n) 是Sobel算子矩阵中位于位置 ( m , n ) (m, n) (m,n) 处的元素 I ( i m , j n ) I(im, jn) I(im,jn) 是图像中位置 ( i m , j n ) (im, jn) (im,jn) 处的像素值。这个卷积操作实际上就是将Sobel算子与图像进行逐像素的乘积和求和。 计算垂直梯度的示例 G y ( i , j ) ( − 1 ) ⋅ I ( i − 1 , j − 1 ) ( − 2 ) ⋅ I ( i , j − 1 ) ( − 1 ) ⋅ I ( i 1 , j − 1 ) 0 ⋅ I ( i − 1 , j ) 0 ⋅ I ( i , j ) 0 ⋅ I ( i 1 , j ) 1 ⋅ I ( i − 1 , j 1 ) 2 ⋅ I ( i , j 1 ) 1 ⋅ I ( i 1 , j 1 ) G_y(i, j) (-1) \cdot I(i-1, j-1) (-2) \cdot I(i, j-1) (-1) \cdot I(i1, j-1) \\ 0 \cdot I(i-1, j) 0 \cdot I(i, j) 0 \cdot I(i1, j) \\ 1 \cdot I(i-1, j1) 2 \cdot I(i, j1) 1 \cdot I(i1, j1) Gy​(i,j)(−1)⋅I(i−1,j−1)(−2)⋅I(i,j−1)(−1)⋅I(i1,j−1)0⋅I(i−1,j)0⋅I(i,j)0⋅I(i1,j)1⋅I(i−1,j1)2⋅I(i,j1)1⋅I(i1,j1) 水平方向的Sobel算子Gx G x [ − 1 0 1 − 2 0 2 − 1 0 1 ] G_x \begin{bmatrix} -1 0 1 \\ -2 0 2 \\ -1 0 1 \end{bmatrix} Gx​ ​−1−2−1​000​121​ ​ 这个矩阵即为水平方向的Sobel算子。通过将这个矩阵与图像进行卷积可以得到每个像素在水平方向上的梯度。 对于图像中的每个像素 ( i , j ) (i, j) (i,j)梯度的计算可以使用矩阵表示 G x ( i , j ) ∑ m − 1 1 ∑ n − 1 1 G x ( m , n ) ⋅ I ( i m , j n ) G_x(i, j) \sum_{m-1}^{1}\sum_{n-1}^{1} G_x(m, n) \cdot I(im, jn) Gx​(i,j)m−1∑1​n−1∑1​Gx​(m,n)⋅I(im,jn) 其中 G x ( m , n ) G_x(m, n) Gx​(m,n) 是Sobel算子矩阵中位于位置 ( m , n ) (m, n) (m,n) 处的元素 I ( i m , j n ) I(im, jn) I(im,jn) 是图像中位置 ( i m , j n ) (im, jn) (im,jn) 处的像素值。这个卷积操作实际上就是将Sobel算子与图像进行逐像素的乘积和求和。 计算水平梯度的的示例 G x ( i , j ) ( − 1 ) ⋅ I ( i − 1 , j − 1 ) 0 ⋅ I ( i , j − 1 ) 1 ⋅ I ( i 1 , j − 1 ) ( − 2 ) ⋅ I ( i − 1 , j ) 0 ⋅ I ( i , j ) 2 ⋅ I ( i 1 , j ) ( − 1 ) ⋅ I ( i − 1 , j 1 ) 0 ⋅ I ( i , j 1 ) 1 ⋅ I ( i 1 , j 1 ) G_x(i, j) (-1) \cdot I(i-1, j-1) 0 \cdot I(i, j-1) 1 \cdot I(i1, j-1) \\ (-2) \cdot I(i-1, j) 0 \cdot I(i, j) 2 \cdot I(i1, j) \\ (-1) \cdot I(i-1, j1) 0 \cdot I(i, j1) 1 \cdot I(i1, j1) Gx​(i,j)(−1)⋅I(i−1,j−1)0⋅I(i,j−1)1⋅I(i1,j−1)(−2)⋅I(i−1,j)0⋅I(i,j)2⋅I(i1,j)(−1)⋅I(i−1,j1)0⋅I(i,j1)1⋅I(i1,j1) 计算梯度 梯度的计算是Sobel算子在边缘检测中的一个关键步骤。通过在图像上应用水平方向的Sobel算子 G x G_x Gx​ 和垂直方向的Sobel算子 G y G_y Gy​可以得到每个像素点在水平和垂直方向上的梯度。然后利用这些梯度值可以计算梯度的大小和方向。 计算梯度大小 梯度大小表示边缘的强度可以通过以下公式计算 Gradient magnitude G x 2 G y 2 \text{Gradient magnitude} \sqrt{G_x^2 G_y^2} Gradient magnitudeGx2​Gy2​ ​ 其中 G x G_x Gx​ 和 G y G_y Gy​ 分别是水平和垂直方向上的梯度。 计算梯度方向 梯度方向表示边缘的方向可以通过以下公式计算 Gradient direction arctan ⁡ ( G y G x ) \text{Gradient direction} \arctan\left(\frac{G_y}{G_x}\right) Gradient directionarctan(Gx​Gy​​) 这个公式使用反正切函数计算 G y G_y Gy​ 和 G x G_x Gx​ 的比值得到的角度表示梯度的方向。 通过这两个公式可以得到每个像素点的梯度大小和方向。在边缘检测中梯度较大的地方通常对应着图像中的边缘而梯度方向则指示着边缘的方向。这些信息对于分割图像中的目标、检测边缘等应用非常有用。 Sobel算子代码实现 下面是使用 OpenCV 实现Sobel算子的示例代码 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)# 应用Sobel算子 sobel_x cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize3) sobel_y cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize3)# 计算梯度幅值和方向 gradient_magnitude np.sqrt(sobel_x**2 sobel_y**2) gradient_direction np.arctan2(sobel_y, sobel_x)# # 分别显示原始图像和Sobel算子的结果 # cv2.imshow(Original Image, image) # cv2.imshow(Gradient Magnitude, cv2.convertScaleAbs(gradient_magnitude)) # cv2.imshow(Gradient Direction, gradient_direction) # cv2.imshow(Sobel X, cv2.convertScaleAbs(sobel_x)) # cv2.imshow(Sobel Y, cv2.convertScaleAbs(sobel_y)) # cv2.imshow(Sobel XY, cv2.convertScaleAbs(sobel_x)cv2.convertScaleAbs(sobel_y))# 将浮点数图像缩放到0到255的范围 normal_gradient_direction cv2.normalize(gradient_direction, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)# 共享的参数 shared_params {org: (10, 30),fontFace: cv2.FONT_HERSHEY_SIMPLEX,fontScale: 1,thickness: 2,color: (0, 255, 0),lineType: cv2.LINE_AA, } # 添加文字 original_image cv2.putText(image.copy(), Original Image,**shared_params) gradient_magnitude_image cv2.putText(cv2.convertScaleAbs(gradient_magnitude.copy()), Gradient Magnitude, **shared_params) gradient_direction_image cv2.putText(normal_gradient_direction, Gradient Direction, **shared_params) sobel_x_image cv2.putText(cv2.convertScaleAbs(sobel_x.copy()), Sobel X, **shared_params) sobel_y_image cv2.putText(cv2.convertScaleAbs(sobel_y.copy()), Sobel Y, **shared_params) sobel_xy_image cv2.putText(cv2.convertScaleAbs(sobel_x sobel_y), Sobel XY, **shared_params)# 水平拼接 row1 cv2.hconcat([original_image, gradient_magnitude_image, gradient_direction_image]) row2 cv2.hconcat([sobel_x_image, sobel_y_image, sobel_xy_image])# 垂直拼接 sobel_image cv2.vconcat([row1, row2])# 显示合并后的图像 cv2.imshow(Sobel Images, sobel_image) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中cv2.Sobel 函数接受图像、数据类型、x和y方向的导数、以及卷积核大小作为参数然后分别计算x和y方向的梯度最后计算梯度幅值和方向。 5.2 Scharr算子 Scharr算子原理 Scharr算子是一种用于边缘检测的算子类似于Sobel算子但其卷积核设计更为复杂旨在更敏感地捕捉图像中的细节。Scharr算子的目标是对图像的变化更敏感尤其是对于细小的、低频的边缘。 Scharr算子公式 水平方向的Scharr算子Gx G x [ − 3 − 10 − 3 0 0 0 3 10 3 ] G_x \begin{bmatrix} -3 -10 -3 \\ 0 0 0 \\ 3 10 3 \end{bmatrix} Gx​ ​−303​−10010​−303​ ​ 垂直方向的Scharr算子Gy G y [ − 3 0 3 − 10 0 10 − 3 0 3 ] G_y \begin{bmatrix} -3 0 3 \\ -10 0 10 \\ -3 0 3 \end{bmatrix} Gy​ ​−3−10−3​000​3103​ ​ 与Sobel算子相比Scharr算子的卷积核中的权重更为平滑和对称这使得它对图像中的高频细节更敏感。因此在一些需要更好细节捕捉的应用场景下Scharr算子可能表现得比Sobel算子更优秀。 计算梯度 计算梯度的方法与Sobel算子类似通过将Scharr算子与图像进行卷积操作分别得到水平方向 G x G_x Gx​ 和垂直方向 G y G_y Gy​ 上的梯度。然后可以使用以下公式计算梯度的大小和方向 Gradient magnitude G x 2 G y 2 \text{Gradient magnitude} \sqrt{G_x^2 G_y^2} Gradient magnitudeGx2​Gy2​ ​ Gradient direction arctan ⁡ ( G y G x ) \text{Gradient direction} \arctan\left(\frac{G_y}{G_x}\right) Gradient directionarctan(Gx​Gy​​) 在一些图像处理任务中Scharr算子在边缘检测中的性能可能会略优于Sobel算子尤其是在需要更好的细节保留和对细小边缘更敏感的情况下。 Scharr算子代码实现 下面是使用 OpenCV 实现Scharr算子的示例代码 import cv2 import numpy as np# 读取图像 image cv2.imread(tulips.jpg)# 应用Scharr算子 scharr_x cv2.Scharr(image, cv2.CV_64F, 1, 0) scharr_y cv2.Scharr(image, cv2.CV_64F, 0, 1)# 计算梯度幅值和方向 gradient_magnitude np.sqrt(scharr_x**2 scharr_y**2) gradient_direction np.arctan2(scharr_y, scharr_x)# # 分别显示原始图像和Sobel算子的结果 # cv2.imshow(Original Image, image) # cv2.imshow(Gradient Magnitude, cv2.convertScaleAbs(gradient_magnitude)) # cv2.imshow(Gradient Direction, gradient_direction) # cv2.imshow(Scharr X, cv2.convertScaleAbs(scharr_x)) # cv2.imshow(Scharr Y, cv2.convertScaleAbs(scharr_y)) # cv2.imshow(Sobel XY, cv2.convertScaleAbs(scharr_x)cv2.convertScaleAbs(scharr_y))# 将浮点数图像缩放到0到255的范围 normal_gradient_direction cv2.normalize(gradient_direction, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)# 共享的参数 shared_params {org: (10, 30),fontFace: cv2.FONT_HERSHEY_SIMPLEX,fontScale: 1,thickness: 2,color: (0, 255, 0),lineType: cv2.LINE_AA, } # 添加文字 original_image cv2.putText(image.copy(), Original Image,**shared_params) gradient_magnitude_image cv2.putText(cv2.convertScaleAbs(gradient_magnitude.copy()), Gradient Magnitude, **shared_params) gradient_direction_image cv2.putText(normal_gradient_direction, Gradient Direction, **shared_params) scharr_x_image cv2.putText(cv2.convertScaleAbs(scharr_x.copy()), Scharr X, **shared_params) scharr_y_image cv2.putText(cv2.convertScaleAbs(scharr_y.copy()), Scharr Y, **shared_params) scharr_xy_image cv2.putText(cv2.convertScaleAbs(scharr_x scharr_y), Scharr XY, **shared_params)# 水平拼接 row1 cv2.hconcat([original_image, gradient_magnitude_image, gradient_direction_image]) row2 cv2.hconcat([scharr_x_image, scharr_y_image, scharr_xy_image])# 垂直拼接 scharr_image cv2.vconcat([row1, row2])# 显示合并后的图像 cv2.imshow(Scharr Images, scharr_image) cv2.waitKey(0) cv2.destroyAllWindows()与Sobel算子类似cv2.Scharr 函数用于应用Scharr算子其余步骤与Sobel算子相似。 5.3 Laplacian算子 Laplacian算子原理 Laplacian算子是一种边缘检测算子它通过计算图像的二阶导数来突出图像中的边缘信息。该算子对图像中的灰度变化较大的区域有很好的响应因此常用于边缘检测和图像锐化。 Laplacian算子公式 Laplacian算子可以用以下卷积核表示 ∇ 2 [ 0 1 0 1 − 4 1 0 1 0 ] \nabla^2 \begin{bmatrix} 0 1 0 \\ 1 -4 1 \\ 0 1 0 \end{bmatrix} ∇2 ​010​1−41​010​ ​ 这个卷积核用于计算图像中每个像素点的二阶导数。对于图像中的每个像素 ( i , j ) (i, j) (i,j)使用以下公式计算Laplacian算子的响应 ∇ 2 ( i , j ) ∑ m − 1 1 ∑ n − 1 1 ∇ 2 ( m , n ) ⋅ I ( i m , j n ) \nabla^2(i, j) \sum_{m-1}^{1}\sum_{n-1}^{1} \nabla^2(m, n) \cdot I(im, jn) ∇2(i,j)m−1∑1​n−1∑1​∇2(m,n)⋅I(im,jn) 其中 ∇ 2 ( m , n ) \nabla^2(m, n) ∇2(m,n) 是Laplacian算子卷积核中位于位置 ( m , n ) (m, n) (m,n) 处的权重 I ( i m , j n ) I(im, jn) I(im,jn) 是图像中位置 ( i m , j n ) (im, jn) (im,jn) 处的像素值。 计算结果 Laplacian算子的计算结果表示了图像中每个像素点的强度变化。对于图像中的边缘Laplacian算子的响应通常呈现极值可以通过阈值处理来检测边缘。此外Laplacian算子对图像中的细节和纹理也具有一定的灵敏度。 在实际应用中可以通过调整阈值来控制检测到的边缘的数量和强度。 Laplacian算子代码实现 下面是使用 OpenCV 实现Laplacian算子的示例代码 import cv2# 读取图像 image cv2.imread(tulips.jpg)# 应用Laplacian算子 laplacian cv2.Laplacian(image, cv2.CV_64F)# 共享的参数 shared_params {org: (10, 30),fontFace: cv2.FONT_HERSHEY_SIMPLEX,fontScale: 1,thickness: 2,color: (0, 255, 0),lineType: cv2.LINE_AA, } # 添加文字 original_image cv2.putText(image.copy(), Original Image, **shared_params) laplacian_image cv2.putText(cv2.convertScaleAbs(laplacian), Laplacian Image, **shared_params)# 显示原始图像和Laplacian算子的结果 cv2.imshow(Laplacian Image, cv2.hconcat([original_image, laplacian_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中cv2.Laplacian 函数用于应用Laplacian算子得到图像的二阶导数。 5.4 Canny算子 Canny算子原理 Canny边缘检测是一种多阶段的算法旨在准确而稳定地检测图像中的边缘。Canny算法包括以下几个主要步骤 高斯平滑 使用高斯滤波器对图像进行平滑以减少噪声的影响。 梯度计算 计算图像的梯度使用Sobel、Scharr或其他梯度算子以捕捉图像中的边缘。 非极大值抑制 对梯度图像进行非极大值抑制保留梯度方向上的局部极大值以细化边缘。 边缘跟踪 使用双阈值边缘跟踪通过选择适当的高低阈值将强边缘和弱边缘分离并通过连接强边缘来形成完整的边缘。 Canny算子公式 1. 高斯平滑 高斯平滑使用一个二维高斯核进行卷积。假设 I I I 是原始图像 G G G 是高斯核 ∗ \ast ∗ 表示卷积操作则高斯平滑可以表示为 I smoothed G ∗ I I_{\text{smoothed}} G \ast I Ismoothed​G∗I 2. 梯度计算 梯度计算使用梯度算子如Sobel或Scharr计算图像在水平和垂直方向上的梯度 G x [ − 1 0 1 − 2 0 2 − 1 0 1 ] G_x \begin{bmatrix} -1 0 1 \\ -2 0 2 \\ -1 0 1 \end{bmatrix} Gx​ ​−1−2−1​000​121​ ​ G y [ − 1 − 2 − 1 0 0 0 1 2 1 ] G_y \begin{bmatrix} -1 -2 -1 \\ 0 0 0 \\ 1 2 1 \end{bmatrix} Gy​ ​−101​−202​−101​ ​ Gradient magnitude G x 2 G y 2 \text{Gradient magnitude} \sqrt{G_x^2 G_y^2} Gradient magnitudeGx2​Gy2​ ​ Gradient direction arctan ⁡ ( G y G x ) \text{Gradient direction} \arctan\left(\frac{G_y}{G_x}\right) Gradient directionarctan(Gx​Gy​​) 3. 非极大值抑制 非极大值抑制将梯度图像中非极大值的位置置为零保留梯度方向上的局部极大值。 4. 边缘跟踪 边缘跟踪使用双阈值法将梯度图像中高于高阈值的像素点标记为强边缘低于低阈值的像素点标记为弱边缘并通过连接强边缘形成最终的边缘。 Canny算法的优点在于能够较好地抑制噪声、准确地检测边缘并具有参数可调性。 Canny算子代码实现 下面是使用 OpenCV实现Canny算子的示例代码 import cv2# 读取图像 image cv2.imread(tulips.jpg)# 应用Canny算子 edges_low cv2.Canny(image, 0, 50) edges_mid cv2.Canny(image, 100, 150) edges_high cv2.Canny(image, 200, 250)# 共享的参数 shared_params {org: (10, 30),fontFace: cv2.FONT_HERSHEY_SIMPLEX,fontScale: 1,thickness: 2,color: (0, 255, 0),lineType: cv2.LINE_AA, } # 创建包含三个相同通道的图像 edges_low_bgr cv2.merge([edges_low, edges_low, edges_low]) edges_mid_bgr cv2.merge([edges_mid, edges_mid, edges_mid]) edges_high_bgr cv2.merge([edges_high, edges_high, edges_high]) # 添加文字 original_image cv2.putText(image.copy(), Original Image, **shared_params) edges_low_image cv2.putText(edges_low_bgr, Low Canny Edges, **shared_params) edges_mid_image cv2.putText(edges_mid_bgr, Mid Canny Edges, **shared_params) edges_high_image cv2.putText(edges_high_bgr, High Canny Edges, **shared_params)# 显示原始图像和Canny算子的结果 cv2.imshow(Canny Edges,cv2.vconcat([cv2.hconcat([original_image, edges_low_image]),cv2.hconcat([edges_mid_image, edges_high_image])])) cv2.waitKey(0) cv2.destroyAllWindows() 在上述代码中cv2.Canny 函数接受图像和两个阈值作为参数然后应用Canny算子进行边缘检测。 5.5 自定义边缘检测滤波器 自定义边缘检测滤波器原理 生成自定义边缘检测滤波器的原理在于设计一个卷积核该卷积核能够突出图像中的边缘信息。通常边缘检测滤波器的设计需要考虑对图像梯度的响应以及对噪声的鲁棒性。 自定义边缘检测滤波器的一般步骤 设计卷积核 确定卷积核的大小和权重。卷积核的设计直接影响了滤波器的性能需要考虑到边缘的方向和强度。 应用卷积操作 将设计好的卷积核应用于原始图像通过卷积操作得到滤波后的图像。 梯度计算 如果边缘检测是通过梯度信息进行的可以计算滤波后图像的梯度。梯度的大小和方向可以用于进一步分析边缘。 阈值处理 根据梯度信息或其他特征可以进行阈值处理来检测和强调边缘。 自定义边缘检测滤波器的例子 设计边缘检测滤波器的具体公式和权重需要根据实际需求和应用场景进行调整可以通过试验和调整来获得最佳效果。 给定的边缘检测滤波器是 Edge Filter [ 2 0 1 0 − 6 0 1 0 2 ] \text{Edge Filter} \begin{bmatrix} 2 0 1 \\ 0 -6 0 \\ 1 0 2 \end{bmatrix} Edge Filter ​201​0−60​102​ ​ 这个卷积核中心元素为-6周围元素为0、1、2是一个对角线方向的边缘检测滤波器。 如果将这个滤波器应用于原始图像 I I I可以通过卷积操作得到滤波后的图像 I filtered I_{\text{filtered}} Ifiltered​。卷积操作的一般形式如下 I filtered ( i , j ) ∑ m − 1 1 ∑ n − 1 1 Edge Filter ( m , n ) ⋅ I ( i m , j n ) I_{\text{filtered}}(i, j) \sum_{m-1}^{1}\sum_{n-1}^{1} \text{Edge Filter}(m, n) \cdot I(im, jn) Ifiltered​(i,j)m−1∑1​n−1∑1​Edge Filter(m,n)⋅I(im,jn) 其中 Edge Filter ( m , n ) \text{Edge Filter}(m, n) Edge Filter(m,n) 是滤波器中位于位置 ( m , n ) (m, n) (m,n) 处的权重 I ( i m , j n ) I(im, jn) I(im,jn) 是图像中位置 ( i m , j n ) (im, jn) (im,jn) 处的像素值。 这个特定的滤波器对图像中的边缘进行强调尤其是在对角线方向。应用该滤波器后可以通过观察滤波后的图像看到在对角线方向上的边缘特征更为突出。 自定义边缘检测代码实现 以下是一个简单的示例代码用于生成自定义的边缘检测滤波器 import cv2 import numpy as np# 生成自定义的边缘检测滤波器 custom_filter np.array([[2, 0, 1],[0, -6, 0],[1, 0, 2]])# 读取图像 image cv2.imread(tulips.jpg)# 应用自定义滤波器 custom_edges cv2.filter2D(image, cv2.CV_64F, custom_filter)# 共享的参数 shared_params {org: (10, 30),fontFace: cv2.FONT_HERSHEY_SIMPLEX,fontScale: 1,thickness: 2,color: (0, 255, 0),lineType: cv2.LINE_AA, }# 添加文字 original_image cv2.putText(image.copy(), Original Image, **shared_params) custom_image cv2.putText(cv2.convertScaleAbs(custom_edges), Custom Edges, **shared_params)# 显示原始图像和自定义滤波器的结果 cv2.imshow(Custom Edges, cv2.hconcat([original_image, custom_image])) cv2.waitKey(0) cv2.destroyAllWindows()在上述代码中通过 cv2.filter2D 函数可以应用自定义的边缘检测滤波器。根据实际需求可以调整滤波器的权重以达到期望的边缘检测效果。 总结 在本篇博客中我们深入探讨了图像处理中常见的噪声种类与生成方法简单介绍了卷积操作的基本原理和代码实现。随后我们详细讨论了线性滤波和非线性滤波的多种方法包括均值滤波、方框滤波、高斯滤波、中值滤波、双边滤波等分别阐述了它们的原理、公式和代码实现。 在边缘检测方面我们介绍了Sobel算子、Scharr算子、Laplacian算子和Canny算子等经典边缘检测算法的原理、公式和代码实现。此外我们还学习了如何生成自定义的边缘检测滤波器并通过例子展示了滤波器的设计和应用。 通过这篇博客不仅可以深入了解图像处理中常用的滤波方法和边缘检测算法还可以学习如何自定义滤波器以满足特定需求。希望本文能够更好地理解图像处理领域的一些关键概念和技术并为实际应用提供有益的指导。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/81840.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外贸网站推广怎么做wordpress 考试

作者 | 俞方桦 随着大数据时代的到来,传统的关系型数据库由于其在数据建模和存储方面的限制,变得越来越难以满足大量频繁变化的需求。关系型数据库,尽管其名称中有“关系”这个词,却并不擅长处理复杂关系的查询和分析。另外&…

网站创建多少年了安徽省住房城乡建设厅官方网站

Google 的项目大多使用 C开发。每一个 C程序员也都知道,C具有很多强大的语言特性,但这种强大不可避免的导致它的复杂,而复杂性会使得代码更容易出现 bug、难于阅读和维护。 本指南的目的是通过详细阐述如何进行 C编码来规避其复杂性&#xf…

asp做网站策划书哪些企业是中小企业

今天在自己的服务器上使用wget下载一个大文件时,不小心把ssh断开连接了,重新登上去后想查看这个文件的下载进度,现记录一些wget的知识点。1:后台下载使用wget -b url[root8f9fbda9bb48 ~]# wget -b http://cn.wordpress.org/word…

大学 英文网站建设萝岗营销型网站建设

目录 一. 前言 二. 实现 三. 优缺点 一. 前言 解释器模式(Interpreter Pattern)指给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子,属于行为型设计模式。是…

休闲咖啡厅网站开发目标怎样临沂网站建设

参考资料: VS插件开发 - 个性化VS IDE编辑器 自己动手编写一个VS插件(一) VS Addin插件基本开发入门 VS Addin插件配置、部署 转载于:https://www.cnblogs.com/wangwangfei/p/5830081.html

顺义做网站公司wordpress即时新闻

UNDO表空间用于存放UNDO数据,当执行DML操作(INSERT,UPDATE和DELETE)时,oracle会将这些操作执行前的旧数据 写入到 UNDO段,在oracle9i之前,管理UNDO数据时使用(Rollback Segment)完成的.从oracle9i开始,管理UNDO数据不仅可以使用回滚段,还可以使用UNDO表空间.因为规划和管理回滚…

企业网站手机端跳转设置网站源码在线查询

要在Ubuntu中查看设备的温度,可以使用一些命令行工具来获取系统硬件的温度信息。下面列出了几种常用的方法: 方法 1: 使用 sensors 命令 sensors 命令用于读取和显示系统中的传感器数据,包括CPU温度和其他硬件传感器的信息。首先需要安装 l…

最好用的免费建站平台中国十大互联网公司排名2021

在 Linux 内核的网络子系统中,netif_start_queue 函数扮演着至关重要的角色。这个函数的主要功能是启动(或启用)网络接口的发送队列,标志着网络接口已经准备好开始发送数据包。本文将深入探讨 netif_start_queue 函数的用途、工作原理以及在实际网络驱动代码中的应用。 函…

文化展厅的设计方案网站优化案例分析

位置参数 理论上,在函数定义时,我们可以为其定义多个参数。但是在函数调用时,我们也应该传递多个参数,正常情况,其要一一对应。 相关链接:Python---函数的作用,定义,使用步骤&…

番禺区建站服务商延吉市住房城乡建设局网站

转载自 服务器性能指标(二)——CPU利用率分析及问题排查 平常的工作中,在衡量服务器的性能时,经常会涉及到几个指标,load、cpu、mem、qps、rt等。每个指标都有其独特的意义,很多时候在线上出现问题时&…

网站如何添加友情链接网站的建设 教学计划

要求: 1、r5为isp,只能进行ip地址的配置,其所有ip地址均为共有ip地址 2、r1和r5使用ppp的PAP认证,r5为主认证方 r2和r5之间使用ppp的chap认证,r5为主认证方 r3和r5之间使用HDLC封装 3、r1 r2 r3构建一个MGRE环境…

win10记事本怎么做网站河南造价信息网官网

参考:https://edu.csdn.net/skill/c 1、输出 “Hello, World!” 字符串,请选出错误答案。 2、错误的print函数。 for … in …:是python的语法,C语言的写法是for (;😉 3、C标准 没有C19标准。 4、了解C编译管道 …

响应式网站psdWordPress顶部广告插件

阿里云服务器租用4核8G配置多少钱一年?700元一年。阿里云4核8G服务器租用优惠价格700元1年,配置为ECS通用算力型u1实例(ecs.u1-c1m2.xlarge)4核8G配置、1M到3M带宽可选、ESSD Entry系统盘20G到40G可选,CPU采用Intel(R)…

二手交易网站建设目标坂田网站建设多少钱

文章目录 前提一、运行效果二、代码获取 前言 首先确定自己的JDBC连接数据库已经完成,不懂可以看看其他博主的解析。 我使用的是SQL Server数据库,数据库名称为stu,账号为sa,密码为123456 数据库的表为student表,内容如下: 一、…

h5学习教程深圳网站优化项目

软件危机是指在计算机软件的开发和维护过程中所遇到的一系列严重问题。 典型表现: 开发成本和进度的估计常常很不准确 用户对已完成的软件系统不满意,闭门造车 软件质量(quality)不可靠 软件常常是不可维护的 软件产品供不应…

将网页加入可信站点网站做rss+wordpress

学习交流加 个人qq: 1126137994个人微信: liu1126137994学习交流资源分享qq群: 962535112 上一篇文章迈进了汇编的大门,点击链接查看上一篇文章:汇编语言和汇编软件 上一篇文章大概学会以下内容: 了解汇编…

专业的移动客户端网站建设如果在网站做推广连接

高版本的 lombok 和 tomcat 7 插件冲突问题 在开发期间,当我们使用 tomcat7-maven-plugin 来作为运行环境运行我们项目使,如果我们项目中使用了 1.16.20 及以上版本的 lombok 包,项目启动时会报错: for annotations org.apache.…

苏州建设交通招聘信息网站深圳高端网站建设费用

快速排序 平均时间复杂度 O(NlogN) 最差时间复杂度O(N*N) 不稳定 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序…

wordpress仿站实战教程计算机应用教程 网站的建设与维护

这道题我真的纠结好久,因为没注意那个原地的题目要求,所以很奇怪怎么我电脑运行成功,但是LeetCode上运行就是不对。气哭。 感谢群友lino的帮助。他试了set方法不行,直接喂给我的答案了。。。 题目:26. 删除排序数组中的…

网站设置不能手机访问做网站价格和配置

日志实现框架 常见框架: JULLogbacLog4jLog4j2 日志实现的抽象层 避免代码的改动影响用户的使用, 常见的: JCLSLF4J 日志发展历程 JDK1.3及以前, 通过System.(out | err).println打印, 存在巨大缺陷解决系统打印缺陷问题出现log4,2015年8月停止更新受到log4j影响, SUN公…