OpenCV图像梯度、边缘检测、轮廓绘制、凸包检测大合集

一、图像梯度

在图像处理中,「梯度(Gradient)」是一个非常基础但又极其重要的概念。它是图像边缘检测、特征提取、纹理分析等众多任务的核心。梯度的本质是在空间上描述像素灰度值变化的快慢和方向。

但我们如何在图像中计算梯度?又该选择什么样的算子?本文将从梯度的数学定义出发,逐步引入经典的 Sobel 与 Laplacian 算子,带你了解图像梯度的计算原理与实践方式。

1.1 什么是图像梯度?

图像梯度反映的是像素值(灰度或强度)在空间中的变化率。可以类比为地形图中的“坡度”:哪里灰度变化剧烈,哪里就是图像的“边缘”。

对于二维灰度图像I(x,y)I(x,y)I(x,y),梯度定义为图像对空间坐标的偏导数组成的向量:
∇I=[∂I∂x,∂I∂y] \nabla I = \left[ \frac{\partial I}{\partial x}, \frac{\partial I}{\partial y} \right] I=[xI,yI]

  • ∂I∂x\frac{\partial I}{\partial x}xI:表示图像在水平方向(x轴)上的变化率;
  • ∂I∂y\frac{\partial I}{\partial y}yI:表示图像在垂直方向(y轴)上的变化率。

该向量的模长表示梯度的强度,方向表示灰度变化最剧烈的方向。

1.2 如何计算梯度

由于图像是离散的,我们不能直接求导,而是通过离散卷积实现近似求导

使用cv2.filter2D自定义卷积核

OpenCV中filter2D可以对图形施加自定义的卷积核,是实现梯度算子的基础方法

语法如下所示:

dst = cv2.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])

filter2D函数是用于对图像进行二维卷积(滤波)操作。它允许用户自定义卷积核(kernal)来实现各种图像处理效果,如平滑,锐化,边缘检测。

参数解析:

参数名类型说明
srcndarray输入图像,必须是单通道或多通道(如灰度图或彩色图)
ddepthint输出图像的深度(如 cv2.CV_64F, -1 表示与原图相同)
kernelndarray卷积核(滤波器),必须是浮点型 np.float32np.float64
dstndarray(可选)输出图像,与 src 同大小
anchortuple卷积核锚点,默认 (-1, -1) 表示核中心
deltafloat可选偏移值,加到卷积结果上
borderTypeint边界填充方式,常见如 cv2.BORDER_DEFAULT(边界反射_101), cv2.BORDER_REPLICATE
import cv2 as cv
import numpy as np# 构造图像:中心有明显亮度突变
img = np.array([[10, 10, 10, 10, 10, 10, 10],[10, 10, 10, 255, 255, 10, 10],[10, 10, 10, 255, 255, 10, 10],[10, 10, 10, 255, 255, 10, 10],[10, 10, 10, 10, 10, 10, 10]
], dtype=np.uint8)# 使用 Sobel 水平方向边缘检测核
kernel = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]], dtype=np.float32)# 卷积
img2 = cv.filter2D(img, -1, kernel)print(img2)

结果展示:

[[  0   0 255 255   0   0   0][  0   0 255 255   0   0   0][  0   0 255 255   0   0   0][  0   0 255 255   0   0   0][  0   0 255 255   0   0   0]]

滑动卷积

1.3 常见的梯度算子

1️⃣ Sobel 算子(Sobel Operator)

Sobel 是最常见的梯度算子之一,结合了高斯平滑微分运算,对噪声更鲁棒。

  • 水平方向梯度核:

Gx=[−101−202−101] Gx=\begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix} Gx=121000121

  • 垂直方向梯度核:
    Gy=[−1−2−1000121] G_y = \begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{bmatrix} Gy=101202101

在 OpenCV 中的实现:

语法说明:

