【学习笔记】车道线识别——图像处理方法

news2026/5/3 1:17:11
一、图像基本知识1. HLS色相亮度饱和度色相通道确定颜色亮度通道亮度信息饱和度通道饱和度信息对于颜色区分鲜艳程度很关键。二、视频读取示例import cv2 if __name__ __main__: video cv2.VideoCapture(./img/img/up.mp4) # 读取帧率 fps video.get(cv2.CAP_PROP_FPS) # success代表是否成功读取,frame是视频的第一帧, success, frame video.read() # 如果第一帧读取成功 while success: cv2.imshow(frame, frame) success, frame video.read() # 视频第一帧之后的每一帧每一次success, frame video.read()只读一帧,这里循环调用成了每一帧 # 按键退出 # 按下空格关闭视频 if cv2.waitKey(1) ord( ): # cv2.waitKey(1) 函数会等待1毫秒检查是否有按键被按下。ord( ) 是一个Python内置函数它返回字符的ASCII码值。在这个例子中ord( ) 返回空格键的ASCII码值即32 break # 1000ms 1s 1000/fps 计算每一帧的时间 cv2.waitKey(int(1000 / int(fps))) # 防止出现非整数 print(int(1000 / int(fps))) 按下空格退出视频很慢,增加释放资源功能提高程序运行效率 # 释放资源 video.release() # 关闭所有窗口 cv2.destroyAllWindows()2、RGB红、绿、蓝三、图像边缘提取1. sobel算子本质上是卷积在图像处理领域梯度不是传统意义上的梯度只是用卷积算出了变化幅度本质上类似于梯度1.1 卷积核Gx [-1 0 1,-2 0 2,-1 0 1]Gy [-1 -2 -1,0 0 0,1 2 1]之所以选择这个卷积核是因为当出现边缘时左右或者上下的差值大-的或者的一边会大于另一边绝对值就会大如果与卷积核进行卷积的地方数值差不多最后结果则接近于0。这样便能区分出非边缘区域和边缘区域有2的原因时因为sobel认为离得近的像素点更重要即类似于加权1.2 Sobel算子的工作原理它使用两个卷积内核一个用于计算x方向上的梯度另一个用于计算y方向上的梯度。每个内核都考虑了像素及其邻域的值并根据这些值计算梯度。通过将这两个梯度分量结合起来通常使用平方和的平方根我们可以得到梯度的幅值它表示了图像中每个像素点处的强度变化速率。1.3 opencv的sobel函数参数由于sobel计算得到的边缘信息可能存在负数(通过导数计算得到的梯度信息)超出图像像素范围 0-255 的无符号数的8位整数类型需要用绝对值的形式来取值以便后续操作sobel_x参数1.src类型numpy.ndarray图像的输入, 必须是灰度图、单通道2.ddepth:类型int输出图像的深度(数据类型)指定了输出图像的位深度。常用的值-1输出图像与输入图像深度相同。其他值cv2.cv_8U8位无符号整数、cv2.cv_16S16位有符号数、cv2.cv_32F32位浮点数cv2.cv_64F64位浮点数。选择合适的输出图像深度对于计算结果的精度和表示的范围有影响。3.dx、dy类型int某个方向的阶数, 表示图像在x、y轴的求导次数1表示计算y、x方向的一阶导数0不计算x, y的导数。大于1表示更高阶的导数极少用4.ksize类型intsobel算子的大小, 通常取奇数, 表示计算梯度时所使用的卷积核大小, 常见的大小有3 * 35 * 57 * 7ksize越大, 算子对图像的平滑效果越强, 但是可能会丢失细节。5.scale类型float可选的缩放因子, 默认值1计算梯度结果比例缩放6.delta类型folat可选的偏移量, m默认值0, 在计算梯度时,.通常用于调整最终图像中的亮度或者对比度7.borderType类型int边缘像素处理方式, 邻域参数决定了怎么处理图像的边界cv2.BORDER_CONSTANT使用常数值来填充边界外的像素cv2.BORDER_REFLECT边界外的像素值的镜像反射。cv2.BORDER_FEPLTCATE边界外的像素值的镜像复制。CV2.BORDER_DEFALUT默认方式填充边界:使用实例sobel_x cv2.Sobel(channels_l, -1, 1, 0) sobel_x_2 cv2.Sobel(channels_l, -1, 1, 0, borderTypecv2.BORDER_REPLICATE) # sobel_x 变量将存储所有检测的边缘信息, # -1表示输出图像的数据类型与输入图像的数据类型保持一致 # 1 表示 在x轴的方向求一阶导数(检测横向边缘) # 0 在y轴的方向不求导数,(不用纵向检测) 由于sobel计算得到的边缘信息可能存在负数(通过导数计算得到的梯度信息) 而图像像素范围 0-255 的无符号数的8位整数类型 一定要用绝对值的形式来取值以便后续操作 abs_sobel_x np.absolute(sobel_x) abs_sobel_x_2 np.absolute(sobel_x_2) print(abs_sobel_x.shape) print(abs_sobel_x_2.shape)2. 归一化和二值化2.1 归一化2.2 二值化忽略不重要的地方,单独取出车道线,事实上就是取出轮廓最明显(梯度最大)的使用实例 # 使用比较高效的布尔索引进行二值化 # 将170作为下限阈值,255为上限阈值,基于车道线在图像中的亮度特征的分析以及多次实验 # 同时满足170和255条件的为True # 归一化结果进一步二值化 sx_binary np.zeros_like(scaled_sobel) sx_binary[(170 scaled_sobel) (scaled_sobel 255)] 255 # 先是取出170和255的元素,取出的均为布尔值,再根据布尔值为True的填充为255(在灰度图中即为白色) s_binary np.zeros_like(channels_s) s_binary[(100 channels_s) (channels_s 255)] 255 # 饱和度二值化 color_binary (sx_binary | s_binary) cv2.imshow(color, color_binary) cv2.waitKey(0) cv2.imwrite(panel12.png, color_binary)2.3 图片保存cv2.imwrite(panel12.png, color_binary)四、仿射变换import cv2 import numpy as np # 原图片 img cv2.imread(./img/img/up01.png) # 处理后的图片 color_binary cv2.imread(./panel11.png) # 灰度化 color_binary cv2.cvtColor(color_binary, cv2.COLOR_BGR2GRAY) img_shape color_binary.shape print(img_shape) ----------------------------------透视变换--------------------------------------------------- 汽车进入车道的角度会变化为了统一使用透视变换使视角统一 仿射变换是一种几何变换它保持了图像中的直线性和平行性。仿射变换包括平移、缩放、旋转和剪切shear等操作。 本质上是一种矩阵计算矩阵本身就是一种空间变换 这些变换可以组合使用以实现复杂的图像变换。 1、偏移量设置 offset_x 160 和 offset_y 0这些偏移量用于调整透视变换后目标图像的位置。 偏移量的选择通常基于实验和图像的具体需求以确保变换后的图像能够正确地表示车道线. offset_x 160 offset_y 0 2、定义原始图像上的透视变换点 pts1这些点定义了原始图像上进行透视变换的四个关键坐标点。定义了需要进行变换的区域 坐标是以图像宽度和高度的比例来表示的数据类型是np.float32类型的数组。这些点的选择基于图像内容和所需的变换效果。 pts1 np.float32([ [img_shape[1] * 0.4, img_shape[0] * 0.7], # 第一个坐标点,横坐标的图像宽度的0.4倍纵坐标的图像0.7倍该例结果为512.0和503.99999999999994 [img_shape[1] * 0.6, img_shape[0] * 0.7], # 第二个坐标点,横坐标的图像宽度的0.4倍纵坐标的图像0.7倍 [img_shape[1] * 1 / 8, img_shape[0]], # 第三个坐标点,横坐标的图像宽度的1/8倍纵坐标就是图像高度 [img_shape[1] * 7 / 8, img_shape[0]], # 第四个坐标点,横坐标的图像宽度的7/8倍纵坐标就是图像高度 ]) print(f放射变换的参数{img_shape[1] * 0.4, img_shape[0] * 0.7}) 3、定义目标图像上的透视变换点 pts2这些点定义了透视变换后目标图像上的四个点。这些点的坐标根据图像的宽度、高度和偏移量进行计算。 目标点的选择是为了将原始图像的特定区域映射到目标图像的特定位置以便于后续处理。 pts2 np.float32([ [offset_x, offset_y], # 第一个点变换后的坐标按照偏移量来定位 [img_shape[1] - offset_x, offset_y], # 横坐标根据图片的宽度和偏移量进行计算纵坐标按照偏移量设置0 [offset_x, img_shape[0] - offset_y], # 横坐标按照偏移量纵坐标根据图像高度和偏移量确定 [img_shape[1] - offset_x, img_shape[0] - offset_y], ]) 4、计算透视变换矩阵 使用cv2.getPerspectiveTransform(pts1, pts2)函数根据给定的源点集pts1和目标点集pts2计算透视变换矩阵pts。 这个矩阵用于将原始图像透视变换为目标图像。 这里的矩阵就是进行仿射变换的关键仿射变换是一种矩阵运算。 pts cv2.getPerspectiveTransform(pts1, pts2) 5、应用透视变换 使用cv2.warpPerspective(color_binary, pts, (img_shape[1], img_shape[0]))函数对原始图像color_binary进行透视变换 得到校正后的图像correct_image。变换后的图像与原始图像的宽高保持一致。 correct_image cv2.warpPerspective(color_binary, pts, (img_shape[1], img_shape[0])) # img_shape[0]和img_shape[1]是元组 6、绘制填充矩形 在correct_image上绘制一个填充矩形用于标记或处理图像的特定区域。矩形的坐标根据图像的宽度和高度比例计算得出。 cv2.rectangle(correct_image, [int(img_shape[1] * 0.4 20), int(img_shape[0] * 0.7)], [int(img_shape[1] * 0.6 20), int(img_shape[0])], color(0, 0, 0), thicknesscv2.FILLED ) cv2.imshow(correct_image, correct_image) cv2.waitKey(0) # correct_image是一个图片类型保存的图片命名要跟上后缀用于确定保存格式 # cv2.imwrite(panel2.png, correct_image) # cv2.waitKey(0)五、开运算与闭运算形态学的腐蚀与膨胀1. 开运算:先腐蚀后膨胀,用于去除图形中的小噪点、孤立的小点,腐蚀多余的像素点原理:腐蚀操作阶段使用一个结构元素(矩形、圆形、其他形状)逐个滑动。当遇到不符合物体(通常是白色)状态时,就会腐蚀掉(背景像素、通常时黑色的)就可以去除小的噪点、和微小的物体。膨胀操作阶段使用一个结构元素(矩形、圆形、其他形状)逐个滑动。当遇到有一个像素是目标像素时,就会膨胀其结构元素中心点的像素不会回复之前已经腐蚀的像素点应用:图像去噪、物体分离2. 闭运算:先膨胀后腐蚀。填充图像中的小孔、小裂缝。膨胀特点的元素.原理膨胀阶段使用一个结构元素(矩形、圆形、其他形状)逐个滑动。当遇到有一个像素是目标像素时,就会膨胀其结构元素中心点的像素不会回复之前已经腐蚀的像素点腐蚀阶段使用一个结构元素(矩形、圆形、其他形状)逐个滑动。当遇到不符合物体(通常是白色)状态时,就会腐蚀掉中心像素点(背景像素、通常时黑色的)就可以去除小的噪点、和微小的物体。避免过度膨胀。应用:图像修复物体轮廓修复3. 腐蚀与膨胀原理腐蚀定义:形态学操作,可以是图像中目标物体(白的或者比较亮的物体)经过一定的收缩在二进制图像中,(只有 0 黑色 1 白色)会将目标物体(白色区域)的边界像素根据一定的规则来变为背景颜色(黑色)原理:结构元素的小矩阵进行滑动,,对于每个像素位置,,当结构元素所覆盖的像素与图像中心点的元素的不完全匹配时就要进行覆盖开运算效果图闭运算效果图图片转载自形态学应用——图像开运算与闭运算_图像开运算和闭运算-CSDN博客开运算与闭运算示例# MORPH_RECT 表示创建矩形结构元素 # MORPH_ELLIPSE 表示创建圆形结构元素 # MORPH_CROSS 表示创建十字结构元素 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) print(fkernel is:{kernel}) 2、闭运算 # 先进行膨胀操作 # dilate 使用定义好的元素结构对图像correct_image进行膨胀 # 膨胀操作会让图像中白色(较亮)区域扩大 dilate_image cv2.dilate(correct_image, kernel) # 再进行腐蚀操作 # erode 使用定义好的元素结构kernel对图像correct_image进行腐蚀 erode_image cv2.erode(dilate_image, kernel) # 显示经过一次闭运算之后的腐蚀图像 # cv2.imshow(erode_image, erode_image) # cv2.waitKey(0) 3、开运算 # 先进行腐蚀操作 # erode 使用定义好的元素结构kernel对图像correct_image进行腐蚀 erode_image cv2.erode(erode_image, kernel) # 显示经过一次闭运算之后的腐蚀图像 # 再进行膨胀操作 # dilate 使用定义好的元素结构对图像correct_image进行膨胀 # 膨胀操作会让图像中白色(较亮)区域扩大 dilate_image cv2.dilate(erode_image, kernel) # cv2.imshow(erode_image, erode_image) # cv2.waitKey(0) 3、直方图 # np.sum(...,axis0) 表示沿着列方向,将图像中矩阵的数值加到一个新的矩阵中 histogram np.sum(dilate_image[:, :], axis0) # 类似于横向压缩为一个矩阵 print(pd.DataFrame(histogram)) # 使用matplotlib绘制直方图 # 横坐标 # 是图像的列索引(范围从0开始 到图像的长度通过np.arrange(0,len(histogram))获得,(例子结果是1280) # 纵坐标 # 对应的列像素总和,histogram # r red g green blue y yellow # - 虚线 .-点虚线 ................... plt.plot(np.arange(0, len(histogram)), histogram, r-) plt.show() # 这个直方图揭示了当纵坐标为多少时横坐标是非0的六、车道线可视化(示例)import cv2 import numpy as np import matplotlib.pyplot as plt import pandas as pd correct_image cv2.imread(./panel2.png) # 灰度处理 correct_image cv2.cvtColor(correct_image, cv2.COLOR_BGR2GRAY) # 创建矩形结构元素。 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) 1.膨胀物体边界扩展可以链接断开的部分 2.对膨胀的图像进行腐蚀消除噪点 3.再次腐蚀进一步细化图像消除不需要的部分 4.再次膨胀相互配合调整图像形态 5.又一次膨胀 6.又一次腐蚀 具体以实际情况为主 # 膨胀 dilate_image cv2.dilate(correct_image, kernel) # 腐蚀 erode_image cv2.erode(dilate_image, kernel) # 腐蚀 erode_image cv2.erode(erode_image, kernel) # 膨胀 dilate_image cv2.dilate(erode_image, kernel) # 膨胀 dilate_image cv2.dilate(dilate_image, kernel) # 腐蚀 erode_image cv2.erode(dilate_image, kernel) # 膨胀 dilate_image cv2.dilate(erode_image, kernel) # 腐蚀 erode_image cv2.erode(dilate_image, kernel) # cv2.imshow(erode_image, erode_image) # cv2.waitKey(0) 一、获取车道线的初始位置 1.1 找到两条车道线 # 直方图图像会有两个凸点代表了车道线因为数组的其他地方为0有车道线的地方才有数字每列相加为一维数组后只有有车道线的那一块会有数值。 histogram np.sum(dilate_image[:, :], axis0) # 类似于纵向压缩为一个矩阵 plt.plot(np.arange(0, len(histogram)), histogram, r-) plt.show() 1.2 计算两条车道线的中心线并以此划分左右车道的搜索范围 # 计算直方图(每列像素值相加数组)中的中点位置用于分割划分左右车道的搜索范围 midpoint np.array(histogram.shape[0] / 2, dtypenp.int32) # 在直方图的左半部分,寻找像素点累加的最大位置这个位置作为左车道线初始搜索的大致横坐标的起点。 left_x_base np.argmax(histogram[:midpoint]) # 在直方图的右半部分,寻找像素点累加的最大位置中点位置的偏移量这个位置作为右车道线初始搜索的大致横坐标的终点。 right_x_base np.argmax(histogram[midpoint:]) midpoint # histogram[midpoint:]只是中点到右车道线的距离 # 根据上面的计算初始化车道线 # 车道检测当前位置初始化左车道线的当前横坐标 left_x_current left_x_base right_x_current right_x_base 二、创建滑动窗口用于检测车道线并为正式滑动作准备 2.1 设置滑动窗口的数量、高度、检测的水平范围、最小像素点阈值 # 设置滑动窗口的数量数量可以决定在图像的垂直方向划分多个区域来搜索车道线 m_windows 9 # 计算每个滑动窗口的高度通过图像的总高度/窗口数量 window_height int(erode_image.shape[0] / m_windows) # 设置x的检测范围这里是滑动窗口宽度的一半手动指定一个值_____可以确定每个滑动窗口内左右车道线可能出现的水平范围 margin 100 # 6.设置最小像素点阈值用于统计每个滑动区域的非0像素个数当窗口内的非0像素个数小于阈值是就说明可能不是车道线对中心点位置进行更新 minpix 50 2.2 找到整个图像中不为零的像素点的坐标 # 获取图像中像素值不为0的坐标,nonzero()返回值是两个数组非零点的纵坐标(行)非0点的纵坐标(行索引)和横坐标(列索引) non_zero erode_image.nonzero() print(non_zero) # 将此数组的纵、坐标提取出来并且进行类型转换为numpy non_zero_y np.array(non_zero[0]) # 纵坐标 non_zero_x np.array(non_zero[1]) # 横坐标 2.3 初始化两个索引分别用于记录那些在左、右车道线搜索中找到的非0数值 # 用于记录搜索窗口的左右车道线的非0数值在nonzero_y和x的索引。初始化为空。 left_lane_inds [] right_lane_inds [] 三、 开始用滑动窗口搜索车道线,遍历该图中的每一个窗口从底部窗口开始向上遍历 # m_windows是滑动窗口个数 for window in range(m_windows): 3.1 窗口纵坐标范围 # 设置窗口的y的检测范围(纵坐标范围) win_y_low erode_image.shape[0] - (window 1) * window_height win_y_high erode_image.shape[0] - window * window_height 3.2 窗口横坐标范围 # 左车道线x的范围根据当前左车道的横坐标位置与设置margin(检测范围100)来确定当前车道线坑出现的水平范围 win_x_left_low left_x_current - margin win_x_left_high left_x_current margin # 右车道线x的范围根据当前右车道的横坐标位置与设置margin(检测范围100)来确定当前车道线坑出现的水平范围 win_x_right_low right_x_current - margin win_x_right_high right_x_current margin 3.3 收集在当前滑动窗口中的非零像素点的索引 # good_left_inds和good_right_inds是一个数组它包含了在当前滑动窗口中被识别为属于左右车道线的非零像素点的索引。这些索引指向non_zero_x和non_zero_y数组中的位置即它们对应于图像中非零像素点的横坐标 good_left_inds ((non_zero_y win_y_low) (non_zero_y win_y_high) # 表示处于窗口纵坐标范围内的非0值的索引 (non_zero_x win_x_left_low) ( non_zero_x win_x_left_high)).nonzero() # 表示处于窗口左车道横坐标范围的非0值的索引 good_right_inds ((non_zero_y win_y_low) (non_zero_y win_y_high) # 表示处于窗口纵坐标范围内的非0值的索引 (non_zero_x win_x_right_low) ( non_zero_x win_x_right_high)).nonzero() # 表示处于窗口右车道横坐标范围的非0值的索引 3.4 将收集到的索引添加到分为左右车道分别添加到列表中 # 将在车道线搜索窗口内的非0点的索引添加到记录在车道索引的列表中 left_lane_inds.append(good_left_inds) right_lane_inds.append(good_right_inds) 3.5 通过阈值检验车道是否在窗口内如果不在就更新横坐标(初始横坐标是根据上面的一维纵坐标相加矩阵) # 不直接用non_zero_x和non_zero_y原因就是good_left_inds和good_right_inds是经过窗口的阈值(minpix)检验的更能说明是车道线而non_zero_x和non_zero_y包含大量非车道线数值 # 如果获取的左车道线搜索窗口内的个数小于最小个数(minpix),则利用这些点的横坐标平均值来进行更新滑动窗口在x轴的车道线 if len(good_left_inds) minpix: left_x_current np.mean(non_zero_x[good_left_inds]).astype(dtypenp.int32) # 如果获取的右车道线搜索窗口内的个数小于最小个数(minpix),则利用这些点的横坐标平均值来进行更新滑动窗口在x轴的车道线 if len(good_right_inds) minpix: right_x_current np.mean(non_zero_x[good_right_inds]).astype(dtypenp.int32) 四、循环结束提取获得到的车道线的索引 # 将检测处左右车道点的索引列表合成一个numpy数组为了统一处理, axis1————按列方向 4.1 转为numpy数组 left_lane_inds np.concatenate(left_lane_inds, axis1) right_lane_inds np.concatenate(right_lane_inds, axis1) 4.2 获取左右车道的横纵坐标 left_x non_zero_x[left_lane_inds] left_y non_zero_y[left_lane_inds] right_x non_zero_x[right_lane_inds] right_y non_zero_y[right_lane_inds] ------------------------------------------------程序执行至此已经获取了所有车道线的坐标------------------------------------------------------------------- 五、曲线拟合 # 就是类似于回归拟合一样的东西用二次项的方式去拟合车道线 # 3.用于曲线拟合检测出的点二次多项式拟合返回结果是二次项的系数(a,b,c),拟合车道线检测出的点,拟合x ay left_fit np.polyfit(left_y[0], left_x[0], 2) right_fit np.polyfit(right_y[0], right_x[0], 2) 六、进行车道线可视化 6.1 获取图像行数 y_max erode_image.shape[0] 62 创建一个处理后的图像从灰度图重新转为彩色图 # np.dstack 是 NumPy 库中的一个函数用于沿深度方向第三维堆叠数组。 # 在这里是从单通道灰度图转为三通道灰度图三通道意味着虽然本身暂时还没有颜色但是具备了显示彩色的能力 out_img np.dstack( (erode_image, erode_image, erode_image)) * 255 # *255的原因是灰度图是二值图像只有0和1回到彩色图要变成0-255的范围白的就是255黑的仍然是0 6.3 获得根据车道线进行曲线拟合生成的坐标点 # 在拟合曲线中获取左、右车道线的像素点通过垂直方向的每一个坐标点y代入拟合的二次多项式公式进行计算横坐标从而生成一系列的坐标点 left_points [[left_fit[0] * y ** 2 left_fit[1] * y left_fit[2], y] for y in range(y_max)] right_points [[right_fit[0] * y ** 2 right_fit[1] * y right_fit[2], y] for y in range(y_max)] # 左右车道线的像素点进行合并。形成一个总的坐标点。 line_points np.vstack((right_points, left_points)) 6.4 优化 # 对合并后的坐标点进行随机打乱更加均匀地展示 np.random.shuffle(line_points) # 线条区分需要更加明显时使用。 6.5 根据左右车道线的像素位置绘制多边形。效果是看起来像一整个车道 # cv2.fillPoly(out_img, [np.array(line_points, dtypenp.int32)], (0, 255, 0)) 6.6 绘制拟合的车道线 # 遍历每个车道线像素点,在输出图像上以原型绘制 for point in line_points.astype(dtypenp.int32): cv2.circle(out_img, point, 10, (0, 255, 0), thickness5) 6.7 显示 # 显示绘制好的车道线的图像 cv2.imshow(Output, out_img) cv2.waitKey(0)

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…