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

计算机视觉cv2入门之边缘检测

检测原理

        边缘检测是指检测图像中的一些像素点,它们周围的像素点的灰度发生了急剧的变化,因此可以将这些像素点作为一个集合,用于标注图像中不同物体的边界。

     边缘是图像上灰度级变化很快的点的集合。这些点的梯度往往很大。因此我们可以使用一阶导数和二阶偏导数来进行求解,但图像是离散的数据并以矩阵的形式存储,并不能像数学理论中对直线或曲线一样求导,所以我们使用差分来近似微分,采用不同的差分模板来对原图像进行卷积运算进而实现对图像求导。

导数算子卷积模板推导

         这里,我们以一阶导数算子Prewitt和二阶导数算子Laplacian的卷积模板为例 进一步推导说明其由来。

我们知道,一个函数的一阶与二阶导数可以表示为:

f'(x)=\lim_{\Delta x\to0}\frac{f(x+\Delta x)-f(x)}{\Delta x}

f'(x)=\lim_{\Delta x\to0}\frac{f(x)-f(x-\Delta x)}{\Delta x}

f''(x)=\lim_{\Delta x\to0}\frac{f'(x+\Delta x)-f'(x)}{\Delta x}

f''(x)=\lim_{\Delta x\to0}\frac{f'(x)-f'(x-\Delta x)}{\Delta x}

那么对于离散的函数,其一阶差分为:

f(x+1)-f(x)  ……(1)

f(x)-f(x-1)  ……(2)

(1)式-(2)式我们可以得到其二阶差分为:

f(x-1)-2f(x)+f(x+1)……(3)

(1)式+(2)式可以得到:

f(x+1)-f(x-1) ……(4)

        这里要注意的是,(4)式并不是标准意义上的一阶差分,不过,其可看做是一种"中心差分"的形式,这里我们也近似把它看做一阶差分。

        实际上,这种中心差分的形式主要是为了和我们图像中最常用的3x3卷积模板相配合使用。

图像坐标系  

Prewitt算子

        prewitt模板分为x与y两个方向。

Prewitt算子在x,y方向上的卷积模板 

这里我们设模板中心点的坐标为(x,y) ,那么其在x方向上的一阶差分利用(4)式可以近似表示为:

提取系数-1,0,1并应用到3x3模板中的每一行便得到了Prewiitt算子在x方向上的卷积模板。

同理,将x变换为y后应用到3x3模板中的每一列便得到了Prewitt算子在y方向上的卷积模板。

Laplacian算子

     Laplacian算子模版同时考虑x与y两个方向

                      图(a)                     图(b)                                 

       

 因此其在差分时是二元差分,我们设3x3卷积模板中心坐标为(x,y),那么在4邻域范围内

对于,其二阶差分结果为:

         提取系数并填入3x3卷积模板中便得到了图(a)所示的Laplacian卷积模板,同时考虑到对角线上的元素,我们也进行二阶差分,然后便得到了如图(b)更通用的Laplacian算子。

        Laplacian卷积模板有个特点是中心处为负,周边为正,且模板内所有元素之和为0。

 常见算子

一阶导数算子

Roberts(重点关注斜对角线)

Prewitt 

Sobel(Prewitt基础上给予中心位置更大权重) 

        对于一阶导数算子而言,我们最后还需要使用不同的范数来计算其在x,y方向上梯度矢量的幅度。一般而言,我们可以使用L2范数,此时幅度值为: 

Magnitude=\sqrt{G_{x}^2+G_{y}^2}  

        其中,G_{x}G_{y}分别为一阶导数算子在x,y方向上的矢量。 

Canny算子 

Canny算子的计算步骤如下:

  1. 用高斯滤波器平滑图像,去除噪声。
  2. 用一阶差分偏导计算梯度方向和幅度(Sobel算子)。
  3. 对梯度值不是极大值的地方进行抑制,将不是机制的点全部置0,去掉大部分的边缘,所以图像边缘会变细。

二阶导数算子

Laplacian算子

Laplacian算子卷积模板 

Mar算子   

        Marr算子通常由两部分组成:一个高斯滤波器用于平滑图像,减少噪声的影响;一个差分算子用于检测亮度变化。在每个像素点上进行如下计算:

  1. 用一个2D的高斯平滑模板与原图像卷积。
  2. 计算卷积后图像的拉普拉斯值。
  3. 检测图像中的过零点,将其作为边缘点。

LOG算子 

        LOG算子的全称是Laplacian of Gaussian,即高斯拉普拉斯算子。它结合了拉普拉斯算子(用于边缘增强)和高斯滤波器(用于去噪的特点)

常用边缘检测算子检测特点比较

cv2实现边缘检测

        注意上述表格中提到的边缘检测算子,只有Sobel,Canny,Laplacian是cv2内置的,其余的算子需要我们手动实现。

        手动实现的原理也很简单,就是我们自己定义卷积核然后使用cv2.filter2D()函数进行卷积。