dst = cv2.Sobel(src, ddepth, dx, dy, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
参数名类型说明
srcndarray输入图像(通常为灰度图)
ddepthint输出图像的数据深度(OpenCV 中,-1 表示输出图像的深度与输入图像相同。)
dxintx 方向求导阶数(1 表示对 x 求一阶导),获取的垂直边缘
dyinty 方向求导阶数,获取的水平边缘
ksizeintSobel 核大小(可为 1, 3, 5, 7,常用 3)
scalefloat可选缩放因子,对导数结果进行缩放(一般为 1)
deltafloat可选偏移量,结果加上 delta(一般为 0)
borderTypeint边界填充方式,默认 cv2.BORDER_DEFAULT

示例代码:Sobel算子的使用

# sobel算子import cv2 as cvshudu = cv.imread('../images/shudu.png', cv.IMREAD_GRAYSCALE)# x方向
dst_x = cv.Sobel(shudu, -1, 1, 0, ksize=3)# y方向
dst_y = cv.Sobel(shudu, -1, 0, 1, ksize=3)# x和y方向
dst_xy = cv.Sobel(shudu, -1, 1, 1, ksize=3)cv.imshow('shudu', shudu)
cv.imshow('dst_x', dst_x)
cv.imshow('dst_y', dst_y)
cv.imshow('dst_xy', dst_xy)
cv.waitKey(0)
cv.destroyAllWindows()

结果输出:

image-20250726152449232image-20250726152520688image-20250726152546696image-20250726152615977
灰度图dx=1,dy=0(获取垂直边缘)dx=0,dy=1(获取水平边缘)dx=1,dy=1(不建议使用),用Laplacian来获取水平垂直边缘。

dxdy可以都为1,获取的垂直和水平方向上的梯度。dxdy不能都为0。

  • grad_x: 图像在 x 方向的梯度(横向变化)
  • grad_y: 图像在 y 方向的梯度(纵向变化)

我们可以将它们组成一个向量:
G⃗=(grad_x, grad_y) \vec{G} = (grad\_x, \, grad\_y) G=(grad_x,grad_y)
然后,使用勾股定理计算这个向量的长度(也就是梯度强度):
magnitude=grad_x2+grad_y2 \text{magnitude} = \sqrt{grad\_x^2 + grad\_y^2} magnitude=grad_x2+grad_y2


2️⃣ Laplacian 算子(Laplacian Operator)

一、什么是 Laplacian 算子?

Laplacian(拉普拉斯算子)是二阶微分算子,用于度量函数在某点处的“变化率的变化”,即函数曲率。

在图像处理中,它能检测图像中灰度变化最显著的地方——边缘,尤其是亮度快速变化的区域,对噪声也很敏感。

数学定义如下:
Δf=∂2f∂x2+∂2f∂y2 \Delta f = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2} Δf=x22f+y22f


🧮 二、从一维差分到二维卷积核
1. 一维差分

一阶差分(梯度近似):
f′(x)≈f(x+1)−f(x) f'(x) \approx f(x+1) - f(x) f(x)f(x+1)f(x)
二阶差分(Laplacian 近似):
f′′(x)≈f(x+1)+f(x−1)−2f(x) f''(x) \approx f(x+1) + f(x-1) - 2f(x) f′′(x)f(x+1)+f(x1)2f(x)
对应的卷积核(差分模板)为:
k=[1,−2,1] k=[1,−2,1] k=[1,2,1]


2. 推导二维 Laplacian 卷积核

对于二维函数 f(x,y)f(x,y)f(x,y)

