当前位置: 首页 > news >正文

图像处理——边缘检测

1 概述

  边缘检测是图像处理和计算机视觉中的一项基本技术,用于识别图像中亮度变化剧烈的像素点,这些像素点通常对应于物体的边界。它通过检测图像中亮度或颜色变化显著的区域,提取出物体的轮廓,常用于计算机视觉、图像处理和模式识别等领域。

  边缘检测的原理是通过计算图像中每个像素点与其周围像素点的亮度或颜色差异来确定该像素点是否为边缘。通常使用卷积操作来实现边缘检测,通过计算像素点与其周围像素点的差异来判断该像素点是否为边缘。

  判断边缘的方法很多,基本上分为两类:

  1. 基于搜索的方法: 基于搜索的边缘检测方法首先计算边缘强度,通常用一阶导数表示,例如梯度模;然后,用计算估计边缘的局部方向,通常采用梯度的方向,并利用此方向找到局部梯度模的最大值。
  2. 基于零交叉的方法: 基于零交叉的方法找到由图像得到的二阶导数的零交叉点来定位边缘.通常用拉普拉斯算子或非线性微分方程的零交叉点。

  而具体到实际场景中,具体的步骤为:

  1. 平滑图像: 减少噪声,噪声可能会被误认为是边缘。常用的平滑滤波器包括高斯滤波器。
  2. 计算导数: 计算图像中每个像素点的导数。根据导数的大小和方向,可以确定边缘的方向和强度。
  3. 非极大值抑制: 细化边缘,只保留梯度方向上的局部最大值。
  4. 阈值处理: 使用阈值来区分边缘像素和非边缘像素。

2 不同的边缘检测算法类型

2.1 一阶算子

  一阶算子是一种基于图像梯度的边缘检测方法,它通过计算图像灰度值的一阶导数来检测边缘,即利用像素灰度值的变化率来找到边缘位置。一阶算子通过梯度的大小和方向来确定边缘的位置和方向。其中:

  • 梯度:图像梯度表示灰度值在空间中的变化率,是一阶导数的体现。
  • 梯度大小:梯度大小表示边缘的强度,是梯度的模。梯度值大的区域通常对应图像中的边缘。
  • 梯度方向:梯度方向表示边缘的方向,是梯度的方向。

  图像的一阶梯度计算比较简单:
G x ( x , y ) = I ( x + 1 , y ) − I ( x , y ) G y ( x , y ) = I ( x , y + 1 ) − I ( x , y ) \begin{aligned} G_x(x, y) &= I(x+1, y) - I(x, y) \\ G_y(x, y) &= I(x, y+1) - I(x, y) \end{aligned} Gx(x,y)Gy(x,y)=I(x+1,y)I(x,y)=I(x,y+1)I(x,y)
  其中, I ( x , y ) I(x, y) I(x,y) 表示图像的灰度值, G x ( x , y ) G_x(x, y) Gx(x,y) G y ( x , y ) G_y(x, y) Gy(x,y) 分别表示图像在 x x x y y y 方向上的梯度。梯度的方向为:
θ ( x , y ) = arctan ⁡ G y ( x , y ) G x ( x , y ) \theta(x, y) = \arctan{\frac{G_y(x, y)}{G_x(x, y)}} θ(x,y)=arctanGx(x,y)Gy(x,y)
  梯度的大小为:
G ( x , y ) = G x ( x , y ) 2 + G y ( x , y ) 2 G(x, y) = \sqrt{G_x(x, y)^2 + G_y(x, y)^2} G(x,y)=Gx(x,y)2+Gy(x,y)2

  常见的一阶算子包括Sobel算子、Prewitt算子、Roberts算子等。

  • 优点
    • 计算简单,速度快。
    • 能够有效检测边缘位置。
    • Sobel 算子等加入平滑操作,抗噪声能力较强。
  • 缺点
    • 对噪声较为敏感(尤其是 Prewitt 和 Roberts 算子)。
    • 边缘定位精度不高,容易丢失细节。

2.2 二阶算子

  二阶算子是一种基于图像灰度值的二阶导数的边缘检测方法,它通过计算图像灰度值的二阶导数来检测边缘,即利用像素灰度值的变化率的变化率来找到边缘位置。二阶算子通过拉普拉斯算子来计算图像的二阶导数,然后通过阈值处理来确定边缘的位置和方向。二阶算子的计算公式为:
L ( x , y ) = ∇ 2 I ( x , y ) = ∂ 2 I ( x , y ) ∂ x 2 + ∂ 2 I ( x , y ) ∂ y 2 L(x, y) = \nabla^2 I(x, y) = \frac{\partial^2 I(x, y)}{\partial x^2} + \frac{\partial^2 I(x, y)}{\partial y^2} L(x,y)=2I(x,y)=x22I(x,y)+y22I(x,y)
  其中, I ( x , y ) I(x, y) I(x,y) 表示图像的灰度值, L ( x , y ) L(x, y) L(x,y) 表示图像的拉普拉斯算子。拉普拉斯算子是一个二阶导数算子,它可以检测图像中的边缘。

  • 优点
    • 能够有效检测边缘位置。
    • 对噪声较为敏感。
    • 能够检测出图像中的细节。
  • 缺点
    • 计算复杂,速度慢。
    • 对噪声较为敏感。

  常见的边缘检测算法包括Sobel算子、Prewitt算子、Canny算子等。

3 传统算法

3.1 Sobel算子

  Sobel 算子通过计算图像在水平和垂直方向上的梯度来寻找图像中的边缘。 梯度代表了图像中亮度变化的强度和方向,边缘通常对应于梯度较大的地方。Sobel 算子使用两个 3x3 的卷积核,分别用于计算水平方向 (Gx) 和垂直方向 (Gy) 的梯度。 这两个卷积核如下:

  • 水平方向 (Gx):
[-1 0 1-2 0 2-1 0 1]
  • 垂直方向 (Gy):
[-1 -2 -10  0  01  2  1]

  Sobel算子的特点:

  • 简单易实现: Sobel 算子的计算过程相对简单,容易在各种图像处理平台上实现。
  • 考虑了像素距离的影响: Sobel 算子在计算梯度时,对中心像素周围的像素赋予了不同的权重,更靠近中心像素的权重更高,这使得 Sobel 算子对噪声具有一定的抑制作用。
  • 对噪声敏感: 虽然 Sobel 算子具有一定的抗噪能力,但仍然对噪声比较敏感。 在处理噪声较大的图像时,通常需要先进行平滑处理,例如使用高斯滤波器。
  • 能够检测水平和垂直方向的边缘: Sobel 算子能够同时检测图像中水平和垂直方向的边缘。
  • 计算量相对较小: 相对于其他一些更复杂的边缘检测算法,Sobel 算子的计算量较小,适合对实时性要求较高的应用。
