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

day33和day34图像处理OpenCV

文章目录

  • 一、图像预处理
    • 12 图像梯度处理
      • 12.3 Sobel算子
      • 12.4 Laplacian算子
        • 1.原理:
        • 2.语法:
    • 13 图像边缘检测思路
      • 13.1 高斯滤波去噪点
      • 13.2 计算图像的梯度与方向
      • 13.3 非极大值抑制
      • 13.4 双阈值筛选
      • 13.5 Canny方法和使用
    • 14 绘制图像轮廓
      • 14.1 什么是轮廓
      • 14.2 寻找轮廓
        • 1. 语法
        • 2. mode参数
        • 3. method参数
      • 14.3 绘制轮廓
    • 15 凸包特征检测
      • 15.1获取凸包
      • 15.2 绘制凸包
    • 16 图像轮廓特征查找
      • 16.1 绘制外接矩形
      • 16.2 最小外接矩形
      • 16.3 最小外接圆

一、图像预处理

12 图像梯度处理

12.3 Sobel算子

  • 语法:sobel_image = cv2.Sobel(src, ddepth, dx, dy, ksize)

    • src:这是输入图像,通常应该是一个灰度图像(单通道图像)

    • ddepth:这个参数代表输出图像的深度,即输出图像的数据类型。在 OpenCV 中,-1 表示输出图像的深度与输入图像相同。

    • dx,dy:当dx=1,dy=0时,求x方向的一阶导数,即提取垂直边缘;当 dx=0,dy=1时,求y方向的一阶导数,即提取水平边缘。

    • ksize:Sobel算子的大小,可选择3、5、7,这里默认为3。

dx,dy如果同时为1,分别求出两个方向的梯度,最后求出总梯度:
G = G x 2 + G y 2 G={\sqrt{G x^{2}+G y^{2}}} G=Gx2+Gy2
这个计算方式和上面类似。

12.4 Laplacian算子

  • 该方法直接同时提取垂直和水平边缘,效果比Sobel算子好很多。

  • Laplacian算子是二阶边缘检测的典型代表,一/二阶边缘检测各有优缺点,可自行了解。

1.原理:

要看原函数的变化率,就看一阶导数。要找边缘点,就找的一阶导数的突变点,所以用一阶导数求极值,在这些极值的地方,二阶导数为0。所以也可以通过求二阶导计算梯度:
d s t = ∂ 2 f ∂ x 2 + ∂ 2 f ∂ y 2 d s t={\frac{\partial^{2}f}{\partial x^{2}}}+{\frac{\partial^{2}f}{\partial y^{2}}} dst=x22f+y22f
一维的一阶和二阶差分公式分别为:
∂ f ∂ x = f ( x + 1 ) − f ( x ) {\frac{\partial f}{\partial x}}=f(x+1)-f(x) xf=f(x+1)f(x)

∂ 2 f ∂ x 2 = f ( x + 1 ) + f ( x − 1 ) − 2 f ( x ) {\frac{\partial^{2}f}{\partial x^{2}}}=f(x+1)+f(x-1)-2f(x) x22f=f(x+1)+f(x1)2f(x)

提取前面的系数,那么一维的Laplacian滤波核是:
k = [ 1 − 2 1 ] k=[1~~-2~~~1] k=[1  2   1]
而对于二维函数f(x,y),两个方向的二阶差分分别是:
∂ 2 f ∂ x 2 = f ( x + 1 , y ) + f ( x − 1 , y ) − 2 f ( x , y ) {\frac{\partial^{2}f}{\partial x^{2}}}=f(x+1,y)+f(x-1,y)-2f(x,y) x22f=f(x+1,y)+f(x1,y)2f(x,y)

∂ 2 f ∂ y 2 = f ( x , y + 1 ) + f ( x , y − 1 ) − 2 f ( x , y ) {\frac{\partial^{2}f}{\partial y^{2}}}=f(x,y+1)+f(x,y-1)-2f(x,y) y22f=f(x,y+1)+f(x,y1)2f(x,y)

合在一起就是:
V 2 f ( x , y ) = f ( x + 1 , y ) + f ( x − 1 , y ) + f ( x , y + 1 ) + f ( x , y − 1 ) − 4 f ( x , y ) V^{2}f(x,y)=f(x+1,y)+f(x-1,y)+f(x,y+1)+f(x,y-1)-4f(x,y) V2f(x,y)=f(x+1,y)+f(x1,y)+f(x,y+1)+f(x,y1)4f(x,y)
同样提取前面的系数,那么二维的Laplacian滤波核就是:
k = [ 0 1 0 1 − 4 1 0 1 0 ] k=\left[\begin{array}{c c c}{0}&{1}&{0}\\ {1}&{-4}&{1}\\ {0}&{1}&{0}\end{array}\right] k= 010141010
这就是Laplacian算子的图像卷积模板,有些资料中在此基础上考虑斜对角情况,将卷积核拓展为:
k = [ 1 1 1 1 − 8 1 1 1 1 ] k=\left[\begin{array}{c c c}{1}&{1}&{1}\\ {1}&{-8}&{1}\\ {1}&{1}&{1}\end{array}\right] k= 111181111