水平方向二阶导数:
∂2f∂x2≈f(x+1,y)+f(x−1,y)−2f(x,y) \frac{\partial^2 f}{\partial x^2} \approx f(x+1, y) + f(x-1, y) - 2f(x, y) x22ff(x+1,y)+f(x1,y)2f(x,y)
垂直方向二阶导数:
∂2f∂y2≈f(x,y+1)+f(x,y−1)−2f(x,y) \frac{\partial^2 f}{\partial y^2} \approx f(x, y+1) + f(x, y-1) - 2f(x, y) y22ff(x,y+1)+f(x,y1)2f(x,y)
将它们相加:
Δf(x,y)≈f(x+1,y)+f(x−1,y)+f(x,y+1)+f(x,y−1)−4f(x,y) \Delta f(x, y) \approx f(x+1, y) + f(x-1, y) + f(x, y+1) + f(x, y-1) - 4f(x, y) Δf(x,y)f(x+1,y)+f(x1,y)+f(x,y+1)+f(x,y1)4f(x,y)
这就是最常见的 4 邻域 Laplacian 模板:
k=[0101−41010] k = \begin{bmatrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{bmatrix} k=010141010


3. 加上对角(斜对角)项:8 邻域

如果你想让算子对角方向也敏感,可以扩展为:
k=[1111−81111] k = \begin{bmatrix} 1 & 1 & 1 \\ 1 & -8 & 1 \\ 1 & 1 & 1 \end{bmatrix} k=111181111

这种核能更广泛捕捉到不同方向的边缘,但也更敏感。

OpenCV 使用方式:

cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
参数含义
src输入图像,必须是灰度图
ddepth输出图像的深度,常用 cv2.CV_64F,避免溢出
ksize卷积核大小,必须是奇数,一般设为 1 表示使用标准核(上面那个)
scale缩放梯度值,默认 1
delta可选的偏移值,默认 0
borderType边缘填充方式,默认 cv2.BORDER_DEFAULT

与 Sobel 不同,Laplacian 不区分方向,输出的是一种方向无关的边缘响应

示例代码
# Laplacian算子
import cv2 as cvshudu = cv.imread('../images/shudu.png', cv.IMREAD_GRAYSCALE)# Laplacian算子
dst = cv.Laplacian(shudu, -1, ksize=1)
cv.imshow('shudu', shudu)
cv.imshow('dst', dst)
cv.waitKey(0)
cv.destroyAllWindows()
image-20250726161527158image-20250726161549023
灰度图Laplacian算子

二、图像边缘检测

2.1. 什么是图像边缘?

从数学角度来看,图像边缘是图像灰度函数的一阶导数(梯度)取得极大值的位置,或二阶导数(Laplacian)为零的地方。

我们把二维图像 f(x,y)f(x,y)f(x,y) 看作一个连续函数,图像的变化速率(即灰度变化)就是它的梯度:
∇f=(∂f∂x,∂f∂y) \nabla f = \left( \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y} \right) f=(xf,yf)
梯度的模长即为边缘强度:
∣∇f∣=(∂f∂x)2+(∂f∂y)2 |\nabla f| = \sqrt{ \left( \frac{\partial f}{\partial x} \right)^2 + \left( \frac{\partial f}{\partial y} \right)^2 } ∣∇f=(xf)2+(yf)2


2. 2. 边缘检测的整体流程图

原始图像
高斯滤波\n去噪
Sobel卷积\n计算梯度与方向
非极大值抑制\n细化边缘
双阈值筛选\n连接边缘
输出边缘图像

2. 3. 高斯滤波去噪

边缘检测属于一种“锐化”操作,容易放大噪声。为此,第一步通常使用高斯滤波对图像进行平滑处理,消除小范围内的噪点干扰:

blur = cv2.GaussianBlur(img, (5, 5), 1.4)

高斯核示例(5x5):
1273[1474141626164726412674162616414741] \frac{1}{273} \begin{bmatrix} 1 & 4 & 7 & 4 & 1\\ 4 & 16 & 26 & 16 & 4\\ 7 & 26 & 41 & 26 & 7\\ 4 & 16 & 26 & 16 & 4\\ 1 & 4 & 7 & 4 & 1 \end{bmatrix} 27311474141626164726412674162616414741


2.4. Sobel算子计算梯度与方向

📌 Sobel 卷积核

用于计算图像在水平与垂直方向上的一阶导数:

  • 水平(x方向)

Gx=[−101−202−101] G_x = \begin{bmatrix} -1 & 0 & 1\\ -2 & 0 & 2\\ -1 & 0 & 1 \end{bmatrix} Gx=121000121

  • 垂直(y方向)

Gy=[−1−2−1000121] G_y = \begin{bmatrix} -1 & -2 & -1\\ 0 & 0 & 0\\ 1 & 2 & 1 \end{bmatrix} Gy=101202101

梯度值与方向