注意事项:

      上述几种模板的卷积核部分含有负数,读取进来的图像原始数据默认是cv2.CV_8U(8位无符号整数),卷积后的图像梯度值可能为负数或超出0~255范围,若使用该类型,这些梯度值将被截断。        因此,我们需要在这些算子或卷积运算函数内部指定图像深度ddepth为cv2.CV_64F 或cv2.CV_32F(32位或64位浮点数)。

在进行运算前,我们先介绍几个函数,以及计算结果的处理方式。

cv2.convertScaleAbs()函数:

  •         用于自动处理截断和类型转换。
  •         处理方式:按照alpha与beta的值,对图像数据进行线性变换。
  •         然后使用绝对值运算将负数转为正数,若大于255则截断至255,否则保留。

    参数详解:

src原始图像数据
alpha线性变化斜率,默认值为1
beta线性变化截距,默认值为0

cv2.normalize()函数

  •         用于保留全局比例,无信息丢失的进行标准化操作(0~255)
  •         处理方式:默认使用cv2.NORM_L2,若要放缩至0~255需要使用指定norm_type为cv2.NORM_MINMAX使用MinMax最小最大值放缩。

参数详解:

src原始图像数据
alpha当norm_type为cv2.NORM_MINMAX时是MIN最小值,当norm_type是其他类型时,是最后运算结果前的系数。
beta只在norm_type为cv2.NORM_MINMAX时有效,是MAX最大值
dtype图像数据类型,通常是cv2.CV_8U(8为无符号整数)
norm_type指定的标准化类型
mask一个掩码蒙版,与原图像大小一致内部只有0,1两种数字,只有值为1的地方参与标准化操作,值为0的位置不参与标准化操作。默认为None,此时所有元素参与标准化操作。

norm_type类型:

cv2.NORM_MINMAX将数据线性映射到指定范围(如 0-255)。默认是 alpha 和 beta 指定范围
cv2.NORM_L1每个元素除以L1 范数归一化后乘以alpha。L1范数是所有元素的绝对值之和
cv2.NORM_L2每个元素除以 L2 范数归一化后乘以alpha。L2范数是所有元素平方和的平方根
cv2.NORM_INF每个元素除以无穷范数将数据据归一化后乘以alpha。无穷范数是所有元素中的最大值

cv2filter2D()函数:

        用于实现二维图像的卷积运算。

     参数详解:   

src

原始图像数据

ddepth

指定卷积运算时的图像深度,通常会选择cv2.CV_32F或cv2.CV_64F

kernal

自定义卷积核矩阵,使用numpy自定义即可,必须是3x3,5x5奇数大小

anchor

锚点,默认在卷积核中心点

delta

偏移量,加在卷积运算的结果上

borderType

指定边界像素的填充方式,与cv2.copyMakeBorder()函数中的bordertype一致

 cv2.magnitude()函数:

        使用L2范数计算X,Y方向的梯度矢量合成的幅值。

        相当于np.sqrt(x**2+y**2)

Roberts交叉算子实现

代码:

#Roberts算子使用cv2.filter2D()函数实现
'''
cv2.filter2D()函数参数详解:
src:原始图像数据
ddepth:指定卷积运算时的图像深度,通常会选择cv2.CV_32F或cv2.CV_64F
kernal:自定义卷积核矩阵,使用numpy自定义即可,必须是3x3,5x5奇数大小
anchor:锚点,默认在卷积核中心点
delta:偏移量,加在卷积运算的结果上
borderType:指定边界像素的填充方式,与cv2.copyMakeBorder()函数中的bordertype一致
''''''
cv2.normalize()函数参数详解:
src:原始图像数据
alpha:当norm_type为cv2.NORM_MINMAX时是MIN最小值,当norm_type是其他类型时,是最后运算结果前的系数。
beta:只在norm_type为cv2.NORM_MINMAX时有效,是MAX最大值
dtype:图像数据类型,通常是cv2.CV_8U(8为无符号整数)
norm_type:指定的标准化类型
mask:一个掩码蒙版,与原图像大小一致内部只有0,1两种数字,只有值为1的地方参与标准化操作,值为0的位置不参与标准化操作。默认为None,
此时所有元素参与标准化操作。norm_type:
cv2.NORM_MINMAX:将数据线性映射到指定范围(如0-255)默认是alpha和beta指定范围。
cv2.NORM_L1:每个元素除以L1范数归一化后乘以alpha。L1范数是所有元素的绝对值之和。
cv2.NORM_L2:每个元素除以L2范数归一化后乘以alpha。L2范数是所有元素平方和的平方根
cv2.NORM_INF:每个元素除以无穷范数将数据据归一化后乘以alpha。无穷范数是所有元素中的最大值。
''''''
cv2.convertScaleAbs()函数参数详解:
src:原始图像数据
alpha:线性变化斜率,默认值为1
beta:线性变化截距,默认值为0
'''
import cv2
import numpy as np
image=cv2.imread('ultraman.jpg',cv2.IMREAD_GRAYSCALE)
image=cv2.resize(image,dsize=(500,500))#自定义的Roberts卷积核
RobertsKernelX=np.array([[1,0],[0,-1]])
RobertsKernelY=np.array([[0,1],[-1,0]])#两个方向的梯度
GradX=cv2.filter2D(src=image,ddepth=cv2.CV_64F,kernel=RobertsKernelX)
GradY=cv2.filter2D(src=image,ddepth=cv2.CV_64F,kernel=RobertsKernelY)Roberts_magnitude=cv2.magnitude(GradX,GradY)#计算幅值,使用L2范数
#使用MINMAX幅值归一化
Roberts_magnitude=cv2.normalize(src=Roberts_magnitude,dst=None,alpha=0,beta=255,norm_type=cv2.NORM_MINMAX,dtype=cv2.CV_8U)
#对于X,Y方向来说其梯度存在负值,但magnitude不存在负值,因为其运算是根号下平方和
#因此对于magnitude我们使用cv2.normalzie()线性映射至(0,255)归一化即可
#,但是X,Y方向梯度运算结果存在负值,我们直接使用normalize()会导致其将负值也映射到(0,255)区间,
#比如 [-100, 100]使用cv2.normalize()将其映射到[0, 255]结果中负值会被映射到[0,127.5],正值会被映射到[127.5,255]
#这可能会造成图像显示异常,因此对于X,Y方向上的梯度我们直接使用convertScaleAbs取绝对值即可
RobertsX=cv2.convertScaleAbs(src=GradX)
RobertsY=cv2.convertScaleAbs(src=GradY)
cv2.imshow('SRC',image)
cv2.imshow('RobertsX',RobertsX)
cv2.imshow('RobertsY',RobertsY)
cv2.imshow('RobertsMagnitude',Roberts_magnitude)
cv2.waitKey(0)