import cv2
import numpy as np# 读取图像 (以灰度模式)
img = cv2.imread('source.jpg', cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (720, 480))
cv2.imwrite('source.jpg', img)
# 使用 Sobel 算子计算梯度
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) # 水平方向
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) # 垂直方向# 计算梯度幅值
sobel = np.sqrt(sobelx**2 + sobely**2)
sobel = np.uint8(sobel) # 转换为 8 位无符号整数# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Sobel', sobel)
cv2.imwrite('sobel.jpg', sobel)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.2 Roberts 算子

  Roberts 算子是一种非常简单且古老的边缘检测算子。 它的核心思想是利用局部差分来近似图像的梯度,从而检测图像中的边缘。Roberts 算子使用两个 2x2 的卷积核,分别计算图像在对角线方向上的梯度。 这两个卷积核如下:

Gx:
[1  0;0 -1]
Gy:
[0  1;-1 0]
  • 卷积: 将图像分别与 Gx 和 Gy 卷积核进行卷积运算。 卷积运算的目的是计算图像中每个 2x2 区域在对角线方向上的梯度值。
  • 梯度幅值: 计算每个像素点的梯度幅值 (Magnitude)。 梯度幅值表示该像素点处亮度变化的强度。

  Roberts算子的特点:

  • 计算简单: Roberts 算子的计算过程非常简单,只需要几个加减运算即可。
  • 对噪声非常敏感: 由于 Roberts 算子只使用了 2x2 的卷积核,它对噪声非常敏感。 图像中的任何微小噪声都可能导致梯度值的剧烈变化,从而被误认为是边缘。
  • 定位精度较高: 由于 Roberts 算子使用了较小的卷积核,因此其边缘定位精度相对较高。
    无法检测水平和垂直方向的边缘: Roberts 算子只能检测对角线方向的边缘,无法检测水平和垂直方向的边缘。
  • 不常用: 由于其对噪声过于敏感,且无法检测所有方向的边缘,因此在实际应用中,Roberts 算子并不常用。 通常会选择更鲁棒的边缘检测算子,例如 Sobel 算子或 Canny 算法。
import numpy as np
import cv2def roberts(img):"""使用 Roberts 算子进行边缘检测。Args:img: 输入图像 (灰度图像).Returns:边缘检测后的图像."""# Roberts 算子卷积核kernelx = np.array([[1, 0], [0, -1]])kernely = np.array([[0, 1], [-1, 0]])# 获取图像尺寸height, width = img.shape# 创建输出图像roberts_img = np.zeros((height, width), dtype=np.uint8)# 遍历图像像素for x in range(height - 1):for y in range(width - 1):# 提取 2x2 区域block = img[x:x+2, y:y+2]# 计算梯度gx = np.sum(block * kernelx)gy = np.sum(block * kernely)# 计算梯度幅值magnitude = np.sqrt(gx**2 + gy**2)# 将梯度幅值赋值给输出图像roberts_img[x, y] = magnitudereturn roberts_img# 读取图像 (以灰度模式)
img = cv2.imread('imgs/source.jpg', cv2.IMREAD_GRAYSCALE)# 应用 Roberts 算子
roberts_img = roberts(img)# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Roberts', roberts_img)
cv2.destroyAllWindows()
cv2.imwrite('imgs/roberts.jpg', roberts_img)

  Roberts 算子只适用于以下情况:

  • 图像噪声非常小: 如果图像噪声非常小,可以使用 Roberts 算子进行简单的边缘检测。
  • 对计算速度要求极高: 如果对计算速度要求极高,且可以容忍一定的误差,可以使用 Roberts 算子。
  • 需要检测对角线方向的边缘: 如果只需要检测对角线方向的边缘,可以使用 Roberts 算子。

3.3 Prewitt 算子

  Prewitt 算子是一种用于图像边缘检测的离散微分算子。 它和 Sobel 算子类似,都是通过计算图像在水平和垂直方向上的梯度来检测边缘。 但是,Prewitt 算子使用的卷积核与 Sobel 算子略有不同。Prewitt 算子使用两个 3x3 的卷积核,分别用于计算水平方向 (Gx) 和垂直方向 (Gy) 的梯度。 这两个卷积核如下:

Gx:
[-1 0 1;-1 0 1;-1 0 1]
Gy:
[-1 -1 -1;0  0  0;1  1  1]

  Prewitt算子特点:

  • 简单易实现: Prewitt 算子的计算过程相对简单,容易在各种图像处理平台上实现。
  • 对噪声敏感: Prewitt 算子对噪声比较敏感。 在处理噪声较大的图像时,通常需要先进行平滑处理,例如使用高斯滤波器。
  • 能够检测水平和垂直方向的边缘: Prewitt 算子能够同时检测图像中水平和垂直方向的边缘。
  • 计算量相对较小: 相对于其他一些更复杂的边缘检测算法,Prewitt 算子的计算量较小,适合对实时性要求较高的应用。
  • 权重相同: Prewitt 算子在计算梯度时,对中心像素周围的上下或左右像素赋予了相同的权重。 这与 Sobel 算子不同,Sobel 算子对更靠近中心像素的像素赋予了更高的权重。
      与 Sobel 算子的比较:Prewitt 算子和 Sobel 算子都是常用的梯度算子,它们的主要区别在于卷积核的权重分配不同。
  • Sobel 算子: 对中心像素周围的像素赋予了不同的权重,更靠近中心像素的权重更高。 这种权重分配使得 Sobel 算子对噪声的抑制能力更强。
  • Prewitt 算子: 对中心像素周围的像素赋予了相同的权重。
      一般来说,Sobel 算子的效果比 Prewitt 算子略好,因为 Sobel 算子考虑了像素距离的影响,对噪声的抑制能力更强。
import cv2
import numpy as npdef prewitt(img):"""使用 Prewitt 算子进行边缘检测。Args:img: 输入图像 (灰度图像).Returns:边缘检测后的图像."""# Prewitt 算子卷积核kernelx = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])kernely = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]])# 使用 filter2D 函数进行卷积prewittx = cv2.filter2D(img, cv2.CV_64F, kernelx)prewitty = cv2.filter2D(img, cv2.CV_64F, kernely)# 计算梯度幅值prewitt = np.sqrt(prewittx**2 + prewitty**2)prewitt = np.uint8(prewitt)return prewitt# 读取图像 (以灰度模式)
img = cv2.imread('imgs/source.jpg', cv2.IMREAD_GRAYSCALE)# 应用 Prewitt 算子
prewitt_img = prewitt(img)# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Prewitt', prewitt_img)
cv2.destroyAllWindows()
cv2.imwrite('imgs/prewitt.jpg', prewitt_img)

  Prewitt 算子适用于以下情况:

  • 需要快速进行边缘检测: Prewitt 算子的计算量较小,适合对实时性要求较高的应用。
  • 图像噪声较小: 如果图像噪声较小,可以使用 Prewitt 算子进行边缘检测。
  • 对边缘检测精度要求不高: 如果对边缘检测精度要求不高,可以使用 Prewitt 算子。