grad_x = cv2.Sobel(blur, cv2.CV_64F, 1, 0)
grad_y = cv2.Sobel(blur, cv2.CV_64F, 0, 1)
magnitude = cv2.magnitude(grad_x, grad_y)
angle = cv2.phase(grad_x, grad_y, angleInDegrees=True)
  • 梯度幅值(强度):

G=Gx2+Gy2 G = \sqrt{G_x^2 + G_y^2} G=Gx2+Gy2

  • 梯度方向:

θ=arctan⁡(GyGx) \theta = \arctan\left( \frac{G_y}{G_x} \right) θ=arctan(GxGy)


2.5. 非极大值抑制(NMS)

目的:只保留梯度方向上的局部极大值点,细化边缘线条

步骤如下:

  1. 对于每一个像素,查找其在梯度方向上的邻接像素。
  2. 如果当前像素的梯度值不是三者中最大的,就将其抑制为0。

为了比较非整数方向上的像素值,需要使用线性插值

得到θ\thetaθ的值之后,就可以对边缘方向进行分类,为了简化计算过程,一般将其归为四个方向:水平方向、垂直方向、45°方向、135°方向。并且:

θ\thetaθ值为-22.5°~22.5°,或-157.5°~157.5°,则认为边缘为水平边缘;

当法线方向为22.5°~67.5°,或-112.5°~-157.5°,则认为边缘为45°边缘;

当法线方向为67.5°~112.5°,或-67.5°~-112.5°,则认为边缘为垂直边缘;

当法线方向为112.5°~157.5°,或-22.5°~-67.5°,则认为边缘为135°边缘;

image-20250726162939631


2.6. 双阈值连接(Hysteresis)

非极大值抑制后,图像中仍有很多边缘片段。通过设定高低两个阈值,连接可靠的边缘:

  • 高于高阈值 → 强边缘(保留)
  • 低于低阈值 → 弱边缘(舍弃)
  • 介于之间 → 如果与强边缘连接,则保留;否则丢弃

image-20250726163059933

推荐设置

edges = cv2.Canny(img, threshold1=50, threshold2=150)

阈值比建议控制在 2:1 到 3:1 之间。


2.7. Canny 算子:全流程封装

OpenCV 内置的 Canny 算子封装了所有步骤:

edges = cv2.Canny(image, 50, 150)

参数说明:

  • image: 输入灰度/二值化图像
  • threshold1: 低阈值,用于决定可能的边缘点。
  • threshold2: 高阈值,用于决定强边缘点。

2.8. 总结

步骤作用工具/算子
高斯滤波平滑图像,去除噪声cv2.GaussianBlur
梯度计算提取边缘强度与方向cv2.Sobel
非极大值抑制边缘细化自定义插值
双阈值链接连接可靠边缘,抑制伪边缘cv2.Canny

三、图像轮廓提取与绘制

图像轮廓是计算机视觉中一个非常关键的概念,它广泛应用于目标检测、图像分割、形状分析等领域。

3.1 什么是轮廓(Contours)

轮廓是将具有相同灰度值的像素点连接成线的过程。在图像中,轮廓通常用于表示物体的边界或形状。

轮廓与边缘的区别:

  • 边缘是强度变化的位置(如 Canny)
  • 轮廓是封闭的路径,更强调形状和结构
  • 边缘可能是离散点,轮廓是连续曲线

示意图:

image-20250726164247720


3.2 寻找轮廓的流程

轮廓提取的流程通常如下:

graph TD
A[彩色图像] --> B[灰度化]
B --> C[二值化]
C --> D[查找轮廓 \n cv2.findContours()]

3.3 OpenCV 提供了非常方便的函数:

contours, hierarchy = cv2.findContours(image, mode, method)
3.3.1 参数说明:
参数说明
image输入图像,必须是二值图像
mode轮廓检索模式(如下表)
method轮廓逼近方法(如下表)
contours返回的轮廓点坐标数组列表
hierarchy返回轮廓间的层级结构