结果:

Prewitt算子实现 

代码:

#Prewitt算子使用cv2.filter2D()函数实现import cv2
import numpy as np
image=cv2.imread('ultraman.jpg',cv2.IMREAD_GRAYSCALE)
image=cv2.resize(image,dsize=(500,500))#自定义的Prewitt卷积核
PrewittKernelX=np.array([[-1,0,1],[-1,0,1],[-1,0,1]])
PrewittKernelY=np.array([[1,1,1],[0,0,0],[-1,-1,-1]])#两个方向的梯度
GradX=cv2.filter2D(src=image,ddepth=cv2.CV_64F,kernel=PrewittKernelX)
GradY=cv2.filter2D(src=image,ddepth=cv2.CV_64F,kernel=PrewittKernelY)Prewitt_magnitude=cv2.magnitude(GradX,GradY)#计算幅值,使用L2范数
#使用MINMAX幅值归一化
Prewitt_magnitude=cv2.normalize(src=Prewitt_magnitude,dst=None,alpha=0,beta=255,norm_type=cv2.NORM_MINMAX,dtype=cv2.CV_8U)
#对于X,Y方向来说其梯度存在负值,但magnitude不存在负值,因为其运算是根号下平方和
#因此对于magnitude我们使用cv2.normalzie()线性映射至(0,255)归一化即可
#,但是X,Y方向梯度运算结果存在负值,我们直接使用normalize()会导致其将负值也映射到(0,255)区间,
#比如 [-100, 100]使用cv2.normalize()将其映射到[0, 255]结果中负值会被映射到[0,127.5],正值会被映射到[127.5,255]
#这可能会造成图像显示异常,因此对于X,Y方向上的梯度我们直接使用convertScaleAbs取绝对值即可
PrewittX=cv2.convertScaleAbs(src=GradX)
PrewittY=cv2.convertScaleAbs(src=GradY)
cv2.imshow('SRC',image)
cv2.imshow('PrewittX',PrewittX)
cv2.imshow('PrewittY',PrewittY)
cv2.imshow('PrewittMagnitude',Prewitt_magnitude)
cv2.waitKey(0)

结果:

Sobel算子实现

