从车道检测项目入门open cv

前提声明:非常感谢b站up主 嘉然今天吃带变,感谢其视频的帮助。同时希望各位大佬积积极提出宝贵的意见。😊😊😊(❁´◡`❁)(●’◡’●)╰(°▽°)╯

github地址:https://github.com/lizhongzheng13/openCV_Lane_Detection/tree/main

视频地址:从车道检测项目入门open cv

基础知识

cv2.imread & cv2.imshow & cv2.imwrite
 import cv2 as cvimg = cv.imread("img.png", cv.IMREAD_GRAYSCALE) #将图片转为灰度图

但是当前会存在一些问题,图片会闪一下,看不清楚,所以我们可以加上阻塞 cv2.waitKey()函数

#完整版
import cv2 as cvimg = cv.imread("img.png", cv.IMREAD_GRAYSCALE)
print(type(img))
print(img.shape)
cv.imshow('image', img)
k = cv.waitKey(0)  # 阻塞 #k相当于检测你的输入的ascii值
print(k)
# while True:
#     if cv.waitKey(0) == ord('q'):
#         cv.destroyAllWindows()
#     else:
#         img = cv.imread("img.png", cv.IMREAD_GRAYSCALE)cv.imwrite("img_gray.png", img)#生成img图片,保存到当前目录中~

效果展示

原始图像:

image-20250428092853043

灰度图:

image-20250428092929086

Canny边缘检测

通过求取图像上每一个像素点周边图像像素变化的梯度,来确定这个点是否是边缘。

image-20250428102959222

梯度的方向一般总是与边界垂直,梯度的方向被归为四类:垂直、水平和两个对角线(即,0度、45度、90度和135度四个方向)。

image-20250428104012729

我们现在的想法是设置一个阈值,当梯度大于阈值时,我们可以认为该点是边缘。但是随之而来的是,图片会产生一些毛边或者光线,角度等问题,导致可能会误判。

image-20250428105216769

为了解决这个问题,我们采用双阈值的方法,一个上阈值,一个下阈值。

image-20250428105314881

我们认为高于上阈值的点为强边缘,在上阈值和下阈值之间的我们认为是弱边缘。

我们认为只有弱边缘与强边缘相连的话,才是边缘。B不认为是边缘,可能是噪声;C与A强边缘相连,我们认为C是边缘。

import cv2img = cv2.imread("img.png", cv2.IMREAD_GRAYSCALE)edge_img = cv2.Canny(img, 190, 350)  # 下边缘和上边缘的阈值设定 #需要自行更改
cv2.imshow("edge", edge_img)
cv2.waitKey(0)
image-20250429203018189

当上边缘和下边缘都升高时,边缘显示会越来越少。


ROI mask

简单来讲就是类似于抠图,就是剔除无关信息的边缘。

roi : region of interest 感兴趣的区域

​ 数组切片

​ 布尔运算(与运算)

image-20250428111139930
  • cv2.fillPoly 是 OpenCV 中的一个函数,用于在图像中填充多边形区域。它常用于绘制、遮罩或标记图像中的特定区域。通过指定多边形的顶点,cv2.fillPoly 可以将这些区域填充为指定的颜色。

  • cv2.bitwise_and 是 OpenCV 中的一个函数,用于对两个图像或数组进行按位与(bitwise AND)操作。按位与操作是逐像素进行的,只有当两个图像的对应像素都为非零值时,结果图像的该像素才为非零值。

    • 图像遮罩

      • 使用掩码提取图像的特定区域。例如,将一个形状(如矩形、圆形或多边形)作为掩码,只保留掩码内的图像内容。
    • 图像合成

      • 将两个图像的特定部分组合在一起。
    • 图像处理

      • 在图像处理中,按位与操作常用于对图像进行区域选择或区域遮挡。

图像以矩阵np.array形式存储在内存中

​ np.zeros_like : np.zeros_like 是 NumPy 库中的一个函数,用于创建一个与给定数组形状和数据类型相同的数组,但所有元素都初始化为零。

# @Author : LiZhongzheng
# 开发时间  :2025-04-28 17:30
import cv2
import numpy as npedge_img = cv2.imread("edge_img.png", cv2.IMREAD_GRAYSCALE)
mask = np.zeros_like(edge_img)  # 获取一个与edge_img大小相同的数组
mask = cv2.fillPoly(mask, np.array([[[0, 569], [661, 195], [914, 248], [979, 592]]]),color=255)  # array中的存放的是想要识别区域的四个顶点 #顺序为左下、左上、右上、右下masked_edge_img = cv2.bitwise_and(edge_img, mask)
# cv2.imshow('mask', mask)
# cv2.waitKey(0)
cv2.imshow("edged", masked_edge_img)
cv2.waitKey(0)
image-20250429202953080

霍夫变换

提取图片中的直线。

注意:霍夫变换是针对灰度图的。

image-20250428191915811 image-20250428192232916 image-20250428192253353

min是最短线段的长度,max是两点之间的最大距离,超过这个距离就不认为是线段了。

  • 首先经过 cv2.HoughLinesP()函数获取到所有的线条,然后计算线条的斜率,根据斜率的正负判断是左车道线还是右车道线。

    • # @Author : LiZhongzheng
      # 开发时间  :2025-04-29 8:54
      import cv2
      import numpy as npdef calculate_slope(line):"""计算线段line的斜率:param line: np.array([[x_1, y_1, x_2, y_2]]):return:"""x_1, y_1, x_2, y_2 = line[0]return (y_2 - y_1) / (x_2 - x_1)edge_img = cv2.imread('masked_edge_img.jpg', cv2.IMREAD_GRAYSCALE)
      # 获取所有线段
      lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40,maxLineGap=20)
      # 按照斜率分成车道线
      left_lines = [line for line in lines if calculate_slope(line) > 0]
      right_lines = [line for line in lines if calculate_slope(line) < 0]print("left_lines =", len(left_lines))
      print("right_lines =", len(right_lines))
      

离群值过滤

剔除出因为误差而被识别出的直线。

如何分解出噪点和车道线那?

  • 我们可以知道,车道线的斜率大致是相同的,进而可以分辨出噪点和车道线。
# @Author : LiZhongzheng
# 开发时间  :2025-04-29 9:01
import cv2
import numpy as np"""
剔除出因为误差而被识别出的直线。
如何分解出噪点和车道线那?我们可以知道,车道线的斜率大致是相同的,进而可以分辨出噪点和车道线。
"""def calculate_slope(line):"""计算线段line的斜率:param line: np.array([[x_1, y_1, x_2, y_2]]):return:"""x_1, y_1, x_2, y_2 = line[0]return (y_2 - y_1) / (x_2 - x_1)edge_img = cv2.imread('masked_edge_img.jpg', cv2.IMREAD_GRAYSCALE)# 获取所有线段
lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40, maxLineGap=20)# 按照斜率分成车道线
left_lines = [line for line in lines if calculate_slope(line) > 0]
right_lines = [line for line in lines if calculate_slope(line) < 0]def reject_abnormal_lines(lines, threshold):"""剔除斜率不一致的线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]"""slopes = [calculate_slope(line) for line in lines]while len(lines) > 0:mean = np.mean(slopes)  # 使用 NumPy 的 np.mean 函数计算当前所有斜率的平均值diff = [abs(s - mean) for s in slopes]  # 遍历 slopes 列表,计算每个斜率与平均斜率的绝对差值,并将结果存储在 diff 列表中idx = np.argmax(diff)  # 使用 NumPy 的 np.argmax 函数找到 diff 列表中最大值的索引,即斜率差异最大的线段。if diff[idx] > threshold:  # 如果最大差异大于阈值 threshold,则认为该线段是异常的,将其从 slopes 和 lines 列表中移除。slopes.pop(idx)lines.pop(idx)else:  # 如果最大差异小于或等于阈值,则认为所有线段的斜率已经足够一致,退出循环。breakreturn lines  # 如果最大差异小于或等于阈值,则认为所有线段的斜率已经足够一致,退出循环。print('before filter:')
print('left lines number=')
print(len(left_lines))
print('right lines number=')
print(len(right_lines))reject_abnormal_lines(left_lines, threshold=0.2)
reject_abnormal_lines(right_lines, threshold=0.2)print('after filter:')
print('left lines number=')
print(len(left_lines))
print('right lines number=')
print(len(right_lines))

最小二乘拟合

将lines的线段拟合成一条直线。

np.ravel 将高维数组拉成一维

np.polyfit 多项式拟合

np.polyval 多项式求值

  • 经过上述的步骤,进而我们可以求出车道线的数量等信息,同时又剔除了噪点。然后我们就可以将在同一个区域的线段拟合一条直线

    • # @Author : LiZhongzheng
      # 开发时间  :2025-04-29 15:58
      import cv2
      import numpy as npdef calculate_slope(line):"""计算线段line的斜率:param line: np.array([[x_1, y_1, x_2, y_2]]):return:"""x_1, y_1, x_2, y_2 = line[0]return (y_2 - y_1) / (x_2 - x_1)edge_img = cv2.imread("masked_edge_img.jpg", cv2.IMREAD_GRAYSCALE)
      # 获取所有线段
      lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40, maxLineGap=20)# 按照斜率分成车道线
      left_lines = [line for line in lines if calculate_slope(line) > 0]
      right_lines = [line for line in lines if calculate_slope(line) < 0]def reject_abnormal_lines(lines, threshold):"""剔除斜率不一致的线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]"""slopes = [calculate_slope(line) for line in lines]while len(lines) > 0:mean = np.mean(slopes)diff = [abs(s - mean) for s in slopes]idx = np.argmax(diff)if (diff[idx] > threshold):slopes.pop(idx)lines.pop(idx)else:breakreturn linesleft_lines = reject_abnormal_lines(left_lines, threshold=0.2)
      right_lines = reject_abnormal_lines(right_lines, threshold=0.2)def least_squares_fit(lines):"""将lines中的线段拟合成一条线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]:return: 线段上的两点,np.array([[xmin, ymin], [xmax, ymax]])"""# 1. 取出所有坐标点"""在 OpenCV 中,线段通常用一个形状为 (1, 4) 的 NumPy 数组表示,其中包含线段的两个端点的坐标。具体来说,数组的格式为 [x1, y1, x2, y2],分别表示起点 (x1, y1) 和终点 (x2, y2)。"""x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])  # np.ravel 将二维列表展平为一维数组y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])# 2. 进行直线拟合.得到多项式系数poly = np.polyfit(x_coords, y_coords, deg=1)# 3. 根据多项式系数,计算两个直线上的点,用于唯一确定这条直线point_min = (np.min(x_coords), np.polyval(poly, np.min(x_coords)))point_max = (np.max(x_coords), np.polyval(poly, np.max(x_coords)))return np.array([point_min, point_max], dtype=np.int32)print("left lane")
      print(least_squares_fit(left_lines))
      print("right lane")
      print(least_squares_fit(right_lines))

直线绘制

绘制车道线 cv2.line

# @Author : LiZhongzheng
# 开发时间  :2025-04-29 16:23
import cv2
import numpy as npdef calculate_slope(line):"""计算线段line的斜率:param line: np.array([[x_1, y_1, x_2, y_2]]):return:"""x_1, y_1, x_2, y_2 = line[0]return (y_2 - y_1) / (x_2 - x_1)edge_img = cv2.imread('masked_edge_img.jpg', cv2.IMREAD_GRAYSCALE)
# 获取所有线段
lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40,maxLineGap=20)
# 按照斜率分成车道线
left_lines = [line for line in lines if calculate_slope(line) > 0]
right_lines = [line for line in lines if calculate_slope(line) < 0]def reject_abnormal_lines(lines, threshold):"""剔除斜率不一致的线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]"""slopes = [calculate_slope(line) for line in lines]while len(lines) > 0:mean = np.mean(slopes)diff = [abs(s - mean) for s in slopes]idx = np.argmax(diff)if diff[idx] > threshold:slopes.pop(idx)lines.pop(idx)else:breakreturn linesleft_lines = reject_abnormal_lines(left_lines, threshold=0.2)
right_lines = reject_abnormal_lines(right_lines, threshold=0.2)def least_squares_fit(lines):"""将lines中的线段拟合成一条线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]:return: 线段上的两点,np.array([[xmin, ymin], [xmax, ymax]])"""# 1. 取出所有坐标点x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])# 2. 进行直线拟合.得到多项式系数poly = np.polyfit(x_coords, y_coords, deg=1)# 3. 根据多项式系数,计算两个直线上的点,用于唯一确定这条直线point_min = (np.min(x_coords), np.polyval(poly, np.min(x_coords)))point_max = (np.max(x_coords), np.polyval(poly, np.max(x_coords)))return np.array([point_min, point_max], dtype=np.int32)left_line = least_squares_fit(left_lines)
right_line = least_squares_fit(right_lines)img = cv2.imread('img.jpg', cv2.IMREAD_COLOR)
cv2.line(img, tuple(left_line[0]), tuple(left_line[1]), color=(0, 255, 255), thickness=5)
cv2.line(img, tuple(right_line[0]), tuple(right_line[1]), color=(0, 255, 255), thickness=5)cv2.imshow('lane', img)
cv2.waitKey(0)
image-20250429205831425
重难点讲解:least_squares_fit()函数讲解

该函数主要做了三个部分:提取坐标点、进行直线拟合、计算直线上的两个点。

1. 提取所有坐标点
x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])
y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])
  • lines
    • 输入的线段集合,每个线段是一个形状为 (1, 4) 的 NumPy 数组,表示线段的两个端点坐标 [x1,y1,x2,y2]。
  • x_coords
    • 提取所有线段的 x 坐标。line[0][0] 是起点的 x 坐标,line[0][2] 是终点的 x 坐标。
    • 使用列表推导式 [[line[0][0], line[0][2]] for line in lines] 生成一个二维列表,包含所有线段的起点和终点的 x 坐标。
    • 使用 np.ravel 将二维列表展平为一维数组。
  • y_coords
    • 提取所有线段的 y 坐标。line[0][1] 是起点的 y 坐标,line[0][3] 是终点的 y 坐标。
    • 使用列表推导式 [[line[0][1], line[0][3]] for line in lines] 生成一个二维列表,包含所有线段的起点和终点的 y 坐标。
    • 使用 np.ravel 将二维列表展平为一维数组。
2. 进行直线拟合
poly = np.polyfit(x_coords, y_coords, deg=1)
  • np.polyfit
    • 这是 NumPy 中的一个函数,用于对给定的数据点进行多项式拟合。
    • 参数:
      • x_coords:自变量 x 的值。
      • y_coords:因变量 y 的值。
      • deg=1:指定拟合多项式的次数为 1,即线性拟合
    • 返回值:
      • 返回拟合多项式的系数,从最高次项到常数项。对于线性拟合,返回两个值 [slope, intercept],分别表示直线的斜率和截距。
3. 计算直线上的两个点
point_min = (np.min(x_coords), np.polyval(poly, np.min(x_coords)))
point_max = (np.max(x_coords), np.polyval(poly, np.max(x_coords)))
  • np.min(x_coords)np.max(x_coords)
    • 分别计算 x 坐标中的最小值和最大值。
  • np.polyval(poly, x)
    • 这是 NumPy 中的一个函数,用于计算多项式在给定的 x 值处的 y 值。
    • 参数:
      • poly:拟合多项式的系数数组。
      • x:输入的 x 值。
    • 返回值:
      • 返回多项式在 x 处的 y 值。
  • point_minpoint_max
    • point_min 是直线上的一个点,其 x 坐标为最小值,y 坐标通过多项式计算得到。
    • point_max 是直线上的一个点,其 x 坐标为最大值,y 坐标通过多项式计算得到。
4. 返回值
return np.array([point_min, point_max], dtype=np.int32)
  • 返回一个形状为 (2, 2) 的 NumPy 数组,表示直线上的两个点的坐标。这两个点可以唯一确定一条直线。

视频流读写

cv2.VideoCapture

​ capture.read

  • 基础代码介绍:
# @Author : LiZhongzheng
# 开发时间  :2025-04-29 17:06
import cv2capture = cv2.VideoCapture('video.mp4')
# capture = cv2.VideoCapture(0) #读取当前设备第0个摄像头
while True:ret, frame = capture.read()  # ret 视频流的状态,frame 当前帧的图像cv2.imshow('frame', frame)cv2.waitKey(20)  # 相当于播放速率

cv2.VideoWriter

最后我们不仅可以识别图片的车道线还可以识别视频的车道线,原理相同,因为视频是一帧一帧的,每一帧就是一个图片。

# @Author : LiZhongzheng
# 开发时间  :2025-04-29 17:12
import cv2
import numpy as npdef get_edge_img(color_img, gaussian_ksize=5, gaussian_sigmax=1, canny_threshold1=50, canny_threshold2=100):"""灰度化,模糊,canny变换,提取边缘:param color_img: 彩色图,channels=3""""""cv2.GaussianBlur() 函数参数color_img:输入的彩色图像,必须是 3 通道的 BGR 图像。gaussian_ksize(可选):高斯模糊的核大小。必须是正奇数,默认值为 5。gaussian_sigmax(可选):高斯模糊的 X 方向标准差,默认值为 1。"""gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize, gaussian_ksize),gaussian_sigmax)  # 使用 cv2.GaussianBlur 对输入图像进行高斯模糊处理。高斯模糊可以减少图像中的噪声,使边缘检测更加稳定。gray_img = cv2.cvtColor(gaussian, cv2.COLOR_BGR2GRAY)edges_img = cv2.Canny(gray_img, canny_threshold1, canny_threshold2)return edges_imgdef roi_mask(gray_img):"""对gray_img进行掩膜:param gray_img: 灰度图,channels=1"""poly_pts = np.array([[[0, 368], [300, 210], [340, 210], [640, 368]]])mask = np.zeros_like(gray_img)mask = cv2.fillPoly(mask, pts=poly_pts, color=255)img_mask = cv2.bitwise_and(gray_img, mask)return img_maskdef get_lines(edge_img):"""获取edge_img中的所有线段:param edge_img: 标记边缘的灰度图"""def calculate_slope(line):"""计算线段line的斜率:param line: np.array([[x_1, y_1, x_2, y_2]]):return:"""x_1, y_1, x_2, y_2 = line[0]return (y_2 - y_1) / (x_2 - x_1)def reject_abnormal_lines(lines, threshold=0.2):"""剔除斜率不一致的线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]"""slopes = [calculate_slope(line) for line in lines]while len(lines) > 0:mean = np.mean(slopes)diff = [abs(s - mean) for s in slopes]idx = np.argmax(diff)if (diff[idx] > threshold):slopes.pop(idx)diff.pop(idx)else:breakreturn linesdef least_squares_fit(lines):"""将lines中的线段拟合成一条线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]:return: 线段上的两点,np.array([[xmin, ymin], [xmax, ymax]])""""""np.polyfit 是 NumPy 库中的一个函数,用于对给定的数据点进行多项式拟合。它通过最小二乘法找到一个多项式,使得这个多项式在给定数据点上的值与实际值之间的误差平方和最小。"""x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])poly = np.polyfit(x_coords, y_coords, deg=1)point_min = (np.min(x_coords), np.polyval(poly, np.min(x_coords)))  # 这行代码的作用是计算拟合直线(或多项式曲线)上的一个特定点的坐标。具体来说,它计算的是当 x 取最小值时,对应的 y 值,并将这个点的坐标存储为一个元组 (x_min, y_min)。point_max = (np.max(x_coords), np.polyval(poly, np.max(x_coords)))return np.array([point_min, point_max], dtype=np.int32)# 获取所有线段lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40,maxLineGap=20)# 按照斜率分成车道线left_lines = [line for line in lines if calculate_slope(line) > 0]right_lines = [line for line in lines if calculate_slope(line) < 0]# 剔除离群线段left_lines = reject_abnormal_lines(left_lines)right_lines = reject_abnormal_lines(right_lines)return least_squares_fit(left_lines), least_squares_fit(right_lines)def draw_lines(img, lines):"""在img上绘制lines:param img::param lines: 两条线段: [np.array([[xmin1, ymin1], [xmax1, ymax1]]), np.array([[xmin2, ymin2], [xmax2, ymax2]])]:return:"""left_line, right_line = linescv2.line(img, tuple(left_line[0]), tuple(left_line[1]), color=(0, 255, 255),thickness=5)cv2.line(img, tuple(right_line[0]), tuple(right_line[1]),color=(0, 255, 255), thickness=5)def show_lane(color_img):  # 封装"""在color_img上画出车道线:param color_img: 彩色图,channels=3:return:"""edge_img = get_edge_img(color_img)mask_gray_img = roi_mask(edge_img)lines = get_lines(mask_gray_img)draw_lines(color_img, lines)return color_imgif __name__ == '__main__':capture = cv2.VideoCapture('video.mp4')while True:ret, frame = capture.read()frame = show_lane(frame)cv2.imshow('frame', frame)cv2.waitKey(10)
image-20250429195914415

以上就是我对这个项目的总结。

同时再次说明我已经将项目上传到github项目中,欢迎大家多多支持,你们的支持是我最大的前进动力~~~

再次感谢b站up主 嘉然今天吃带变,以及各位大佬的宝贵意见。

祝好~

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

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

相关文章

【行业特化篇3】制造业简历优化指南:技术参数与标准化流程的关键词植入艺术

写在最前 作为一个中古程序猿,我有很多自己想做的事情,比如埋头苦干手搓一个低代码数据库设计平台(目前只针对写java的朋友),比如很喜欢帮身边的朋友看看简历,讲讲面试技巧,毕竟工作这么多年,也做到过高管,有很多面人经历,意见还算有用,大家基本都能拿到想要的offe…

如何在本地部署小智服务器:从源码到全模块运行的详细步骤

小智聊天机器人本地后台服务器源码全模块部署 作者&#xff1a;林甲酸 -不是小女子也不是女汉子 是大女子 更新日期&#xff1a;2025年4月29日 &#x1f3af; 前言&#xff1a;为什么要写这篇教程&#xff1f; 上周按照虾哥小智服务器的教程去部署本地后台&#xff0c;我用的是…

github开源项目添加开源协议,使用很简单

直接在 GitHub 网页上创建 进入你的 GitHub 仓库 打开你的项目仓库页面&#xff08;如 https://github.com/用户名/仓库名&#xff09;。 点击 "Add file" → "Create new file" 在仓库主页&#xff0c;点击右上角的 "Add file" 按钮&#xff…

8.idea创建maven项目(使用Log4j日志记录框架+Log4j 介绍)

8.idea创建maven项目(使用Log4j日志记录框架Log4j 介绍) 在 IntelliJ IDEA 的 Maven 项目中引入了 Log4j&#xff0c;并配置了日志同时输出到控制台和文件。 Log4j 提供了灵活的日志配置选项&#xff0c;可以根据项目需求调整日志级别、输出目标和格式。 1. 创建 Maven 项目 …

【和春笋一起学C++】函数——C++的编程模块

目录 1. 原型句法 2. 函数分类 3. 函数参数之按值传递 4. 数组作为函数参数 在C中&#xff0c;要使用函数&#xff0c;必须要有这三个方面&#xff1a; 函数原型&#xff0c;函数原型描述了函数到编译器的接口&#xff0c;函数原型一般放在include文件中。函数原型告诉编译…

深挖Java基础之:认识Java(创立空间/先导:Java认识)

今天我要介绍的是在Java中对Java的一些基本语法的认识与他们的运用&#xff0c;以及拟举例子说明和运用场景&#xff0c;优势和劣势&#xff0c; 注&#xff1a;本篇文章是对Java的一些基本的&#xff0c;简单的代码块的一些内容&#xff0c;后续会讲解在Java中的变量类型&…

Python+Selenium+Pytest+Allure PO模式UI自动化框架

一、框架结构 allure-report&#xff1a;测试报告base&#xff1a;定位元素封装data&#xff1a;数据log&#xff1a;日志文件page&#xff1a;页面封装文件夹report&#xff1a;缓存报告testcases&#xff1a;测试用例层utils&#xff1a;工具类run.py&#xff1a;执行文件 二…

博物馆除湿控湿保卫战:M-5J1R 电解除湿科技如何重塑文物守护的未来

在卢浮宫幽深的长廊里&#xff0c;达芬奇的《蒙娜丽莎》正经历着一场看不见的战争——不是来自时间的侵蚀&#xff0c;而是空气中无形的水分子。每一件文物都在与湿度进行着无声的抗争&#xff0c;这场抗争关乎人类文明的延续。湿度&#xff0c;这个看不见的文物杀手&#xff0…

【嘉立创EDA】如何找到曲线和直线的交点,或找到弧线和直线的交点

文章路标👉 :one: 文章解决问题:two: 主题内容:three: 参考方法be end..1️⃣ 文章解决问题 操作环境:嘉立创EDA专业版 V2.2.38 本文使用嘉立创EDA,描述如何快速找到曲线和直线交点的方法,这里的曲线包括了弧线等。本文将此过程记录,以供有需要的读者参考。 2️⃣ 主题…

大语言模型能否替代心理治疗师的深度拓展研究:fou

大语言模型能否替代心理治疗师的深度拓展研究 在科技初创企业和研究领域,大型语言模型(LLMs)用于替代心理健康服务提供者的应用备受关注。但研究人员通过对主要医疗机构治疗指南的梳理回顾,并对当前 LLMs(如 gpt-4o)进行实验评估后发现,LLMs 存在对心理疾病患者表达污名…

【linux】Chrony服务器

简介 1.1 时间的重要性 由于 IT 系统中&#xff0c;准确的计时非常重要&#xff0c;有很多种原因需要准确计时&#xff1a; 在网络传输中&#xff0c;数据包括和日志需要准确的时间戳 各种应用程序中&#xff0c;如订单信息&#xff0c;交易信息等 都需要准确的时间戳 1.2 时区…

mysql查看哪些表的自增id已超过某个值

场景 想看哪些表数据比较大&#xff0c;如果用count 比较慢&#xff0c;同时表设计如果是自增&#xff0c;有没有办法一次查出自增id已超过某值的所有表呢。 方法 SELECT AUTO_INCREMENT,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA 库名 AND AUTO_INCRE…

SiamMask原理详解:从SiamFC到SiamRPN++,再到多任务分支设计

SiamMask原理详解&#xff1a;从SiamFC到SiamRPN&#xff0c;再到多任务分支设计 一、引言二、SiamFC&#xff1a;目标跟踪的奠基者1. SiamFC的结构2. SiamFC的局限性 三、SiamRPN&#xff1a;引入Anchor机制的改进1. SiamRPN的创新2. SiamRPN的进一步优化 四、SiamMask&#x…

SpringBoot终极形态:AI生成带OAuth2鉴权的微服务模块(节省20人日)

在数字化转型的浪潮中,开发效率和质量是企业竞争力的关键要素。飞算 JavaAI 作为一款创新的 AI 工具,能在 Spring Boot 开发中,自动生成完整微服务模块,极大提升开发效率。下面,我们就详细介绍如何借助飞算 JavaAI,实现 Spring Boot 微服务模块的自动化生成。 飞算 JavaAI 简介…

Spring缓存注解深度实战:3大核心注解解锁高并发系统性能优化‌

引言&#xff1a;缓存——高并发系统的“性能加速器”‌ 在互联网应用中&#xff0c;数据库查询往往是性能瓶颈的核心。当每秒数千次的请求直接冲击数据库时&#xff0c;系统响应速度会急剧下降&#xff0c;甚至引发宕机风险。‌缓存技术‌应运而生&#xff0c;成为解决这一痛…

CSS元素动画篇:基于当前位置的变换动画(二)

基于当前位置的变换动画&#xff08;二&#xff09; 前言旋转效果类元素动画摇摆动画效果效果预览代码实现 摇晃动画效果效果预览代码实现 螺旋旋转效果预览代码实现 结语 前言 CSS元素动画一般分为两种&#xff1a;一种是元素基于当前位置的变换动画&#xff0c;通过不明显的…

Qt/C++开发监控GB28181系统/设备注册/设备注销/密码认证/心跳保活/校时

一、前言 根据gb28181协议文档&#xff0c;第一步就是需要实现设备的注册&#xff0c;和onvif不同&#xff0c;gb是反过来的&#xff0c;设备端主动连接服务端&#xff0c;而onvif是服务端主动发出搜索&#xff0c;设备被动应答&#xff0c;包括后续的交互几乎都是被动应答&am…

MATLAB 中的图形绘制

一、线图 plot 函数用来创建x和y值的简单线图。 x 0 : 0.05 : 30; %从0到30&#xff0c;每隔0.05取一次值 y sin(x); plot(x,y,LineWidth,2) %若&#xff08;x&#xff0c;y&#xff0c;LineWidth&#xff0c;2&#xff09;可变粗 xlabel("横轴标题") ylab…

go语言八股文(五)

1.go的局部变量是分配在栈上还是在堆上 在Go语言中&#xff0c;局部变量的内存分配&#xff08;栈或堆&#xff09;由编译器基于逃逸分析&#xff08;escape analysis&#xff09;来决定。以下是总结和具体示例&#xff1a; 栈上分配 当局部变量的生命周期严格限定在函数作用…

Gradients of Matrix-Matrix Multiplication in Deep Learning

Gradients of Matrix-Matrix Multiplication in Deep Learning 1. Matrix multiplication2. Derivation of the gradients2.1. Dimensions of the gradients2.2. The chain rule2.3. Derivation of the gradient ∂ L ∂ A \frac{ {\partial L} }{ {\partial \boldsymbol {\bo…