2.语法:
  • cv2.Laplacian(src, ddepth)

    • 返回一个图像对象

    • src:这是输入图像

    • ddepth:这个参数代表输出图像的深度,即输出图像的数据类型。在 OpenCV 中,-1 表示输出图像的深度与输入图像相同。

13 图像边缘检测思路

不单单是算子,是完整的一整套方案。

13.1 高斯滤波去噪点

边缘检测本身属于锐化操作,对噪点比较敏感,所以需要进行平滑处理。

13.2 计算图像的梯度与方向

原理:

这里使用了sobel算子来计算图像的梯度值,在上一章节中,我们了解到sobel算子其实就是一个核值固定的卷积核,如下所示:
s o b e l ( 水平方向 ) = [ − 1 0 1 − 2 0 2 − 1 0 1 ] sobel(水平方向)=\left[\begin{array}{c c c}{{-1}}&{{0}}&{{1}}\\ {{-2}}&{{0}}&{{2}}\\ {{-1}}&{{0}}&{{1}}\end{array}\right] sobel(水平方向)= 121000121

s o b e l ( 垂直方向 ) = [ − 1 − 2 − 1 0 0 0 1 2 1 ] sobel(垂直方向)=\left[\begin{array}{c c c}{{-1}}&{{-2}}&{{-1}}\\ {{0}}&{{0}}&{{0}}\\ {{1}}&{{2}}&{{1}}\end{array}\right] sobel(垂直方向)= 101202101

首先使用sobel算子计算中心像素点的两个方向上的梯度 G x G_{x} Gx G y G_{y} Gy,然后就能够得到其具体的梯度值:
G = G x 2 + G y 2 G={\sqrt{G_{x}{}^{2}+G_{y}{}^{2}}} G=Gx2+Gy2
也可以使用 G = ∣ G x + G y ∣ G=|G_{x}+G_{y}| G=Gx+Gy来代替。在OpenCV中,默认使用 G = ∣ G x + G y ∣ G=|G_{x}+G_{y}| G=Gx+Gy来计算梯度值。

然后我们根据如下公式可以得到一个角度值

G y G x = tan ⁡ ( θ ) {\frac{G_{\mathrm{y}}}{G_{x}}}=\tan\,(\theta) GxGy=tan(θ)
θ = arctan ⁡ ( G y G x ) \theta=\arctan\,({\frac{G_{\mathrm{y}}}{G_{x}}}) θ=arctan(GxGy)
这个角度值其实是当前边缘的梯度的方向。通过这个公式我们就可以计算出图片中所有的像素点的梯度值与梯度方向,然后根据梯度方向获取边缘的方向。

a). 并且如果梯度方向不是0°、45°、90°、135°这种特定角度,那么就要用到插值算法来计算当前像素点在其方向上进行插值的结果了,然后进行比较并判断是否保留该像素点。这里使用的是单线性插值,通过A1和A2两个像素点获得dTmp1与dTmp2处的插值,然后与中心点C进行比较(非极大值抑制)。具体的插值算法请参考图像旋转实验。

b). 得到 θ \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°边缘;
在这里插入图片描述

13.3 非极大值抑制

在该步骤中,我们需要检查每个像素点的梯度方向上的相邻像素,并保留梯度值最大的像素,将其他像素抑制为零。假设当前像素点为(x,y),其梯度方向是0°,梯度值为G(x,y),那么我们就需要比较G(x,y)与两个相邻像素的梯度值:G(x-1,y)和G(x+1,y)。如果G(x,y)是三个值里面最大的,就保留该像素值,否则将其抑制为零。

13.4 双阈值筛选

经过非极大值抑制之后,我们还需要设置阈值来进行筛选,当阈值设的太低,就会出现假边缘,而阈值设的太高,一些较弱的边缘就会被丢掉,因此使用了双阈值来进行筛选,推荐高低阈值的比例为2:1到3:1之间,其原理如下图所示:

在这里插入图片描述

当某一像素位置的幅值超过最高阈值时,该像素必是边缘像素;当幅值低于最低像素时,该像素必不是边缘像素;幅值处于最高像素与最低像素之间时,如果它能连接到一个高于阈值的边缘时,则被认为是边缘像素,否则就不会被认为是边缘。也就是说,上图中的A和C是边缘,B不是边缘。因为C虽然不超过最高阈值,但其与A相连,所以C就是边缘。

13.5 Canny方法和使用

  • 方法内部自动实现:自适应二值化、高斯滤波、梯度计算等

    • 只是效果不如自己调用
  • 语法:

    • edges = cv2.Canny(image, threshold1, threshold2),即使读到的是彩色图也可以进行处理。
  • 参数:

    • image输入的灰度/二值化图像数据。

    • threshold1:低阈值,用于决定可能的边缘点。

    • threshold2:高阈值,用于决定强边缘点。

  • 案例