3.3.2 mode 参数解释(轮廓层次结构)
mode 值含义
RETR_EXTERNAL只提取最外层轮廓(最常用)
RETR_LIST提取所有轮廓,但不构建父子关系
RETR_CCOMP提取所有轮廓,并将外层和内层分层保存
RETR_TREE提取所有轮廓并构建完整层次树结构

层次结构说明图(RETR_TREE):

hierarchy[i] = [next, previous, child, parent]

3.3.3 method 参数解释(轮廓点存储方式)
method 值含义
CHAIN_APPROX_NONE保存所有边界点
CHAIN_APPROX_SIMPLE压缩冗余点,只保留关键点(如直线只保留端点)
CHAIN_APPROX_TC89_L1使用 Teh-Chin 链码逼近算法,效率更高(较少使用)

3.4 绘制轮廓

查找到轮廓后,可以使用以下函数将轮廓画出来:

cv2.drawContours(image, contours, contourIdx, color, thickness)

参数说明

参数名含义
image输入/输出图像(会被修改)
contours找到的轮廓点数组
contourIdx要绘制的轮廓索引(-1 表示绘制所有)
color轮廓线颜色(BGR)
thickness线条粗细,负值表示填充区域

3.5 实战代码示例:

import cv2 as cv
from socks import PRINTABLE_PROXY_TYPES# 读取图像
img = cv.imread('../images/num.png')# 转换为灰度图像
img_gray =cv.cvtColor(img,cv.COLOR_BGR2GRAY)#二值化
_,img_binary = cv.threshold(img_gray,127,255,cv.THRESH_BINARY_INV)# 寻找轮廓
counters,hierarchy = cv.findContours(img_binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)print(counters)
print(len(counters))
print('-------')
print(hierarchy)# 绘制轮廓
cv.drawContours(img,counters,-1,(0,255,0),3,cv.LINE_AA)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

image-20250726165323496


3.6 小贴士:轮廓查找注意事项

  • 🔸 输入图像必须为二值图像(黑白),推荐使用 cv2.threshold()
  • 🔸 可以先做边缘检测(如 Canny),再轮廓提取。
  • 🔸 cv2.findContours() 会修改原图像,最好用拷贝版本。
  • 🔸 drawContours() 可以搭配 boundingRect()minAreaRect() 等函数做目标框选。

3.7总结

步骤内容
1️⃣灰度化原图
2️⃣二值化处理
3️⃣使用 cv2.findContours 提取轮廓
4️⃣使用 cv2.drawContours 绘制轮廓
5️⃣可结合形状分析、ROI 提取等进一步处理

四、绘制凸包

我们已经知道了如何获取轮廓点(contours)以及如何通过 cv2.convexHull() 得到 凸包点集。接下来,我们通过绘图的方式将凸包显示出来。


4.1 算法特点

在计算几何中,**穷举法(Brute Force)QuickHull是两种常见的凸包(Convex Hull)**构造算法,它们各有优缺点,适用于不同场景。下面为你简要整理两者特点,并通过表格进行对比:

1. 穷举法(Brute Force)

原理
遍历所有点对,判断这条边是否是凸包边:即判断所有其他点是否都在该边的同一侧。若是,则保留该边。

特点

  • 算法思想简单直观
  • 时间复杂度较高O(n3)O(n^3)O(n3)
  • 适合教学/小规模数据集
  • 实现容易理解,但不适合大数据场景。

2. QuickHull 算法

原理
类似快速排序的分治思想。先找出最左和最右的两个点作为“线段”,划分上下两部分递归寻找最外层点,逐步构造出凸包。

特点

  • 平均性能优良,时间复杂度大约为 O(nlog⁡n)O(n \log n)O(nlogn)
  • 适合中大型数据
  • 实现相对复杂,但效率更高;
  • 对输入数据分布较敏感(最坏 O(n2)O(n^2)O(n2))。

函数一览