#边缘检测Sobel算子cv2.Sobel()
'''
cv2.Sobel()函数参数详解:
src:原始图像数据。
ddepth:图像深度,计算梯度的幅值,通常会选择 cv2.CV_32F或cv2.CV_64F。
因为梯度值可能为负数使用无符号整数类型会导致负数被截断。
dx:x方向上的导数阶数,即Sobel算子在x方向上的差分阶数。取值为非负整数,常见的取值有0、1、2。
dy:y方向上的导数阶数,即Sobel算子在y方向上的差分阶数。取值为非负整数,常见的取值有0、1、2。
ksize:Sobel算子的大小。即卷积核的大小。必须是正奇数,常见的取值有1、3、5、7等。特别的,当ksize=1时
Sobel算子退化为简单的差分算子。
scale:对结果进行放缩。
delta:用于在计算结果上加上一个常数偏移量。默认值为None,不添加偏移量。如果指定了该参数,计算结果会在返回之前加上这个值。
bodertype:指定边界像素的填充方式,与cv2.copyMakeBorder()函数中的bordertype一致。
'''
import cv2
image=cv2.imread('ultraman.jpg',cv2.IMREAD_GRAYSCALE)
image=cv2.resize(image,dsize=(500,500))#变换一下大小
#使用cv2.64F是为了确保梯度计算过程中保留了所有负值和高幅值信息。
GradX=cv2.Sobel(src=image,ddepth=cv2.CV_64F,dx=1,dy=0,ksize=3)
GradY=cv2.Sobel(src=image,ddepth=cv2.CV_64F,dx=0,dy=1,ksize=3)
Sobel_magnitude=cv2.magnitude(GradX,GradY)#计算幅值,相当于np.sqrt(x**2+y**2)
Sobel=cv2.normalize(Sobel_magnitude,None,alpha=0,beta=255,norm_type=cv2.NORM_MINMAX,dtype=cv2.CV_8U)
#对于X,Y方向来说其梯度存在负值,但magnitude不存在负值,因为其运算是根号下平方和
#因此对于magnitude我们使用cv2.normalzie()线性映射至(0,255)归一化即可
#,但是X,Y方向梯度运算结果存在负值,我们直接使用normalize()会导致其将负值也映射到(0,255)区间,
#比如 [-100, 100]使用cv2.normalize()将其映射到[0, 255]结果中负值会被映射到[0,127.5],正值会被映射到[127.5,255]
#这可能会造成图像显示异常,因此对于X,Y方向上的梯度我们直接使用convertScaleAbs取绝对值即可
Sobel_x=cv2.convertScaleAbs(src=GradX)
Sobel_y=cv2.convertScaleAbs(src=GradY)
cv2.imshow('SRC_image',image)
cv2.imshow('Sobel X',Sobel_x)
cv2.imshow('Sobel Y',Sobel_y)
cv2.imshow('Sobel Magnitude',Sobel)
cv2.waitKey(0)

 结果:

Canny算子实现

代码:

#边缘检测cv2.Canny()算子
'''
cv2.Canny()函数参数详解:
image:原始图像数据
threshold1:第一个阈值(低阈值),用于边缘检测的滞后阈值处理
threshold2:第二个阈值(高阈值),用于边缘检测的滞后阈值处理
aperturesize:Sobel算子的卷积核大小,用于计算图像的梯度幅值和方向
L2gradient:是否使用L2范数计算梯度幅值即cv2.magnitude()函数。
'''
#这里需要注意的是threshold1与threshold2一般为2倍时效果明显
#因此我们可以使用cv2.threshold()函数自动计算threashold2,然后threshold1=0.5*threshold1
import cv2
bgr_image=cv2.imread('ultraman.jpg')
bgr_image=cv2.resize(src=bgr_image,dsize=(500,500))
# 计算图像的直方图并应用 Otsu'阈值
gray_image=cv2.cvtColor(bgr_image,cv2.COLOR_BGR2GRAY)
#使用的是cv2.THRESH_BINARY+cv2.THRESH_OTSU自动计算阈值
thresh,_= cv2.threshold(gray_image, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
high_thresh=thresh
low_thresh=0.5 * high_thresh
Canny_image=cv2.Canny(image=gray_image,threshold1=low_thresh,threshold2=high_thresh,apertureSize=3,L2gradient=True)
cv2.imshow('BgrImage',bgr_image)
cv2.imshow('GrayImage',gray_image)
cv2.imshow('CannyImage',Canny_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果: 

Laplacian算子实现 

代码:

#边缘检测cv2.Laplacian()算子
'''
cv2.Canny()函数参数详解:
image:原始图像数据
threshold1:第一个阈值(低阈值),用于边缘检测的滞后阈值处理
threshold2:第二个阈值(高阈值),用于边缘检测的滞后阈值处理
aperturesize:Sobel算子的卷积核大小,用于计算图像的梯度幅值和方向
L2gradient:是否使用L2范数计算梯度幅值即cv2.magnitude()函数。
'''
import cv2
bgr_image=cv2.imread('ultraman.jpg')
bgr_image=cv2.resize(src=bgr_image,dsize=(500,500))
gray_image=cv2.cvtColor(bgr_image,cv2.COLOR_BGR2GRAY)
Laplacian_image=cv2.Laplacian(src=gray_image,ddepth=cv2.CV_64F,dst=None,ksize=3,scale=1,delta=0)
#laplacian算子是二阶导数算子,它同时卷积x与y反向不需要计算幅值,其结果中含有负数
#我们直接使用normalize()会导致其将负值也映射到(0,255)区间,
#比如[-100, 100]使用cv2.normalize()将其映射到[0, 255]结果中负值会被映射到[0,127.5],正值会被映射到[127.5,255]
#这可能会造成图像显示异常,因此我们直接使用convertScaleAbs取绝对值即可
Laplacian_image=cv2.convertScaleAbs(src=Laplacian_image)
cv2.imshow('BgrImage',bgr_image)
cv2.imshow('GrayImage',gray_image)
cv2.imshow('LaplacianImage',Laplacian_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

 LOG算子实现

代码:

#LOG算子实现边缘检测
import cv2
image=cv2.imread('ultraman.jpg', cv2.IMREAD_GRAYSCALE)
image=cv2.resize(image,dsize=(500,500))
#高斯滤波(降噪)
sigma=2.0#高斯核标准差
blurred=cv2.GaussianBlur(image, (0, 0), sigma)
#使用Laplacian算子计算二阶导数
laplacian=cv2.Laplacian(blurred, cv2.CV_64F, ksize=3)
laplacian_abs=cv2.convertScaleAbs(laplacian)
#零交叉点检测(通过阈值化提取边缘)
#这里使用自适应阈值
edges=cv2.adaptiveThreshold(src=laplacian_abs,maxValue=255,adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,thresholdType=cv2.THRESH_BINARY_INV,C=4,blockSize=11)
cv2.imshow("SRCImage", image)
cv2.imshow("LOGEdges", edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果: 

总结

        简而言之,我们这里介绍到的边缘检测算子都是基于梯度,因此其内部的数字都基于差分结果的系数。不同的区别在于,他们中有些使用的差分阶数不同,有些考虑到了使用滤波模版,有些考虑到了中心像素点的权重,有些重点关注斜对角线上像素点的差分结果……但是追根溯源,都不外乎是在利用卷积运算查找灰度值变化明显的地方,这也是边缘的概念所在。

相关文章:

计算机视觉cv2入门之边缘检测

检测原理 边缘检测是指检测图像中的一些像素点,它们周围的像素点的灰度发生了急剧的变化,因此可以将这些像素点作为一个集合,用于标注图像中不同物体的边界。 边缘是图像上灰度级变化很快的点的集合。这些点的梯度往往很大。因此我们可以使用一阶导数和二…...

python脚本实现服务器内存和cpu使用监控,并记录日志,可以设置阈值和采样频率

Python 脚本,实现以下功能: 按日期自动生成日志文件(例如 cpu_mem_20231001.csv)当 CPU 或内存超过阈值时触发记录独立记录报警事件(保存到 alert.log)支持自定义阈值和监控间隔 脚本代码 import psutil …...

解决PC串流至IPad Pro时由于分辨率不一致导致的黑边问题和鼠标滚轮反转问题

问题背景 今天在做 电脑串流ipad pro 的时候发现了2个问题: 1.ipadpro 接上鼠标后,滚轮上下反转,这个是苹果自己的模拟造成的问题,在设置里选择“触控板与鼠标”。 关闭“自然滚动”,就可以让鼠标滚轮正向滚动。 2. ipadpro 分…...

星越L_三角指示牌及危险警示灯使用

目录 1.打开危险警告灯 2.取出反光背心穿上 3.取出指示牌 4.放置三角指示牌。 1.打开危险警示灯 2.取出反光背心穿上 3.取出指示牌...

使用WireShark解密https流量

概述 https协议是在http协议的基础上,使用TLS协议对http数据进行了加密,使得网络通信更加安全。一般情况下,使用WireShark抓取的https流量,数据都是加密的,无法直接查看。但是可以通过以下两种方法,解密抓…...

MySQL复习(检查本地MySQL是否安装、DataGrip数据库可视化工具使用、增删改查基础语法、唯一索引、SQL简单函数)

目录 一、快速检查本地MySQL是否安装。(详细教程) (1)MySQL本地系统环境变量配置。(简单说明) (2)cmd命令行——判断MySQL是否安装成功! 二、DataGrip数据库操作可视化工具。 (1)基本介绍。 &am…...

数学建模 第一节

目录​​​​​​ 前言 一 优化模型的类型 二 线性规划1 线性规划2 三 0-1规划 总结 前言 数学建模主要是将问题转化为模型,然后再以编程的形式输出出来 算法都知道,数学建模也需要用到算法,但是不是主要以编程形式展示,而是…...

《Python实战进阶》No24: PyAutoGUI 实现桌面自动化

No24: PyAutoGUI 实现桌面自动化 摘要 PyAutoGUI 是一个跨平台的桌面自动化工具,能够模拟鼠标点击、键盘输入、屏幕截图与图像识别,适用于重复性桌面任务(如表单填写、游戏操作、批量文件处理)。本集通过代码截图输出日志的实战形…...

实验篇| CentOS 7 下 Keepalived + Nginx 实现双机高可用

为什么要做双机高可用?‌ 想象一下:你的网站突然宕机,用户无法访问,订单流失、口碑暴跌…💸 ‌双机热备‌就是解决这个痛点的终极方案!两台服务器互为备份,724小时无缝切换,保障业务…...

音视频入门基础:RTP专题(19)——FFmpeg源码中,获取RTP的音频信息的实现(下)

本文接着《音视频入门基础:RTP专题(18)——FFmpeg源码中,获取RTP的音频信息的实现(上)》,继续讲解FFmpeg获取SDP描述的RTP流的音频信息到底是从哪个地方获取的。本文的一级标题从“四”开始。 四…...

JAVA面试_进阶部分_dubbo负载均衡策略

前言:zookeeper作为dubbo的注册中心,有一个很重要的点,我们的程序是分布式应用,服务部署在几个节点(服务器)上,当消费者调用服务时,zk返回给dubbo的是一个节点列表,但是d…...

《我的Python觉醒之路》之转型Python(十三)——控制流

#今天风景不错,明天继续学习 请关注我之前的笔记啊...

QT6.8.2在线安装记录

命令行带安装源启动,但仍不能连接到服务器,开着VPN才通过 .\qt-online-installer-windows-x64-4.8.1.exe --mirror https://mirrors.ustc.edu.cn/qtproject 开始安装前断开VPN,其实启动安装器时的镜像源修改参数是起作用的,因为下…...

70.HarmonyOS NEXT PicturePreview组件深度剖析:从架构设计到核心代码实现

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT PicturePreview组件深度剖析:从架构设计到核心代码实现 文章目录 HarmonyOS NEXT PicturePreview组件深度剖析&#xf…...

如何从受 Cloudflare 保护的网站提取数据:技术与挑战

引言 Web抓取是数据科学和市场研究的重要工具,但当面对受Cloudflare等先进保护系统守护的网站时,这项任务变得异常具有挑战性。Cloudflare的机器人检测系统需要精心设计的网页抓取解决方案才能成功提取数据。本文将介绍Cloudflare的防护机制以及如何使用…...

【DeepSeek应用】DeepSeek模型本地化部署方案及Python实现

DeepSeek实在是太火了,虽然经过扩容和调整,但反应依旧不稳定,甚至小圆圈转半天最后却提示“服务器繁忙,请稍后再试。” 故此,本文通过讲解在本地部署 DeepSeek并配合python代码实现,让你零成本搭建自己的AI助理,无惧任务提交失败的压力。 一、环境准备 1. 安装依赖库 …...

WPF程序使用AutoUpdate实现自动更新

AutoUpdate.NET使用 一、AutoUpdater.NET 简介 AutoUpdater.NET 是一个开源库,支持从各种源(如GitHub、FTP、HTTP服务器等)下载并安装更新。它提供了灵活的配置选项,允许开发者根据需求定制更新检查逻辑和用户体验。 二、安装 …...

A SURVEY ON POST-TRAINING OF LARGE LANGUAGE MODELS——大型语言模型的训练后优化综述——第2部分

3、微调(上一部分内容) 4、LLMs的对齐 大型语言模型(LLMs)中的对齐涉及引导模型输出以符合人类预期和偏好,特别是在安全关键或用户面对的应用程序中。本章讨论了实现对齐的三个主要范式: 带有反馈的人工…...

【2025】Electron Git Desktop 实战一(上)(架构及首页设计开发)

源代码仓库: Github仓库【electron_git】 Commit : bb40040 Github Desktop 页面分析 本节目标: 1、实现类似Github Desktop的「空仓库」提示页 2、添加本地仓库逻辑编写从 Github Desktop 我们看到 他的 主要页面分为三个区域 Head头部区域…...

996引擎-问题处理:缺失特效分割文件 ModelAtlasSplitConfigs

通常我们买的资源都是带会 ModelAtlasSplitConfigs.txt 或 sceneAtlasSplitConfigs.txt 的 但有时确实找不到的话,是可以用996工具生成的:...

2024年12月CCF-GESP编程能力等级认证C++编程三级真题解析

三级真题的难度: ‌ CCF-GESP编程能力等级认证的C++三级真题难度通常被认为是中等水平,适合具备一定编程基础的考生。以下是关于三级真题难度的一些具体信息: 1. 考试内容 C++三级考试主要涵盖以下几个方面的知识: 基本语法:包括数据类型、变量、运算符等基础知…...

Java面试八股—Redis篇

一、Redis的使用场景 (一)缓存 1.Redis使用场景缓存 场景:缓存热点数据(如用户信息、商品详情),减少数据库访问压力,提升响应速度。 2.缓存穿透 正常的访问是:根据ID查询文章&…...

机器人ROS学习:Ubuntu22.04安装ROS2和Moveit2实现运动规划

通过本篇文章学习,你可以收获以下内容: 学会在 Ubuntu22.04 上安装 Moveit2学会下载编译运行 Moveit2 样例程序学会使用样例程序进行运动规划等 版本平台 系统版本:ubuntu22.04ROS2 版本:humbleMoveit 版本:moveit2…...

树结构和数组之间的转化

1、树结构转为数组 treeToArray(treeData, returnValue []) { let newValue [...returnValue] treeData.map(item > { if (item.children) { const { children, ...treeObj } { ...item } newValue.push(treeObj) newValue this.treeToArray(children, newValue) } else…...

2024华东师范大学计算机复试上机真题

2024华东师范大学计算机复试机试真题 2023华东师范大学计算机复试机试真题 2022华东师范大学计算机复试机试真题 2024华东师范大学计算机复试上机真题 2023华东师范大学计算机复试上机真题 2022华东师范大学计算机复试上机真题 在线评测:传动门:pgcode…...

Blender-MCP服务源码3-插件开发

Blender-MCP服务源码3-插件开发 Blender-MCP服务源码解读-如何进行Blender插件开发 1-核心知识点 1)使用Blender开发框架学习如何进行Blender调试2)学习目标1-移除所有的Blender业务-了解如何MCP到底做了什么?3)学习目标2-模拟MC…...

C++复试笔记(三)

1.友元函数和友元类 1.1友元函数 友元函数的经典实例是重载 "<<" 和 ">>" ,去重载operator<<&#xff0c;然后发现没办法将operator<<重载成成员函数。因为cout的 输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默…...

【数学基础】概率与统计#1概率论与信息论初步

本系列内容介绍&#xff1a; 主要参考资料&#xff1a; 《深度学习》[美]伊恩古德菲洛 等 著 《机器人数学基础》吴福朝 张铃 著 文章为自学笔记&#xff0c;默认读者有一定的大学数学基础&#xff0c;仅供参考。 目录 随机变量概率分布离散型随机变量和概率质量函数连续型变量…...

掌握这些 UI 交互设计原则,提升产品易用性

在当今数字化时代&#xff0c;用户对于产品的体验要求越来越高&#xff0c;UI 交互设计成为决定产品成败的关键因素之一。一个易用的产品能够让用户轻松、高效地完成各种操作&#xff0c;而实现这一目标的核心在于遵循一系列科学合理的 UI 交互设计原则。本文将详细阐述简洁性、…...

工程化与框架系列(32)--前端测试实践指南

前端测试实践指南 &#x1f9ea; 引言 前端测试是保证应用质量的重要环节。本文将深入探讨前端测试的各个方面&#xff0c;包括单元测试、集成测试、端到端测试等&#xff0c;并提供实用的测试工具和最佳实践。 测试概述 前端测试主要包括以下类型&#xff1a; 单元测试&a…...

Python----计算机视觉处理(opencv:像素,RGB颜色,图像的存储,opencv安装,代码展示)

一、计算机眼中的图像 像素 像素是图像的基本单元&#xff0c;每个像素存储着图像的颜色、亮度和其他特征。一系列像素组合到一起就形成 了完整的图像&#xff0c;在计算机中&#xff0c;图像以像素的形式存在并采用二进制格式进行存储。根据图像的颜色不 同&#xff0c;每个像…...

表单 schema 配置化

一、前沿 基于 Ant Design Vue 组件库实现了表单的配置化生成&#xff0c;通过 schema 配置化的方式实现表单的动态渲染、数据绑定和更新等功能&#xff0c;而提交按钮及获取数据逻辑由使用方自行提供。通过 schema 对象来定义表单的结构和属性&#xff0c;modelData 对象存储…...

Java数据结构第二十三期:Map与Set的高效应用之道(二)

专栏&#xff1a;Java数据结构秘籍 个人主页&#xff1a;手握风云 目录 一、哈希表 1.1. 概念 1.2. 冲突 1.3. 避免冲突 1.4. 解决冲突 1.5. 实现 二、OJ练习 2.1. 只出现一次的数字 2.2. 随机链表的复制 2.3. 宝石与石头 一、哈希表 1.1. 概念 顺序结构以及平衡树中…...

unity生命周期

unity的生命周期 都是有序的1. 实例化与初始化阶段Awake()OnEnable() 2. 开始与更新阶段Start()FixedUpdate()Update()LateUpdate() 3. 渲染阶段OnPreCull()OnBecameVisible() 和 OnBecameInvisible()OnWillRenderObject()OnRenderObject()OnPostRender() 4. 销毁阶段OnDisable…...

对比学习(Contrastive Learning)

1. 概念 对比学习&#xff08;Contrastive Learning&#xff09;是一种自监督学习&#xff08;Self-Supervised Learning&#xff09;方法&#xff0c;其核心思想是通过相似样本靠近&#xff0c;不同样本远离的方式学习数据的潜在表示。它广泛用于无标签数据的特征提取&#x…...

C语言输入与输出:从零掌握数据的“对话”

手把手教你理解C语言中输入&#xff08;Input&#xff09;与输出&#xff08;Output&#xff09;的核心操作。 一、输入与输出是什么&#xff1f; C语言通过标准库函数实现程序与用户&#xff08;或设备&#xff09;的“对话”&#xff1a; 输出&#xff1a;程序将数据展示给…...

PyCharm 2019.1.3使用python3.9创建虚拟环境setuptools-40.8.0报错处理

目录 前置&#xff1a; 一劳永逸方法&#xff08;缺最后一步&#xff0c;没有成行&#xff09; step one: 下载高版本的pip、setuptools、virtualenv的tar.gz包 step two: 进入PyCharm安装目录的 helpers 目录下 step three: 下载并安装grep和sed命令&#xff0c;然后执行 …...

从0到1构建AI深度学习视频分析系统--基于YOLO 目标检测的动作序列检查系统:(2)消息队列与消息中间件

文章大纲 原始视频队列Python 内存视频缓存优化方案(4GB 以内)一、核心参数设计二、内存管理实现三、性能优化策略四、内存占用验证五、高级优化技巧六、部署建议检测结果队列YOLO检测结果队列技术方案一、技术选型矩阵二、核心实现代码三、性能优化策略四、可视化方案对比五…...

Redis基本命令手册——五大类型

目录 一&#xff1a;基本操作 二&#xff1a;字符串&#xff08;String&#xff09; 三&#xff1a;哈希&#xff08;Hash) 四&#xff1a;列表&#xff08;List&#xff09; 五&#xff1a;集合&#xff08;Set&#xff09; 六&#xff1a;有序集合&#xff08;Zset&…...

Java 大视界 -- Java 大数据在智能金融资产定价与风险管理中的应用(134)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

Linux 系统蓝牙音频服务实现分析

Linux 系统蓝牙音频服务实现分析 蓝牙音频设备连接管理Linux 系统中,蓝牙音频服务实现为系统音频服务 PulseAudio 的可加载模块,它用来以 PulseAudio 标准的方式描述蓝牙音频设备,将其嵌入 PulseAudio 的音频处理流水线,并呈现给用户,支持用户切换音频设备,如蓝牙耳机。 …...

PyTorch 深度学习实战(14):Deep Deterministic Policy Gradient (DDPG) 算法

在上一篇文章中&#xff0c;我们介绍了 Proximal Policy Optimization (PPO) 算法&#xff0c;并使用它解决了 CartPole 问题。本文将深入探讨 Deep Deterministic Policy Gradient (DDPG) 算法&#xff0c;这是一种用于连续动作空间的强化学习算法。我们将使用 PyTorch 实现 D…...

craftjs的示例landing项目改成APP路由

下载项目 项目地址是&#xff1a;https://github.com/prevwong/craft.js 示例项目在examples文件夹下面landing文件夹 修改 1.修改依赖包 由于craftjs使用的多包管理&#xff0c;示例项目中craftjs/core和craftjs/layers使用的是工作区路径&#xff0c;这里需要修改版本 …...

java -jar 执行基于Maven构建的Java应用的方法总结

一、Maven pom.xml文件未指定主类的情况 1、用Maven打包 mvn clean package -DskipTests 2、用java命令执行jar包 java -cp maven-allin-mainclass-demo-1.0-SNAPSHOT.jar org.example.Main 二、Maven pom.xml文件指定主类的情况 1、pom.xml文件指定主类&#xff0c;有两种…...

前端发布缓存导致白屏解决方案

解决发布H5后因为本地缓存白屏方案 一、 核心配置优化&#xff08;前提是访问网站的请求能抵达服务器&#xff09; 方案一&#xff1a;前端项目设置全局不缓存方案 运行逻辑&#xff1a;在H5服务器配置中增加Cache-Control: no-cache或max-age0响应头&#xff0c;禁用静态资…...

【后端】【django】Django 自带的用户系统与 RBAC 机制

Django 自带的用户系统与 RBAC 机制 Django 自带的用户系统&#xff08;django.contrib.auth&#xff09;提供了 身份验证&#xff08;Authentication&#xff09; 和 权限管理&#xff08;Authorization&#xff09;&#xff0c;能够快速实现 用户管理、权限控制、管理员后台…...

SpringBoot MCP 入门使用

随着AI的火爆&#xff0c;最近发现MCP在未来确实大有可为&#xff0c;作为一名javaer怎么可以落后在历史洪流呢&#xff0c;根据官网和cursor也从零开始体验一下自定义mcp server。以后可以根据自己业务场景做出各种适合自身业务的工具。 至于什么是MCP 可以到https://modelcon…...

Java使用JDBC连接操作Sqlite 笔记250314

Java使用JDBC连接操作Sqlite 以下是使用 Java JDBC 连接和操作 SQLite 数据库的详细步骤&#xff1a; 1. 添加 SQLite JDBC 驱动 在项目中引入 SQLite JDBC 驱动依赖。 Maven 项目在 pom.xml 中添加&#xff1a;<dependency><groupId>org.xerial</groupId>…...

每日一题---腐烂的苹果(广度优先搜索)

腐烂的苹果 给定一个 nm nm 的网格&#xff0c;其中每个单元格中可能有三种值中的一个 0 , 1 , 2。 其中 0 表示这个格子为空、1 表示这个格子有一个完好的苹果&#xff0c;2 表示这个格子有一个腐烂的苹果。 腐烂的苹果每分钟会向上下左右四个方向的苹果传播一次病菌&…...

Visual Studio里的调试(debugging)功能介绍

参考 1- Introduction to Debugging | Basic Visual Studio Debugging&#xff08;这是一位印度博主视频&#xff0c;我下面做到笔记也主要参考她的视频&#xff0c;但不得不说口音太重了&#xff0c;一股咖喱味&#xff09; 目录 个人对调试浅显的认识和对调试的介绍逐行调…...