import cv2 as cv
img = cv.imread('./images/shudu.png')
# 转为灰度图
img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 二值化处理--手动处理
ret, img_binary = cv.threshold(img,127,255,cv.THRESH_BINARY)
# 高斯滤波----手动降噪
img_binary2 = cv.GaussianBlur(img_binary,(3,3),0)# canny方法
dst_img = cv.Canny(img,100,167)
# 显示
cv.imshow('dst_img',dst_img)
cv.imshow('img_binary2',img_binary2)
cv.waitKey(0)
cv.destroyAllWindows()

14 绘制图像轮廓

14.1 什么是轮廓

轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。相对于边缘,轮廓是连续的,边缘不一定连续,如下图所示。轮廓是一个闭合的、封闭的形状。
在这里插入图片描述

  • 轮廓的作用
    • 形状分析
    • 目标识别
    • 图像分割

14.2 寻找轮廓

在OpenCV中,使用cv2.findContours()来进行寻找轮廓,其原理过于复杂,这里只进行一个简单的介绍,具体的实现原理可参考:

https://zhuanlan.zhihu.com/p/107257870

  • 寻找轮廓我们需要对原始的图像进行灰度化、二值化的处理,令目标区域显示为白色,其他区域显示为黑色
1. 语法
  • contours,hierarchy = cv2.findContours(image,mode,method)

  • 返回值:[ 轮廓点坐标 ] 和 [ 层级关系 ]。

    • contours:表示获取到的轮廓点的列表。检测到有多少个轮廓,该列表就有多少子列表,每一个子列表都代表了一个轮廓中所有点的坐标。

    • hierarchy:表示轮廓之间的关系。对于第i条轮廓, h i e r a r c h y [ i ] [ 0 ] hierarchy[i][0] hierarchy[i][0], h i e r a r c h y [ i ] [ 1 ] hierarchy[i][1] hierarchy[i][1] , h i e r a r c h y [ i ] [ 2 ] hierarchy[i][2] hierarchy[i][2] ,$ hierarchy[i][3]$分别表示其后一条轮廓、前一条轮廓、(同层次的第一个)子轮廓、父轮廓的索引(如果没有相应的轮廓,则对应位置为-1)。该参数的使用情况会比较少。

  • 参数:

    • image:表示输入的二值化图像

    • mode:表示轮廓的检索模式。

    • method:轮廓的表示方法。

2. mode参数

轮廓查找方式。返回不同的层级关系。

mode参数共有四个选项分别为:RETR_LIST,RETR_EXTERNAL,RETR_CCOMP,RETR_TREE。

  1. RETR_EXTERNAL

表示只查找最外层的轮廓。并且在hierarchy里的轮廓关系中,每一个轮廓只有前一条轮廓与后一条轮廓的索引,而没有父轮廓与子轮廓的索引。

  1. RETR_LIST

表示列出所有的轮廓。并且在hierarchy里的轮廓关系中,每一个轮廓只有前一条轮廓与后一条轮廓的索引,而没有父轮廓与子轮廓的索引。

  1. RETR_CCOMP

表示列出所有的轮廓。并且在hierarchy里的轮廓关系中,轮廓会按照成对的方式显示。

RETR_CCOMP 模式下,轮廓被分为两个层级:

  • 层级 0:所有外部轮廓(最外层的边界)。
  • 层级 1:所有内部轮廓(孔洞或嵌套的区域)。
  1. RETR_TREE

表示列出所有的轮廓。并且在hierarchy里的轮廓关系中,轮廓会按照树的方式显示,其中最外层的轮廓作为树根,其子轮廓是一个个的树枝。

3. method参数

轮廓存储方法。轮廓近似方法。决定如何简化轮廓点的数量。就是找到轮廓后怎么去存储这些点。

method参数有三个选项:CHAIN_APPROX_NONE、CHAIN_APPROX_SIMPLE、CHAIN_APPROX_TC89_L1。

  • CHAIN_APPROX_NONE表示将所有的轮廓点都进行存储

  • CHAIN_APPROX_SIMPLE表示只存储有用的点,比如直线只存储起点和终点,四边形只存储四个顶点,默认使用这个方法;

对于mode和method这两个参数来说,一般使用RETR_EXTERNAL和CHAIN_APPROX_SIMPLE这两个选项。

14.3 绘制轮廓

轮廓找出来后,其实返回的是一个轮廓点坐标的列表,因此我们需要根据这些坐标将轮廓画出来,因此就用到了绘制轮廓的方法。

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

  • image:原始图像,一般为单通道或三通道的 numpy 数组。

  • contours:包含多个轮廓的列表,每个轮廓本身也是一个由点坐标构成的二维数组(numpy数组)。

  • contourIdx:要绘制的轮廓索引。如果设为 -1,则会绘制所有轮廓。根据索引找到轮廓点绘制出来。默认是-1。

  • color:绘制轮廓的颜色,可以是 BGR 值或者是灰度值(对于灰度图像)。

  • thickness:轮廓线的宽度,如果是正数,则画实线;如果是负数,则填充轮廓内的区域。

  • 示例:

# ================寻找轮廓=============================
# 读取、转灰度图
img = cv.imread('./images/num.png')
num = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 二值化 === 要使用反阈值法,把内容变成  黑底白字
_, binary = cv.threshold(num,127,255,cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
# 查找轮廓
contours, hierarchy = cv.findContours(binary,mode=cv.RETR_EXTERNAL,method=cv.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv.drawContours(img, contours, -1, (0,255,0), 3)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

15 凸包特征检测

通俗的讲,凸包其实就是将一张图片中物体的最外层的点连接起来构成的凸多边形,它能包含物体中所有的内容。

凸包检测常用在物体识别、手势识别、边界检测等领域。

凸包查找的常用方法:穷举法和QuickHull法

15.1获取凸包

  • pts = cv.convexHull( )
    • 返回一个二维 numpy 数组,每个元素是一维数组,代表一个多边形的一系列顶点坐标。

15.2 绘制凸包

cv2.polylines(image, pts, isClosed, color, thickness=1)

  • image:要绘制线条的目标图像,它应该是一个OpenCV格式的二维图像数组(如numpy数组)。

  • pts:一个二维 numpy 数组,每个元素是一维数组,代表一个多边形的一系列顶点坐标。

  • isClosed:布尔值,表示是否闭合多边形,如果为 True,会在最后一个顶点和第一个顶点间自动添加一条线段,形成封闭的多边形。

  • color:线条颜色,可以是一个三元组或四元组,分别对应BGR或BGRA通道的颜色值,或者是灰度图像的一个整数值。

  • thickness(可选):线条宽度,默认值为1。

  • 案例

img = cv.imread('./images/tu.png')
# 转为灰度图
num = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 二值化
_, binary = cv.threshold(num, 127, 255, cv.THRESH_OTSU + cv.THRESH_BINARY)
# 查找轮廓
c, h = cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
# 查找凸包
pts = cv.convexHull(c[0])# 绘制凸包点
cv.polylines(img,[pts],True,(0,255,0),3,cv.LINE_AA)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

16 图像轮廓特征查找

  • 图像轮廓特征查找其实就是他的外接轮廓。
  • 应用:
    • 图像分割
    • 形状分析
    • 物体检测与识别
  • 根据轮廓点进行,所以要先找到轮廓。
    • 先灰度化、二值化。目标物体白色,非目标物体黑色,选择合适的二值化方式。

16.1 绘制外接矩形

通过轮廓点就可以找到最上、最下、最左、最右的四个坐标, X m i n 、 X m a x 、 Y m i n 、 Y m a x X_{min}、X_{max}、Y_{min}、Y_{max} XminXmaxYminYmax。就可以绘制出矩形。

  • 使用前面绘制矩形的方法:cv.rectangle(img,左上点, 右下点, 颜色,大小)
    • 使用 x,y,w,h = cv.boundingRect( 存放轮廓点的数组 ) 找到左上和右下点
  • 示例:
num = cv.imread("./images/num.png")
img = num.copy()
# 转灰度
img2 = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 二值化
_,new_img = cv.threshold(img2,127,255,cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
# 查找轮廓
c,h=cv.findContours(new_img,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv.drawContours(img,c,-1,(0,255,0),3)
# 绘制外接矩形
for i in c:# 寻找每一个左上和右下坐标x,y,w,h = cv.boundingRect(i)# 绘制矩形cv.rectangle(img,(x,y),(x+w,y+h),(25,205,125),3)cv.imshow("img",img)
cv.waitKey(0)
cv.destroyAllWindows()

16.2 最小外接矩形

寻找最小外接矩形使用的算法叫做旋转卡壳法。下面简单说明一下旋转卡壳法的思路:

  • 在上一章节中,我们了解到了凸包的概念,而旋转卡壳法就是基于凸包点进行的,旋转卡壳法有一个很重要的前提条件:绘制的外接矩形有一条边与凸包的一条边共线

  • 以共线边为外接矩形的边,找出外接矩形,计算面积;这样计算出不同共边得到的面积,找出最小面积。

  • 关键 三步 语法:

    • rect = cv2.minAreaRect(cnt)
      • cnt参数:一维的轮廓坐标,需要遍历找到的二维轮廓数组传入
      • 返回值:rect 结构通常包含中心点坐标 (x, y)、宽度 width、高度 height 和旋转角度 angle
    • box = cv2.boxPoints(rect).astype(np.int32)
      • astype(int)方法:保证返回的数据是整数并且防止溢出
      • rect参数:上面
      • 返回值:一个形状为 4行2列的数组,每一行代表一个点的坐标(x, y),顺序按照逆时针或顺时针方向排列
    • cv2.drawContours(image, contours, contourIdx, color, thickness)
      • 返回的box也是轮廓点坐标,所以使用画凸包的方式画出矩形
  • 示例

num = cv.imread("./images/num.png")
img = num.copy()
# 转灰度
img2 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 二值化
_, new_img = cv.threshold(img2, 127, 255, cv.THRESH_OTSU + cv.THRESH_BINARY_INV)
# 查找轮廓
c, h = cv.findContours(new_img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)# 绘制最小外接矩形
for i in c:  # 关键 3步rect = cv.minAreaRect(i)box = cv.boxPoints(rect).astype(np.int32)cv.drawContours(img,[box],0,(0,0,255),2,cv.LINE_AA)cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()

16.3 最小外接圆

  • 语法:
    • **center, radius = cv2.minEnclosingCircle(points) **
    • 参数
      • points:输入参数图片轮廓数据
    • 返回值:
      • center:圆心坐标的二元组 (x, y)
      • radius半径
      • 圆心和半径都不是整数,需要转化np.int_( [x,y,r] )
    • cv2.circle(img, center, radius, color, thickness)
      • 通过前面的画圆方法,画圆
  • 示例:
img = cv.imread('./images/num.png')
# 灰度化
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 二值化
_, binary = cv.threshold(gray, 127, 255, cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
# 查找轮廓
c, h = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# 遍历轮廓
for i in c:# 获取最小外接圆(x, y), r = cv.minEnclosingCircle(i)# 数据取整x,y,r = np.int_([x,y,r])# 画圆cv.circle(img,(x,y),r,(0,255,0),3,cv.LINE_AA)cv.imshow('img', img)
cv.waitKey(0)
cv.destroyAllWindows()

相关文章:

day33和day34图像处理OpenCV

文章目录 一、图像预处理12 图像梯度处理12.3 Sobel算子12.4 Laplacian算子1.原理:2.语法: 13 图像边缘检测思路13.1 高斯滤波去噪点13.2 计算图像的梯度与方向13.3 非极大值抑制13.4 双阈值筛选13.5 Canny方法和使用 14 绘制图像轮廓14.1 什么是轮廓14.…...

电脑硬盘常见的几种接口类型

一、传统接口(机械硬盘为主) 1. SATA 接口(Serial ATA) 特点: 最主流的机械硬盘(HDD)接口,广泛用于台式机和笔记本电脑。传输速度较慢,理论最大带宽为 6 Gbps&#xff…...

Windows网络及服务:制作系统盘

今天我要介绍的是一个比较有意思且好玩的一个小玩意儿:关于系统盘的制作; 注明:对于系统盘的制作,以及接下来的课程,基本是作为动手课业来进行的,这也是作为程序员的必要进行的一项活动。 对于系统盘&…...

Docker Compose 使用实例

文章目录 一、Docker Compose 简介二、安装 Docker Compose三、基础配置文件示例(docker-compose.yml)四、关键配置解析五、常用命令六、完整项目示例(Node.js MySQL Nginx)七、高级功能八、最佳实践九、调试技巧 一、Docker Co…...

系统架构师2025年论文《论基于UML的需求分析》

论基于 UML 的需求分析 摘要: 2018 年 3 月 1 日至 12 月 20 日,我参加了 “某市医院预约挂号系统” 项目的开发,担任系统架构师的工作。该项目是某市医院信息化建设的重要组成部分,目标是:优化医院挂号流程,提高患者就医体验,规范医院号源管理,实现患者预约挂号、医…...

Uniapp 自定义TabBar + 动态菜单实现教程(Vuex状态管理详解)

大家好,我是一诺。今天跟大家分享一下uniapp 封装自定义底部导航栏(TabBar) 过程中的思考和实践。通过本文,你将学会如何打造一个功能完善、可自由定制的TabBar组件! 先看效果: 支持自定义图标和样式动态…...

4月21日日记

新的一周开始了,好消息是未来这两周都每周只用上3天课,因为这周四五是运动会,下周四五是五一! 非常好的周一!收到了wxx和san还有小林的礼物!! wxx的是一个定制的有小排球的蓝牙影响&#xff0…...

2025高频面试算法总结篇【其他】

文章目录 直接刷题链接直达LRU Cache买卖股票的最佳时机系列实现一个HashMap环形链表寻找重复数缺失的第一个正数螺旋矩阵字符串相乘分发糖果 直接刷题链接直达 LRU Cache 头尾两个伪节点(避免判断) 双向链表146. LRU 缓存 买卖股票的最佳时机系列 121…...

vue项目中使用antvX6(可拖拽,vue3)

参考 先知demons 这位大佬的这篇文章:https://blog.csdn.net/wzy_PROTEIN/article/details/136305034?utm_mediumdistribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-136305034-blog-136032209.235v43pc_blog_bottom_relevance_ba…...

文档处理控件Aspose.Words 教程:在 Word 中删除空白页完整指南

Word 文档中的空白页总是令人烦恼。如果您想从 Word 文档中删除空白页,以获得更清晰的演示文稿或整理文件,那么您来对地方了。本指南涵盖了使用 Aspose.Words编码解决方案和在 Microsoft Word 中手动删除方案,让您可以灵活地选择最适合自己的…...

自动驾驶最新算法进展

自动驾驶技术的算法进展迅速,涵盖感知、预测、规划、端到端学习等多个领域。以下是2023年至2024年的关键进展及实例: 1. ‌感知与融合‌ ‌BEVTransformer的进化‌:特斯拉的Occupancy Networks升级至支持动态场景建模,结合NeRF技术…...

OpenCV训练题

一、创建一个 PyQt 应用程序,该应用程序能够: 使用 OpenCV 加载一张图像。在 PyQt 的窗口中显示这张图像。提供四个按钮(QPushButton): 一个用于将图像转换为灰度图一个用于将图像恢复为原始彩色图一个用于将图像进行…...

34、Spark实现读取XLS文件

需求背景: 有一些xls大文件数据。使用spark-excel(spark-excel)来读取时,文件太大会oom;工具提供的流式读取参数:maxRowsInMemory 也只支持xlsx类型文件。搜索了poi流式读取xls的方案,HSSFEvent…...

为什么RPN生成的候选框,要使用rcnn来进行分类和回归操作?

一句大白话总结:RPN是广撒网捕鱼,RCNN是细化鱼的分类和具体尺寸 在目标检测任务中,RPN(区域提议网络) 生成的候选框需要经过 RCNN(如 Fast R-CNN、Faster R-CNN) 进行分类和回归,这…...

固定总价合同工程范围变更,如果规避风险

一、合同签订阶段 工程范围的锁定 清单式列举 兜底条款:在合同附件中以 “正负零以上主体结构”“XX 型号设备采够” 等具体描述界定承包范围,同时约定 “超出本附件描述的工程内容视为变更”111。 设计深度要求:对于 EPC 项目,需…...

windows传文件给mac, linux或者其他windows

如果你想把你本地windows的文件传递给mac, linux或者其他windows电脑, 你会使用什么方法呢? 方法一 经常写python的朋友, 肯定会说, 我会用 SimpleHTTPServer python -m SimpleHTTPServer 8000生成一个超链接, 然后在其他机器上直接下载这个链接. 方法二 scp命令 Use SC…...

AI音乐解决方案:1分钟可切换suno、udio、luno、kuka等多种模型,suno风控秒切换 | AI Music API

你有没有觉得,suno风控来了,就要停服了? 你有没有觉得,对接多种音乐模型,让你很疲乏? 你有没有觉得,音乐模型,中文咬字不清楚,让你很苦恼? 别怕&#xff0…...

LeetCode 热题100题解(Java版本)

一、哈希 1、两数之和 https://leetcode.cn/problems/two-sum/?envType=study-plan-v2&envId=top-100-liked使用HashMap,遍历数组,判断当前元素的“补数”是否存在,如果存在直接返回结果,否则在Map中记录当前元素及其下标。 时间复杂度 O(n) 空间复杂度 O(n) class …...

突破传统!SEARCH-R1如何让LLM与搜索引擎协同推理?

大语言模型(LLMs)虽强大,但在复杂推理和获取最新信息方面存在局限。本文介绍的SEARCH-R1框架,通过强化学习让LLMs能自主与搜索引擎交互,在多个问答数据集上性能大幅提升。想知道它是如何做到的吗?快来一探究…...

C语言复习笔记--字符函数和字符串函数(下)

在上篇我们了解了部分字符函数及字符串函数,下面我们来看剩下的字符串函数. strstr 的使用和模拟实现 老规矩,我们先了解一下strstr这个函数,下面看下这个函数的函数原型. char * strstr ( const char * str1, const char * str2); 如果没找到就返回NULL指针. 下面我们看下它的…...

Git SSH 密钥多个 Git 来源

1. 生成 SSH 密钥 ssh-keygen -t rsa -b 4096 -C "997959066qq.com" 2. 输入指定路径 3. 增加 config文件在.ssh文件下 # GitHub 主账户 Host github.dis.comHostName github.disney.comUser gitIdentityFile ~/.ssh/id_rsa# 其他 Git 服务器 Host github.comHost…...

华为盒式交换机堆叠配置

1. 堆叠线缆连线图(如下图) 2. 配置Swtich1: [HUAWEI] sysname Switch1 [Switch1] interface stack-port 0/1 [Switch1-stack-port0/1] port interface xgigabitethernet 0/0/3 xgigabitethernet 0/0/4 enable Warning: Enabling stack function may cause configuration l…...

map和set的使用

序列式容器和关联式容器 c标准库为我们提供了多种容器类型,可以大体分为两类:序列式容器和关联式容器。 序列式容器按照线性顺序储存数据,元素的位置取决与插入的时间和地点。关联式容器基于键值对存储元素,提供高效的键查找能力…...

VMware制作Windows虚拟机模板注意点

1 、删除右下角的热删除 这个是必须的!虚拟机的高级参照中添加devices.hotplug “FALSE”,关闭USB设备热插拔,防止用户把虚拟桌面的网卡删除掉。 2、移除CD/DVD驱动器 这个建议!移除CD/DVD驱动器,此项操作…...

公有云攻防5(云函数)

Serverless概述 无服务器(Serverless)不是表示没有服务器,而是表示当您在使用Serverless时,您无需关心底层的资源,也无需登录服务器和优化服务器,只需关注最核心的代码片段,即可跳过复杂的、繁琐的基本工作。 Serverless 拥有近乎无限的扩容能力,空闲时,不运行任何资…...

【计算机网络】第五章 局域网技术

以太网技术 以太网的诞生 网络适配器和MAC地址 单播MAC地址 广播MAC地址 CSMA/CD协议 CSMA/CD协议的基本原理 共享式以太网---广播特性 MA多址接入 CS载波监听---先听后说 CD碰撞检测---边听边说 载波监听检测到总线空闲,但总线并不一定空闲。 使用CSMA/CD协议的…...

傲来云分享,负载均衡:提升网站性能与稳定性

在网站或应用的流量不断增加时,单台服务器往往无法承载过多的并发请求,导致性能下降和响应延迟。负载均衡技术正是为了解决这个问题,它可以将流量分发到多台服务器,从而提高系统的可扩展性、处理能力和可靠性。今天,我…...

Python基础总结(九)之推导式

文章目录 一、列表推导式1.1 列表推导式的格式1.2 列表推导式的注意事项1.3 列表推导式示例 二、 字典推导式2.1 字典推导式格式2.2 字典推导式注意事项2.3 字典推导式示例 三、 元组推导式3.1 元组推导式格式3.3 元组推导式示例 Python中的推导式有列表推导式,字典…...

程序员学商务英文之Terms of Payment Packing

Dia-3: Packing 1 包装-1 1. I’m here to improve my communication skill of English. 我来这里是为了提升我的英文沟通技能。 2. What a co-incidence! Fancy meeting you here. 这么巧!真没想到在这见到你。 3. Some birds aren’t meant to be caged…...

学生管理系统项目中的相关问题总结

目录 1. 项目中哪里体现出了封装性及其好处? 2. 项目中的setter/getter模式与封装性 什么是setter/getter?有什么用?怎么自动生成? 3.项目中某些类的toString()方法 4. 项目中几个常用方法解析 5. 项目中的面向对象设计 1…...

AI驱动下的企业学习:人力资源视角下的范式重构与价值觉醒

一、传统企业学习体系的系统性失效 当企业学习市场规模突破3600亿美元,人均年投入达1400美元的历史高位时,这场看似繁荣的图景背后却暗藏结构性危机。正如一份2024年研究报告所指出的,66%的企业仍倾向于通过外部招聘而非内部培养获取AI人才&…...

工厂模式:简单工厂模式

工厂模式 简单工厂模式&#xff1a;子类对象较多&#xff0c;则引入工厂类来创建 简单工厂模式 流程&#xff1a; 实例&#xff1a; 某电视机厂为各个品牌代工生产电视机&#xff0c;可以使用简单工厂的模式来实现 #include <iostream> #include <vector> using…...

Java并发编程-线程池

Java并发编程-线程池 线程池运行原理线程池生命周期线程池的核心参数线程池的阻塞队列线程池的拒绝策略线程池的种类newFixedThreadPoolnewSingleThreadExecutornewCachedThreadPoolnewScheduledThreadPool 创建线程池jdk的Executors(不建议&#xff0c;会导致OOM)jdk的ThreadP…...

ios17 音频加载失败问题

现象&#xff1a; 项目中有2个MP3 格式的音频&#xff0c;在iOS17 下 一个可以播&#xff0c;一个不能播&#xff0c;但是在浏览器可 正常播放 原因&#xff1a; 不能播的mp3是因为其编码格式为mpeg-4 AAC 编码格式 正常的mpeg audio 是可以播放的 解决&am…...

HarmonyOS:Navigation实现导航之页面设置和路由操作

导读 设置标题栏模式设置菜单栏设置工具栏路由操作页面跳转页面返回页面替换页面删除移动页面参数获取路由拦截 子页面页面显示类型页面生命周期页面监听和查询 页面转场关闭转场自定义转场共享元素转场 跨包动态路由系统路由表自定义路由表 示例代码 Navigation组件适用于模块…...

ADB -> pull指令拉取手机文件到电脑上

ADB Pull命令 在Android开发中&#xff0c;ADB的pull命令可以帮助我们将文件从设备拷贝到电脑上。 基本语法 adb pull <设备文件路径> [本地目标路径]<设备文件路径>&#xff1a;必需参数&#xff0c;指定要拉取的设备上的文件或文件夹[本地目标路径]&#xff1…...

Android Studio打开xml布局文件内存会快速增加如何设置

打开xml布局文件内存快速增加的原因是预览设置问题&#xff0c;直接在file-setting-editor-ui tools-editor view mode-resource: 选择code 就好了...

Spring Boot集成Keycloak

前言 本文参考A Quick Guide to Using Keycloak with Spring Boot&#xff0c;整理实战中遇到的问题。 Docker 安装 Keycloak 下载镜像 quay下载镜像 docker pull quay.io/keycloak/keycloak 失败的话&#xff0c;可再次尝试。 启动keycloak docker run -p 6060:8080 -…...

实验七 shell程序设计

实验七 shell程序设计 一、实验目的 理解shell的工作原理&#xff0c;学会编写shell脚本。 二、实验内容 1.编写不同功能的脚本程序。 2.利用chmod修改文件权限。 3.掌握脚本文件执行的方法。 三、主要实验步骤 1.创建一个名为zs_lab7的目录&#xff0c;下边实验步骤都在…...

FlaskRestfulAPI接口的初步认识

FlaskRestfulAPI 介绍 记录学习 Flask Restful API 开发的过程 项目来源&#xff1a;【Flask Restful API教程-01.Restful API介绍】 我的代码仓库&#xff1a;https://gitee.com/giteechaozhi/flask-restful-api.git 后端API接口实现功能&#xff1a;数据库访问控制&#xf…...

自定义错误码的必要性

为什么要使用错误码&#xff0c;直接返回一个错误信息不好么&#xff1f; 下面介绍一下&#xff0c;在程序开发中使用错误码的必要性~ 便于排查问题 想象你开了一家奶茶店&#xff0c;顾客下单后可能出现各种问题&#xff1a; 没珍珠了​​&#xff08;错误码&#xff1a;50…...

快手砍掉本地生活的门槛

一场本地商家的效率革命。 作者|景行 编辑|杨舟 “两斤鸡翅根七块九&#xff0c;两盒蓝莓九块钱&#xff0c;两公斤卫生纸十四块九一提。” 这是朝阳佳惠超市&#xff0c;在快手一则普通的短视频内容。 佳惠超市在辽宁省朝阳市有22家分店&#xff0c;打开佳惠超市的相关快手…...

Python+Word实现周报自动化的完整流程

一、技术方案概述 自动化报表解决方案基于以下技术组件&#xff1a; Python 作为核心编程语言python-docx 库用于处理 Word 文档pandas 库用于数据处理和分析matplotlib 或 plotly 库用于数据可视化Word 模版作为报表的基础格式 这种方案的优势在于&#xff1a;保留了 Word 文…...

PCIE Spec ---Base Address Registers

7.5.1.2.1 Base Address Registers (Offset 10h - 24h) 在 boot 到操作系统之前&#xff0c;系统软件需要生产一个内存映射的 address map &#xff0c;用于告诉系统有多少内存资源&#xff0c;以及相应功能需要的内存空间&#xff0c;所以在设备的 PCI 内存空间中就有了这个 …...

list的学习

list的介绍 list文档的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一…...

numpy、pandas内存优化操作整理

前言 python作为一款不怎么关注数据类型的语言&#xff0c;不同类型的数据可以往同一个变量中放置 这也就直接导致&#xff0c;作为熟悉C这种一个变量只有一个类型的程序员来说&#xff0c;在解读python程序时&#xff0c;想搞清楚变量中到底存的是什么数据类型的时候时常很头…...

【OSG学习笔记】Day 5: 坐标系与变换节点(Transform)

在前面的学习中,我们对 OpenSceneGraph(OSG)有了基础的认识。 今天,我们将深入探讨 OSG 中的坐标系和变换节点(Transform),并通过平移、旋转、缩放模型以及父子节点层级变换的实战操作,加深对这些概念的理解。 坐标系 1. 基础坐标系 在 OSG 里,使用的是右手坐标系…...

使用 Logstash 迁移 MongoDB 数据到 Easysearch

大家好&#xff01;在前面的文章中&#xff0c;我们已经详细介绍了如何通过 Logstash 和 Canal 工具实现 MySQL 数据向 Easysearch 的迁移。如果您正在使用 MongoDB 作为数据存储&#xff0c;并希望将其数据迁移到 Easysearch 中&#xff0c;这篇指南或许能为您提供一些帮助。 …...

在线查看【免费】vsd, vsdx/wmf, emf /psd, eps/pdf ,ofd, rtf/xmind/bpmn/eml/epub文件格式网

可以免费在线查看 .docx/wps/Office/wmf/ psd/ psd/eml/epub/dwg, dxf/ txt/zip, rar/ jpg/mp3 m.gszh.xyz m.gszh.xyz 免费支持以下格式文件在线查看类型 支持 doc, docx, xls, xlsx, xlsm, ppt, pptx, csv, tsv, dotm, xlt, xltm, dot, dotx, xlam, xla, pages 等 Office 办…...

富诺健康旗下运动营养品牌力爆(LIPOW):以冠军精神定义运动营养新时代

在全民健身热潮持续升温的今天&#xff0c;运动已不仅是竞技场上的较量&#xff0c;更是普通人突破自我的健康生活方式。《全民健身计划&#xff08;2021-2025年&#xff09;》中指出&#xff0c;“十三五”时期&#xff0c;全民健身国家战略深入实施&#xff0c;全民健身公共服…...