3.4 拉普拉斯算子

  普拉斯算子计算的是图像的二阶导数,这使得它对图像中的细节更加敏感。拉普拉斯算子计算的是图像的标量场的散度(divergence)的梯度(gradient)。 在二维图像中,拉普拉斯算子可以表示为:
∇ 2 f = ∂ 2 f / ∂ x 2 + ∂ 2 f / ∂ y 2 ∇²f = ∂²f/∂x² + ∂²f/∂y² 2f=2f/x2+2f/y2
  其中, ∇ 2 ∇² 2 是拉普拉斯算子的符号。 f ( x , y ) f(x, y) f(x,y) 是图像在 ( x , y ) (x, y) (x,y) 处的像素值。 ∂ 2 f / ∂ x 2 ∂²f/∂x² 2f/x2 f ( x , y ) f(x, y) f(x,y) x x x 的二阶偏导数。 ∂ 2 f / ∂ y 2 ∂²f/∂y² 2f/y2 f ( x , y ) f(x, y) f(x,y) y y y 的二阶偏导数。在离散图像中,拉普拉斯算子可以使用卷积核来近似。 常用的拉普拉斯算子卷积核如下:

  • 标准形式:
[0  1  0;1 -4  1;0  1  0]
  • 对角线形式:
[1  1  1;1 -8  1;1  1  1]

  拉普拉斯算子的特点:

  • 各向同性: 拉普拉斯算子是各向同性算子,即对图像旋转不敏感。 无论图像如何旋转,拉普拉斯算子都能检测到相同的边缘。
  • 对噪声敏感: 拉普拉斯算子对噪声非常敏感。 由于拉普拉斯算子计算的是二阶导数,噪声会被放大,导致检测到大量的假边缘。
  • 容易检测到双边缘: 拉普拉斯算子容易检测到双边缘。 这是因为在边缘两侧,拉普拉斯值会发生剧烈的变化,从而产生两个零交叉点。
  • 无法检测边缘方向: 拉普拉斯算子只能检测边缘的位置,无法检测边缘的方向。
  • 常用于与其他方法结合使用: 由于拉普拉斯算子对噪声敏感,且容易检测到双边缘,因此在实际应用中,通常会与其他方法结合使用,例如先进行高斯滤波。
import cv2
import numpy as np# 读取图像 (以灰度模式)
img = cv2.imread('imgs/source.jpg', cv2.IMREAD_GRAYSCALE)# 应用拉普拉斯算子
laplacian = cv2.Laplacian(img, cv2.CV_64F)# 将结果转换为 8 位无符号整数 (取绝对值)
laplacian = np.uint8(np.abs(laplacian))# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Laplacian', laplacian)
cv2.destroyAllWindows()
cv2.imwrite('imgs/lap.jpg', laplacian)

  拉普拉斯算子适用于以下情况:

  • 需要检测各向同性的边缘: 如果需要检测各向同性的边缘,可以使用拉普拉斯算子。
  • 需要增强图像的细节: 拉普拉斯算子可以增强图像的细节,使其更加清晰。
  • 与其他方法结合使用: 拉普拉斯算子通常会与其他方法结合使用,例如先进行高斯滤波,然后再使用拉普拉斯算子进行边缘检测。

3.5 LoG (Laplacian of Gaussian) 算子

  由于拉普拉斯算子对噪声敏感,因此通常会先使用高斯滤波器对图像进行平滑处理,然后再使用拉普拉斯算子进行边缘检测。 这种方法称为 LoG (Laplacian of Gaussian) 算子。

import cv2
import numpy as np# 读取图像 (以灰度模式)
img = cv2.imread('imgs/source.jpg', cv2.IMREAD_GRAYSCALE)# 高斯滤波
gaussian = cv2.GaussianBlur(img, (5, 5), 0)# 应用拉普拉斯算子
laplacian = cv2.Laplacian(gaussian, cv2.CV_64F)# 将结果转换为 8 位无符号整数 (取绝对值)
laplacian = np.uint8(np.abs(laplacian))# 显示结果
cv2.imshow('Original', img)
cv2.imshow('LoG', laplacian)
cv2.destroyAllWindows()
cv2.imwrite('imgs/log.jpg', laplacian)

3.6 DoG (Difference of Gaussians) 算子

  DoG (Difference of Gaussians) 算子的核心思想是用两个不同方差(标准差)的高斯模糊图像的差分来逼近 LoG (Laplacian of Gaussian) 算子。 由于 DoG 算子在计算上比 LoG 算子更有效率,因此在许多应用中被广泛使用。DoG 算子的数学表达式如下:
D o G ( x , y , σ 1 , σ 2 ) = G ( x , y , σ 1 ) − G ( x , y , σ 2 ) DoG(x, y, σ1, σ2) = G(x, y, σ1) - G(x, y, σ2) DoG(x,y,σ1,σ2)=G(x,y,σ1)G(x,y,σ2)

  其中, D o G ( x , y , σ 1 , σ 2 ) DoG(x, y, σ1, σ2) DoG(x,y,σ1,σ2) 是DoG算子在 $(x, y) 处的输出值。 处的输出值。 处的输出值。G(x, y, σ)$是高斯模糊函数,定义为:
G ( x , y , σ ) = ( 1 / ( 2 π σ 2 ) ) ∗ e x p ( − ( x 2 + y 2 ) / ( 2 σ 2 ) ) G(x, y, σ) = (1 / (2πσ²)) * exp(-(x² + y²) / (2σ²)) G(x,y,σ)=(1/(2πσ2))exp((x2+y2)/(2σ2))

   σ 1 σ1 σ1 σ 2 σ2 σ2 是两个不同方差(标准差)的高斯模糊函数的参数。 通常, σ 2 σ2 σ2 > σ 1 σ1 σ1。DoG 算子可以用来近似 LoG 算子。 理论证明,当 σ 2 = k σ 1 σ2 = kσ1 σ2=1,且 k 接近于 1 时,DoG 算子可以很好地逼近 LoG 算子:
D o G ≈ ( k − 1 ) σ 2 ∇ 2 G DoG ≈ (k - 1)σ² ∇²G DoG(k1)σ22G
  其中, ∇ 2 G ∇²G 2G是 LoG 算子。计算过程:

  • 高斯模糊: 使用两个不同方差(σ1 和 σ2)的高斯滤波器对图像进行模糊处理,得到两个模糊图像。
  • 差分: 将两个模糊图像相减,得到 DoG 图像。
  • 零交叉点检测 (可选): 可以通过检测 DoG 图像中的零交叉点来确定边缘的位置。

  DoG算子的特点:

  • 计算效率高: DoG 算子的计算效率比 LoG 算子更高。 这是因为 DoG 算子只需要进行两次高斯模糊和一次减法运算,而 LoG 算子需要计算二阶导数。
  • 尺度空间分析: DoG 算子可以用于尺度空间分析。 通过改变高斯滤波器的方差,可以检测到不同尺度的特征。
  • 边缘检测: DoG 算子可以用于边缘检测。 DoG 图像中的零交叉点对应于图像中的边缘。
import cv2
import numpy as npdef dog(img, sigma1, sigma2):"""使用 DoG 算子进行图像增强和边缘检测。Args:img: 输入图像 (灰度图像).sigma1: 第一个高斯滤波器的标准差.sigma2: 第二个高斯滤波器的标准差.Returns:DoG 图像."""# 高斯模糊gaussian1 = cv2.GaussianBlur(img, (0, 0), sigma1)gaussian2 = cv2.GaussianBlur(img, (0, 0), sigma2)# 差分dog_img = gaussian1 - gaussian2return dog_img# 读取图像 (以灰度模式)
img = cv2.imread('imgs/source.jpg', cv2.IMREAD_GRAYSCALE)# 应用 DoG 算子
dog_img = dog(img, 1, 2)# 显示结果
cv2.imshow('Original', img)
cv2.imshow('DoG', dog_img)
cv2.imwrite('imgs/dog.jpg', dog_img)
cv2.destroyAllWindows()

  DoG 算子适用于以下情况:

  • 需要快速进行边缘检测: DoG 算子的计算效率高,适合对实时性要求较高的应用。
  • 需要进行尺度空间分析: DoG 算子可以用于尺度空间分析,检测不同尺度的特征。
  • 需要近似 LoG 算子: DoG 算子可以很好地逼近 LoG 算子。

3.7 Canny算子

  Canny 算子是一种被广泛认为是最优的边缘检测算法之一。 它由 John Canny 在 1986 年开发,旨在提供清晰、准确的边缘检测结果。 Canny 算子不仅能检测到图像中真实的边缘,还能最大限度地减少噪声的影响,并提供精确的边缘定位。
  Canny 边缘检测算法是一个多步骤的过程,主要包括以下几个步骤:

  • 高斯滤波 (Gaussian Filter):
    • 目的: 降低图像噪声的影响。 噪声会影响边缘检测的准确性,因此首先需要对图像进行平滑处理。
    • 方法: 使用高斯滤波器对图像进行卷积。 高斯滤波器是一种线性平滑滤波器,它可以有效地抑制高频噪声。
    • 参数: 高斯滤波器的标准差 (σ) 是一个重要的参数,它决定了滤波器的平滑程度。 较大的 σ 值会导致更强的平滑效果,但也可能模糊图像中的细节。
  • 计算梯度幅值和方向 (Gradient Calculation):
    • 目的: 检测图像中的边缘。 边缘通常对应于图像中亮度变化剧烈的地方,即梯度较大的地方。
    • 方法: 使用 Sobel 算子或其他梯度算子计算图像在水平和垂直方向上的梯度 (Gx 和 Gy)。 然后,计算梯度幅值 (G) 和方向 (θ):
      • 梯度幅值: G = sqrt(Gx^2 + Gy^2)
      • 梯度方向: θ = arctan(Gy / Gx)
      • 梯度方向量化: 将梯度方向量化为四个方向之一:0°, 45°, 90°, 135°。 这是为了方便后续的非极大值抑制。
  • 非极大值抑制 (Non-Maximum Suppression - NMS):
    • 目的: 细化边缘,消除梯度方向上的非最大值,只保留最强的边缘像素。
    • 方法: 遍历图像中的每个像素,如果该像素的梯度幅值在其梯度方向上不是局部最大值,则将其梯度幅值设置为 0。
    • 步骤:
      • 对于每个像素,比较其梯度幅值与其梯度方向上的两个相邻像素的梯度幅值。
      • 如果该像素的梯度幅值不是局部最大值,则将其梯度幅值设置为 0。
  • 双阈值处理 (Double Threshold):
    • 目的: 将像素分为三类:强边缘像素、弱边缘像素和非边缘像素。
    • 方法: 使用两个阈值:高阈值 (highThreshold) 和低阈值 (lowThreshold)。
      • 如果像素的梯度幅值大于高阈值,则将其标记为强边缘像素。
      • 如果像素的梯度幅值小于低阈值,则将其标记为非边缘像素。
      • 如果像素的梯度幅值介于高阈值和低阈值之间,则将其标记为弱边缘像素。
  • 边缘连接 (Edge Tracking by Hysteresis):
    • 目的: 连接弱边缘像素,形成完整的边缘。
    • 方法: 遍历图像中的每个弱边缘像素。 如果该弱边缘像素的周围 8 个像素中存在强边缘像素,则将其标记为边缘像素。 否则,将其标记为非边缘像素。
    • 滞后阈值处理: 这种边缘连接方法称为滞后阈值处理,它可以有效地连接边缘,并减少噪声的影响。

   Canny 算子的特点包括:

  • 优秀的边缘检测效果: Canny 算子能够检测到清晰、准确的边缘。
  • 抗噪能力强: Canny 算子首先使用高斯滤波器降低噪声,然后使用非极大值抑制和双阈值处理进一步抑制噪声。
  • 精确的边缘定位: Canny 算子使用非极大值抑制细化边缘,从而提供精确的边缘定位。
  • 可调节的参数: Canny 算子有多个可调节的参数,例如高斯滤波器的标准差、高阈值和低阈值。 可以根据具体的应用场景调整这些参数,以获得最佳的边缘检测效果。
  • 计算复杂度较高: Canny 算子的计算复杂度相对较高,但由于其优秀的边缘检测效果,仍然被广泛应用于各种图像处理和计算机视觉应用中。
import cv2
import numpy as np# 读取图像 (以灰度模式)
img = cv2.imread('imgs/source.jpg', cv2.IMREAD_GRAYSCALE)# 应用 Canny 算子
edges = cv2.Canny(img, 100, 200)# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Canny', edges)
cv2.destroyAllWindows()
cv2.imwrite('imgs/canny.jpg', edges)

  Canny 算子适用于各种需要高质量边缘检测的场景,例如:

  • 图像分割: 通过检测图像中的边缘,可以将图像分割成不同的区域。
  • 目标检测: 边缘可以作为图像的特征,用于目标检测。
  • 图像识别: 边缘可以作为图像的特征,用于图像识别。
  • 医学图像分析: Canny 算子可以用于医学图像的边缘检测,例如肿瘤的边缘检测。
  • 自动驾驶: Canny 算子可以用于自动驾驶系统中,检测道路和车辆的边缘。