函数功能
cv2.findContours()获取轮廓点
cv2.convexHull()根据轮廓点获取凸包点
cv2.polylines()根据点集绘制折线(或闭合多边形)
# 获取凸包点
import cv2 as cv# 读取图像
image_tu = cv.imread('../images/tu.png')# 转换为灰度图像
image_gray = cv.cvtColor(image_tu, cv.COLOR_BGR2GRAY)# 二值化处理
_,image_binary = cv.threshold(image_gray,127,255,cv.THRESH_BINARY)# 寻找轮廓
counters,_ = cv.findContours(image_binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)# 获取凸包
convex_hull= []
for cnt in counters:convex_hull.append(cv.convexHull(cnt))cv.polylines(image_tu,convex_hull,True,(255,0,0),3,cv.LINE_AA)
cv.imshow('binary',image_binary)
cv.imshow('tu',image_tu)
cv.waitKey(0)
cv.destroyAllWindows()

4.4 结果效果

假设你的原始图像中有一个不规则物体,该代码会:

  • 提取其轮廓
  • 计算包住这个物体的最小凸多边形(凸包)
  • 用线条将这个凸包标出

如图所示:

image-20250726165945562


4.5 应用场景总结

应用领域使用场景
手势识别识别手指个数:凸包与缺陷分析(defects)
目标检测将不规则轮廓转为规则包围多边形
图像压缩简化轮廓特征
安全区域包围任意散点区域

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

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

相关文章

GitHub 趋势日报 (2025年07月25日)

📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图1814Resume-Matcher985neko714Qwen3-Coder622OpenBB542BillionMail486hrms219hyper…

编程语言Java——核心技术篇(五)IO流:数据洪流中的航道设计

🌟 你好,我是 励志成为糕手 ! 🌌 在代码的宇宙中,我是那个追逐优雅与性能的星际旅人。 ✨ 每一行代码都是我种下的星光,在逻辑的土壤里生长成璀璨的银河; 🛠️ 每一个算法都是我绘制…

基于FPGA的16QAM软解调+卷积编码Viterbi译码通信系统,包含帧同步,信道,误码统计,可设置SNR

目录 1.引言 2.算法仿真效果 3.算法涉及理论知识概要 3.1 16QAM调制软解调原理 3.2 帧同步 3.3 卷积编码,维特比译码 4.Verilog程序接口 5.参考文献 6.完整算法代码文件获得 1.引言 基于FPGA的16QAM软解调卷积编码Viterbi译码通信系统开发,包含帧同步,高斯…

Python数据分析基础(二)

一、Numpy 常用函数分类概览函数类别常用函数基本数学函数np.sum(x)、np.sqrt(x)、np.exp(x)、np.log(x)、np.sin(x)、np.abs(x)、np.power(a, b)、np.round(x, n) 等统计函数np.mean(x)、np.median(x)、np.std(x)、np.var(x)、np.min(x)、np.max(x)、np.percentile(x, q) 等比…

Colab中如何临时使用udocker(以MinIO为例)

本文主要是想记录一下自己在Colab中用udocker启动一个MinIO的容器的过程。 1. 命令行配置环境 由于目前没有用到GPU,所以我选择的是CPU的环境。(内存12G)然后就可以在命令行里安装udocker了,并配置minio的环境 # 由于minio需要做两个端口映射&#xff0c…

rt-thread 5.2.1 基于at-start-f437开发过程记录

基于rt-thread 5.2.1 bsp/at/at32f437-start进行开发,记录详细过程,包括中间遇到的各种坑。 at32f437-start原理图 自己设计的电路板主要换了一块小封装的同系列芯片, 目标是移植opENer。 1. 开发环境 env长时间不用,有点忘了。这次新下载…

EMCCD相机与电可调变焦透镜的同步控制系统设计与实现

EMCCD相机与电可调变焦透镜的同步控制系统设计与实现 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家,觉得好请收藏。点击跳转到网站。 摘要 本文详细介绍了基于Python的EMCCD相机&#xff0…

前缀和-560.和为k的子数组-力扣(LeetCode)

一、题目解析1.子数组是数组中元素的连续非空序列2.nums[i]范围为[-1000,1000],存在负数3.由于2的题目条件,该题不能用双指针算法,不具备单调性 二、算法原理解法1:暴力解法->枚举 O(N^2)固定一个值,向后枚举数组和…