3.8 罗盘算子

  罗盘算子 (Compass Operator)通过使用一组预定义的卷积核来检测特定方向上的边缘。 与 Sobel 或 Prewitt 等算子不同,罗盘算子不是简单地计算水平和垂直梯度,而是计算多个方向上的梯度响应,从而能够更精确地检测具有特定方向的边缘。罗盘算子的核心思想是使用一组卷积核,每个卷积核对应一个特定的方向(例如,北、东北、东、东南等)。 将图像与每个卷积核进行卷积,得到该方向上的梯度响应。 然后,选择具有最大梯度响应的方向作为该像素点的边缘方向。

  常见的罗盘算子:

  • Kirsch 算子: 使用 8 个卷积核,分别对应 8 个方向(0°, 45°, 90°, 135°, 180°, 225°, 270°, 315°)。
  • Robinson 算子: 类似于 Kirsch 算子,也使用 8 个卷积核,但卷积核的系数略有不同。

  Kirsch 算子使用 8 个 3x3 的卷积核,每个卷积核对应一个方向。 这些卷积核如下:

N (北):
[-3 -3  5;-3  0  5;-3 -3  5]NE (东北):
[-3  5  5;-3  0  5;-3 -3 -3]E (东):
[ 5  5  5;-3  0 -3;-3 -3 -3]SE (东南):
[ 5  5 -3;5  0 -3;-3 -3 -3]S (南):
[ 5 -3 -3;5  0 -3;5 -3 -3]SW (西南):
[-3 -3 -3;5  0 -3;5  5 -3]W (西):
[-3 -3 -3;-3  0  5;-3  5  5]NW (西北):
[-3 -3 -3;-3  0 -3;5  5  5]

  计算过程:

  • 卷积: 将图像与每个卷积核进行卷积运算,得到 8 个方向上的梯度响应。
  • 最大响应: 对于每个像素点,选择 8 个梯度响应中的最大值作为该像素点的梯度幅值。
  • 边缘方向: 记录具有最大梯度响应的卷积核对应的方向作为该像素点的边缘方向。

  罗盘算子的特点:

  • 能够检测特定方向的边缘: 罗盘算子能够检测具有特定方向的边缘,这使得它在某些应用中比其他边缘检测算子更有效。
  • 对噪声敏感: 类似于其他梯度算子,罗盘算子也对噪声比较敏感。
  • 计算量较大: 由于需要进行多次卷积运算,罗盘算子的计算量相对较大。
import cv2
import numpy as npdef kirsch(img):"""使用 Kirsch 算子进行边缘检测。Args:img: 输入图像 (灰度图像).Returns:边缘检测后的图像和边缘方向图像."""# Kirsch 算子卷积核kernels = [np.array([[-3, -3, 5], [-3, 0, 5], [-3, -3, 5]]),  # Nnp.array([[-3, 5, 5], [-3, 0, 5], [-3, -3, -3]]),  # NEnp.array([[5, 5, 5], [-3, 0, -3], [-3, -3, -3]]),  # Enp.array([[5, 5, -3], [5, 0, -3], [-3, -3, -3]]),  # SEnp.array([[5, -3, -3], [5, 0, -3], [5, -3, -3]]),  # Snp.array([[-3, -3, -3], [5, 0, -3], [5, 5, -3]]),  # SWnp.array([[-3, -3, -3], [-3, 0, 5], [-3, 5, 5]]),  # Wnp.array([[-3, -3, -3], [-3, 0, -3], [5, 5, 5]])   # NW]# 获取图像尺寸height, width = img.shape# 创建输出图像magnitude = np.zeros((height, width), dtype=np.uint8)direction = np.zeros((height, width), dtype=np.uint8)# 遍历图像像素for x in range(1, height - 1):for y in range(1, width - 1):# 提取 3x3 区域block = img[x-1:x+2, y-1:y+2]# 计算每个方向上的梯度响应responses = [np.sum(block * kernel) for kernel in kernels]# 找到最大响应和对应的方向max_response = np.max(responses)max_index = np.argmax(responses)# 赋值给输出图像magnitude[x, y] = max_responsedirection[x, y] = max_index * 45  # 将索引转换为角度return magnitude, direction# 读取图像 (以灰度模式)
img = cv2.imread('imgs/source.jpg', cv2.IMREAD_GRAYSCALE)# 应用 Kirsch 算子
magnitude, direction = kirsch(img)# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Kirsch Magnitude', magnitude)
cv2.imshow('Kirsch Direction', direction)
cv2.imwrite('imgs/kirsch_magnitude.jpg', magnitude)
cv2.destroyAllWindows()

  罗盘算子适用于以下情况:

  • 需要检测特定方向的边缘: 例如,在检测建筑物或道路的边缘时,可以使用罗盘算子来检测特定方向的直线。
  • 需要获取边缘方向信息: 罗盘算子可以提供边缘的方向信息,这对于某些应用非常有用。

4 深度学习边缘检测

  除了传统的边缘检测算子,深度学习也可以用于边缘检测。 深度学习方法通常使用卷积神经网络 (CNN) 来学习图像中的边缘特征。 这些 CNN 可以通过大量的训练数据来学习图像中的边缘特征。 然后,这些 CNN 可以用于边缘检测。相较于传统的基于梯度或手工设计的算子,深度学习方法能够学习更复杂的图像特征,从而实现更准确、更鲁棒的边缘检测。

  深度学习边缘检测的步骤:

  • 数据准备: 收集大量的图像数据,并将其标记为边缘或非边缘。
  • 模型训练: 使用 CNN 来训练模型。 通常,CNN 由多个卷积层、池化层和全连接层组成。 这些层可以学习图像中的边缘特征。
  • 边缘检测: 使用训练好的模型来检测图像中的边缘。

  深度学习边缘检测的优点:

  • 能够学习更复杂的图像特征: 深度学习方法可以学习更复杂的图像特征,从而实现更准确的边缘检测。
  • 能够处理复杂的图像: 深度学习方法可以处理复杂的图像,例如具有复杂背景的图像。

  深度学习边缘检测的缺点:

  • 计算量较大: 深度学习方法需要大量的计算资源,尤其是在处理大规模图像时。
  • 训练数据量较大: 深度学习方法需要大量的训练数据,这需要大量的时间和计算资源。

  深度学习边缘检测算法比较多,常见的有U-Net,Faster R-CNN,YOLO等。这里只简单较少其中的HED。HED 的核心思想是利用深度卷积神经网络学习图像的多尺度特征表示,并在网络的多个层次上进行边缘预测。 通过将这些不同尺度的预测结果融合起来,HED 能够有效地利用图像的上下文信息,从而提高边缘检测的准确性。HED 的网络结构基于 VGG16 网络,并进行了一些修改,使其更适合边缘检测任务。 主要的修改包括:在 VGG16 网络的每个卷积块 (convolutional block) 之后添加一个侧边输出 (side output)。 每个侧边输出都连接到一个卷积层,用于预测该尺度下的边缘图。将所有侧边输出的预测结果融合起来,得到最终的边缘图。
  HED 使用加权交叉熵损失函数 (weighted cross-entropy loss) 来训练网络。 加权交叉熵损失函数可以有效地解决类别不平衡问题,即边缘像素数量远小于非边缘像素数量。损失函数定义如下:
L o s s = Σ ( β ∗ y i ∗ l o g ( p i ) + ( 1 − β ) ∗ ( 1 − y i ) ∗ l o g ( 1 − p i ) ) Loss = Σ (β * y_i * log(p_i) + (1 - β) * (1 - y_i) * log(1 - p_i)) Loss=Σ(βyilog(pi)+(1β)(1yi)log(1pi))
其中:

  • y i y_i yi 是像素 i 的真实标签 (0 或 1)。
  • p i p_i pi 是网络预测的像素 i 为边缘的概率。
  • β β β 是一个权重,用于平衡边缘像素和非边缘像素的损失。 通常,β 设置为边缘像素数量与非边缘像素数量的比值。
      HED 的总损失函数是所有侧边输出层损失函数和融合层损失函数的加权和:
    T o t a l L o s s = Σ w m ∗ L o s s m + w f u s e ∗ L o s s f u s e Total Loss = Σ w_m * Loss_m + w_fuse * Loss_fuse TotalLoss=ΣwmLossm+wfuseLossfuse
    其中:
  • L o s s m Loss_m Lossm 是第 m 个侧边输出层的损失函数。
  • L o s s f u s e Loss_fuse Lossfuse 是融合层的损失函数。
  • w m w_m wm w f u s e w_fuse wfuse 是权重,用于平衡不同层次的损失。

5 参考文献

  • 边缘检测
  • HED
  • Github-HED
  • 基于深度学习的图像边缘和轮廓提取方法介绍

相关文章:

图像处理——边缘检测

1 概述 边缘检测是图像处理和计算机视觉中的一项基本技术,用于识别图像中亮度变化剧烈的像素点,这些像素点通常对应于物体的边界。它通过检测图像中亮度或颜色变化显著的区域,提取出物体的轮廓,常用于计算机视觉、图像处理和模式识…...

认识哈希以及哈希表的模拟实现

文章目录 1.什么是哈希2.哈希函数2.1 除留余数法/除法散列法2.2 乘法散列法2.3 全域散列法 3.哈希冲突4.解决哈希冲突的方法4.1 开放定址法4.1.1 用除留余数法和线性探测模拟实现简单的哈希表 4.2 链地址法4.2.1 用除留余数法和链地址法模拟实现简单的哈希表 1.什么是哈希 概念…...

【Castle-X机器人】二、智能导览模块安装与调试

持续更新。。。。。。。。。。。。。。。 【Castle-X机器人】智能导览模块安装与调试 二、智能导览模块安装与调试2.1 智能导览模块安装2.2 智能导览模块调试2.2.1 红外测温传感器测试2.2.2 2D摄像头测试 二、智能导览模块安装与调试 2.1 智能导览模块安装 使用相应工具将智能…...

硬件须知的基本问题2

目录 1、典型电路 1. DC5V 转 DC3.3V 电路 2. 通信电路 2、STM32F103RCT6 最小系统如何设计搭建电路 1. 电源电路 2. 复位电路 3. 时钟电路 4. 下载电路 5. 单片机连接连接 3、请列举你所知道的二极管型号? 1. 整流二极管 2. 小信号二极管 3. 肖特基二极管 4. 超…...

Dify 使用 excel 或者 csv 文件创建知识库

Dify 使用 excel 或者 csv 文件创建知识库 1. 创建知识库2. 创建聊天助手3. 其他 1. 创建知识库 创建知识库,导入excel/csv文件, 文件内容, 单击 “预览块”,可以确认会生成多个键值对的块, 配置 Embedding 模型和检索…...

深入理解二叉树遍历:递归与栈的双重视角

二叉树的遍历前序遍历中序遍历后续遍历总结 二叉树的遍历 虽然用递归的方法遍历二叉树实现起来更简单,但是要想深入理解二叉树的遍历,我们还必须要掌握用栈遍历二叉树,递归其实就是利用了系统栈去遍历。特此记录一下如何用双重视角去看待二叉…...

通过gap看margin和padding在布局中的应用

在CSS布局中,控制元素之间的间距有多种方式:margin、padding,还有新晋的gap属性。虽然选择多了,但这也带来了不少头疼的问题。比如,你的自定义组件到底该不该加margin?如果加了,那在使用这个组件…...

图像畸变-径向切向畸变实时图像RTSP推流

实验环境 注意:ffmpeg进程stdin写入两张图片的时间间隔不能太长,否则mediamtx会出现对应的推流session超时退出。 实验效果 全部代码 my_util.py #进度条 import os import sys import time import shutil import logging import time from datetime i…...

2025最新Facefusion3.1.2使用Docker部署,保姆级教程,无需配置环境

Docker部署Facefusion 环境 windows10 Facefusion3.1.2 安装 拉取源代码 git clone https://github.com/facefusion/facefusion-docker.git 此处如果拉不下来,需要科学上网,不会的可以找我。 运行容器 将Dockerfile.cpu文件中的的From python:3.…...

区块链实战:Hyperledger Fabric多节点网络部署与高性能业务链码

一、联盟链架构设计与技术选型 1.1 架构设计原则 联盟链采用​​分层架构​​,包含应用层、共识层、网络层和数据层: ​​应用层​​:提供用户接口(Web/API)和智能合约交互入口​​共识层​​:采用PBFT或…...

C++学习笔记(四十)——STL之归约算法

STL 算法分类: 类别常见算法作用排序sort、stable_sort、partial_sort、nth_element等排序搜索find、find_if、count、count_if、binary_search等查找元素修改copy、replace、replace_if、swap、fill等修改容器内容删除remove、remove_if、unique等删除元素归约for…...

docker容器运维工具——ctop

概述 Github主页:https://github.com/bcicen/ctop 当服务器上运行多个容器时,迅速查看所有容器运行情况及指标将会大为提高工作效率。ctop工具可以像top命令一样,对所有容器进行总览,并实现简单的操作。 部署 下载(…...

RAG vs 微调:大模型知识更新的最优解之争