解决企业微信收集表没有图片、文件组件,不能收集图片的问题

问题: 企业微信里面的收集表功能,有一个图片收集的收集表,但是插入的组件没有收集图片的组件? 原因: 大概率是微盘未启用 解决方法: 1、登陆企业微信管理后台 企业微信 2、访问微盘页面,…

认识单片机

《认识单片机》课程内容 一、课程导入 在我们的日常生活中,有很多看似普通却充满智慧的小物件。比如家里的智能电饭煲,它能精准地控制煮饭的时间和温度,让米饭煮得香喷喷的;还有楼道里的声控灯,当有人走过发出声音时&a…

数据结构(2)顺序表算法题

一、移除元素1、题目描述2、算法分析 思路1:查找val值对应的下标pos,执行删除pos位置数据的操作。该方法时间复杂度为O(n^2),因此不建议使用。思路2:创建新数组(空间大小与原数组一致&#xff0…

汽车电子架构

本文试图从Analog Devices官网中的汽车解决方案视角带读者构建起汽车电子的总体架构图,为国内热爱和从事汽车电子行业的伙伴们贡献一份力量。 一 、汽车电子架构总览 整个汽车电子包括四个部分:车身电子(Body Electronics)、座舱与…

pycharm 2025 专业版下载安装教程【附安装包】

安装之前,请确保已经关闭所有安全软件(如杀毒软件、防火墙等)安装包 👇链接:https://pan.xunlei.com/s/VOU-5_L1KOH5j3zDaaCh-Z28A1# 提取码:6bjy下载 PyCharm2025专业版 安装包 并 进行解压运行 pycharm-2…

在 Java 世界里让对象“旅行”:序列化与反序列化

Java 生态里关于 JSON 的序列化与反序列化(以下简称“序列化”)是一个久经考验的话题,却常因框架繁多、配置琐碎而让初学者望而却步。本文将围绕一段极简的 JsonUtils 工具类展开,以 FastJSON 与 Jackson 两大主流实现为例&#x…

High Speed SelectIO Wizard ip使用记录

本次实验的目的是通过VU9P开发板的6个TG接口,采用固定连接的方式,即X和X-维度互联,其框图如下所示:IP参数配置通过调用High Speed SelectIO Wizard来实现数据通路,High Speed SelectIO Wizard ip有24对数据通道&#x…

Execel文档批量替换标签实现方案

问题背景需求:俺现网班级作为维度,批量导出每个班级学员的数据,excel的个数在1k左右,每一张表的人数在90左右。导出总耗时在10小时左右。代码编写完成并导出现网数据后,发现导出的标题错了。解决方案1.通过修改代码&am…

SpringBoot配置多数据源多数据库

Springboot支持配置多数据源。默认情况,在yml文件中只会配置一个数据库。如果涉及到操作多个数据库的情况,在同实例中(即同一个ip地址下的不同数据库),可以采用数据库名点数据库表的方式,实现跨库表的操作。…

Rocky9.4部署Zabbix7

一、配置安装源 rpm -Uvh https://repo.zabbix.com/zabbix/7.0/rocky/9/x86_64/zabbix-release-7.0-5.el9.noarch.rpm ​ yum clean all 二、安装Zabbix server,Web前端,agent yum install zabbix-server-mysql zabbix-web-mysql zabbix-nginx-conf z…

【Java】对象类型转换(ClassCastException)异常:从底层原理到架构级防御,老司机的实战经验

在开发中,ClassCastException(类转换异常)就像一颗隐藏的定时炸弹,常常在代码运行到类型转换逻辑时突然爆发。线上排查问题时,这类异常往往因为类型关系复杂而难以定位。多数开发者习惯于在转换前加个instanceof判断就…

探路者:用 AI 面试加速人才集结,为户外爱好者带来更专业的服务

作为深耕户外用品领域的知名品牌,探路者已构建起覆盖全国的销售服务网络,上千品种的产品矩阵更是为品牌在市场中站稳脚跟提供了有力支撑。对探路者来说,要持续为户外爱好者带来专业且贴心的体验,专业人才是核心支撑。然而&#xf…