一、技术本质:知识注入的两条路径 在大模型应用落地的实践中,RAG(检索增强生成)与微调(Fine-tuning)已成为知识更新的两大核心技术路径。二者的本质差异在于是否对模型参数进行修改: 维度RAG微…...

FPGA前瞻篇-组合逻辑电路设计-多路复用器

多路选择器(MUX)简介 基本概念 多路选择器(MUX,Multiplexer)是一种多输入、单输出的组合逻辑电路。 它通过选择控制信号,在多个输入信号中选择一个连接到输出端。 可以理解为一个多路数字开关。 &…...

Day13(前缀和)——LeetCode2845.统计趣味子数组的数目

1 题目描述 给定一个下标从0开始的数组nums,以及整数modulo和k。找出并统计数组中趣味子数组的数目: 在范围[l,r]内,设cnt为满足nums[i]%modulok的索引i的数量,并且cnt%modulok。子数组是数组中的一个连续非空的元素序列。 其中一…...

WebcamJS中文文档

文章目录 WebcamJS针对Chrome 47及以上版本的重要说明浏览器支持演示示例开源协议快速入门指南配置初始化拍摄照片自定义图像大小裁剪图像翻转图像(镜像模式)冻结/预览图像设置备用SWF文件位置重置(关闭)API 参考自定义事件向服务器提交图像跟踪上传进度包含在现有表单中自…...

论文笔记(八十)π0.5: a Vision-Language-Action Model with Open-World Generalization

π0.5: a Vision-Language-Action Model with Open-World Generalization 文章概括摘要I. 引言II. 相关工作通用机器人操作策略。非机器人数据的协同训练。使用语言进行机器人推理和规划。具有开放世界泛化能力的机器人学习系统。 III. 序言IV. π 0.5 π_{0.5} π0.5​ 模型与…...

pymongo功能整理与基础操作类

以下是 Python 与 PyMongo 的完整功能整理,涵盖基础操作、高级功能、性能优化及常见应用场景: 1. 安装与连接 (1) 安装 PyMongo pip install pymongo(2) 连接 MongoDB from pymongo import MongoClient# 基础连接(默认本地,端口…...

硬件须知的基本问题1

目录 1. 电路表示中的电压源表示符号有哪些? 2.查找电路表示中的电流源表示符号有哪些? 3.上拉电阻和下拉电阻的作用是什么? 4.0 欧姆电阻在电路中有什么作用? 5.电容的耦合…...

LangChain 中的 Task(任务) 主要通过 生成器(Generator) 实现,而非传统的迭代器(Iterator)

LangChain 中的 Task(任务) 主要通过 生成器(Generator) 实现,而非传统的迭代器(Iterator)。以下是关键分析: 任务链的流程控制 LangChain 的 链式结构(Chains&#xff0…...

加里·基尔代尔:CP/M之父与个人计算时代的先驱

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 加里基尔代尔:CP/M之父与个人计算时代的先驱 一、早年生活与教育背景 1.…...

深入解析Spring Boot配置处理器:机制、架构与实践

深入解析Spring Boot配置处理器:机制、架构与实践 Spring Boot的配置处理器(spring-boot-configuration-processor)是支撑其智能配置体验的关键组件。本文结合实际开发需求,从使用方式、底层原理到性能优化与架构设计&#xff0c…...

Ragflow新建的知识库完成后刷新却没有显示,报错MethodNotAllowed: 405 Method Not Allowed:

环境: Ragflow17.2 debian12.8 问题描述: Ragflow新建的知识库完成后刷新却没有显示,报错MethodNotAllowed: 405 Method Not Allowed: The method is not allowed for the requested URL. 后台日志: 2025-04-25 13:54:25,988 ERROR 235204 405 Method Not Allowed:…...

Maven进阶知识

一、Maven 坐标 (一)概念 在 Maven 中坐标是构件的唯一标识,其元素包括 groupId、artifactId、version、packaging、classifier。其中 groupId、artifactId、version 是必定义项,packaging 默认为 jar。 (二&#x…...

通过门店销售明细表用SQL得到每月每个门店的销冠和按月的同比环比数据

假设我在Snowflake里有销售表,包含ID主键、门店ID、日期、销售员姓名和销售额,需要统计出每个月所有门店和各门店销售额最高的人,不一定是一个人,以及他所在的门店ID和月总销售额。 统计每个月份下,各门店内销售额最高…...

聊聊Spring AI Alibaba的YuQueDocumentReader

序 本文主要研究一下Spring AI Alibaba的YuQueDocumentReader YuQueDocumentReader community/document-readers/spring-ai-alibaba-starter-document-reader-yuque/src/main/java/com/alibaba/cloud/ai/reader/yuque/YuQueDocumentReader.java public class YuQueDocument…...

Tauri文件系统操作:桌面应用的核心能力(入门系列四)

今天我们来聊聊Tauri中一个超级重要的功能 - 文件系统操作。这可是Web应用和桌面应用最大的区别之一。在浏览器里,出于安全考虑,我们对文件系统的访问被限制得死死的。但在Tauri桌面应用中,我们可以安全地访问用户的文件系统,这简…...

网络流之最大流(Dinic)

正文 在了解了Ford-Fulkerson 和Edmonds-Karp之后,我们可以进一步学习更高效的算法——Dinic。 Dinic算法的时间复杂度是O(VE),实际运用过程中是比EK算法快的。 特性Ford-FulkersonEdmonds-Karp (EK)Dinic 增广路径选择 任意方式BFS找最短路径分层图多…...

LVGL模拟器:NXP GUIDER+VSCODE

1. 下载安装包 NXP GUIDER:GUI Guider | NXP 半导体 CMAKE:Download CMake MINGW:https://github.com/niXman/mingw-builds-binaries/releases SDL2:https://github.com/libsdl-org/SDL/releases/tag/release-2.30.8 VSCODE&…...

魔幻预言手游》:职业介绍!

在《魔幻预言》手游中,共有武玄、魔魅、剑仙三大核心职业,各具特色且定位鲜明,以下为具体介绍: 一、武玄(战士) 核心定位:近战物理输出与团队增益担当,兼具控制与防御能力。 战斗风…...

什么时候使用Python 虚拟环境(venv)而不用conda

是的!python3.9 -m venv rtdetr_env 是 Python 原生的虚拟环境(venv),而 conda 是另一个流行的虚拟环境管理工具(来自 Anaconda/Miniconda)。下面我会详细对比两者的区别,并讲解 venv 的基本用法…...

Vue3的内置组件 -实现过渡动画 TransitionGroup

Vue3的内置组件 -实现过渡动画 TransitionGroup 是一个内置组件,用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果 支持和 基本相同的 props、CSS 过渡 class 和 JavaScript 钩子监听器,但有以下几点区别: 默认情况下&…...

水果成篮--LeetCode

题目 你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水…...

ROS 快速入门教程05

15. IMU航向锁定的节点 编写锁定节点 打开vscode编写imu_node.cpp #include<ros/ros.h> #include<sensor_msgs/Imu.h> #include<tf/tf.h> #include<geometry_msgs/Twist.h>ros::Publisher vel_pub;void IMUCallback(sensor_msgs::Imu msg) {if(msg.o…...

用 C 语言实现通用的冒泡排序算法

在日常编程中&#xff0c;排序算法是一个非常常见且重要的工具。虽然有许多排序算法可以选择&#xff0c;但如果你需要一个能够处理不同数据类型的排序算法&#xff0c;如何设计一个通用的排序算法呢&#xff1f;今天我们将实现一个通用的冒泡排序算法&#xff0c;支持不同数据…...

Linux——进程间通信

目录 1. 进程间通信的介绍 1.1 概念 1.2 目的 1.3 进程间通信的本质 1.4 进程间通信的分类 2. 管道 2.1 概念 2.2 匿名管道 2.2.1 原理 2.2.2 pipe函数 2.2.3 匿名管道使用步骤 2.2.4 管道读写规则 2.2.5 管道的特点 2.2.6 管道的四种特殊情况 2.2.7 管道的…...

深入详解人工智能数学基础——微积分中拉格朗日乘数法在GAN训练中的应用

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用…...

精益数据分析(26/126):依据商业模式确定关键指标

精益数据分析&#xff08;26/126&#xff09;&#xff1a;依据商业模式确定关键指标 在创业与数据分析的探索之路上&#xff0c;每一次的学习都像是为前行点亮一盏灯。今天&#xff0c;我们依旧怀揣着共同进步的期望&#xff0c;深入解读《精益数据分析》的相关内容&#xff0…...

前端面试宝典---vue原理

vue的Observer简化版 class Observer {constructor(value) {if (!value || typeof value ! object) returnthis.walk(value) // 对对象的所有属性进行遍历并定义响应式}walk (obj) {Object.keys(obj).forEach(key > defineReactive(obj, key, obj[key]))} } // 定义核心方法…...

Cribl 上传lookup 表,传入数据进event

cribl 插入lookup 表,来数据有针对性的插入字段,对event 的数据进行字段插入。灵活性强。 The Lookup At long last, were ready to configure the lookup. First, lets create the Lookup table wed like to use. Getting the goods 先下载一个lookup 表,然后上传到cri…...

使用 binlog2sql 闪回 MySQL8 数据

【说明】 MySQL服务器版本 8.0.26 mysql> SELECT version(); ----------- | version() | ----------- | 8.0.26 | -----------Python 版本 Python 3.8.10 [infuq ~]# python -V Python 3.8.10【安装】 binlog2sql 官方地址 1.安装 binlog2sql [infuq ~]# git clone …...

蓝桥杯赛场反思:技术与心态的双重修炼

蓝桥杯赛场反思&#xff1a;技术与心态的双重修炼 在刚刚结束的第十六届蓝桥杯大赛软件赛省赛第二场中&#xff0c;我经历了一场充满挑战与自我审视的旅程。走出赛场&#xff0c;内心既有些许成就感&#xff0c;也夹杂着对自身不足的深刻反思。这次比赛不仅是一次技术的较量&a…...

介绍常用的退烧与消炎药

每年春夏交替之季&#xff0c;是感冒发烧、咳嗽、咽喉肿痛、支气管炎、扁桃体炎的高发期。在家里或公司&#xff0c;常备几种预防感冒发烧、咳嗽、流鼻涕、咽喉发炎的药品&#xff0c;是非常必要的。下面介绍几款效果非常明显的中成药、西药&#xff0c;具体如下。 1 莲芝消炎…...

C++篇——继承

目录 引言 1.继承的概念及定义 1_1&#xff0c;继承的概念 1_2&#xff0c; 继承定义 1_2_1&#xff0c;继承关系和访问限定符 1_2_2&#xff0c;继承基类成员访问方式的变化 2.基类和派生类对象赋值转换 3.继承中的作用域 4.派生类的默认成员函数 构造函数 拷贝构造…...

C++ 基础综合练习案例01:联系人管理系统(Part01)

通讯录是一个可以记录亲人、好友信息的工具。 本教程主要利用C来实现一个通讯录管理系统 系统中需要实现的功能如下&#xff1a; * 添加联系人&#xff1a;向通讯录中添加新人&#xff0c;信息包括&#xff08;姓名、性别、年龄、联系电话、家庭住址&#xff09;最多记录1000人…...

Trae 宝藏功能实测:从 Mcp 搭建天气系统,到 AI 重塑 Excel 数据处理

本文 利用trae以及第三方MCP Server搭建一个天气系统网页前言链接高德地图MCP链接quickchart-server MCP Server链接EdgeOne Pages Deploy MCP智能体的创建天气系统效果展示 利用trae做一个Excel格式化工具前言使用trae完成代码的实现总结 我正在参加Trae「超级体验官」创意实践…...

MCP与Sequential Thinking:系统问题的分解与解决之道

MCP与Sequential Thinking:系统问题的分解与解决之道 引言:复杂问题背后的逻辑思维 在面对复杂问题时,我们常常感到手足无措,尤其是在需要将任务分解为多个步骤时。这是对个人思维能力的极大挑战,而掌握有效的思维工具则可以让事情事半功倍。今天我们讨论的两个工具:MC…...

Scrapy爬取动态网页:简洁高效的实战指南

引言 动态网页依赖JavaScript加载,传统爬虫望而却步。Scrapy搭配scrapy-splash却能轻松破局!本文通过一个原创案例,带你用Scrapy和Splash高效爬取动态网页,代码简洁、可运行,从零基础到进阶开发者都能快速上手。无论是数据采集还是自动化任务,这篇指南让你一学即会,开启…...

在 Linux 上安装 PNPM 的教程

在 Linux 上安装 PNPM 的教程 PNPM&#xff08;Performant NPM&#xff09;是一个非常快速的包管理器&#xff0c;作为 npm 的替代品&#xff0c;PNPM 在安装速度和磁盘占用方面都具有显著优势。PNPM 通过“硬链接”共享依赖来节省磁盘空间&#xff0c;并且比 npm 更加高效。本…...

Vue3 组件通信与插槽

Vue3 组件通信方式全解&#xff08;10种方案&#xff09; 一、组件通信方式概览 通信方式适用场景数据流向复杂度Props/自定义事件父子组件简单通信父 ↔ 子⭐v-model 双向绑定父子表单组件父 ↔ 子⭐⭐Provide/Inject跨层级组件通信祖先 → 后代⭐⭐事件总线任意组件间通信任…...