激光和相机的标定---手动标定的方法

news2024/11/28 15:55:00

一、手动标定

代码工程:GitHub - Livox-SDK/livox_camera_lidar_calibration: Calibrate the extrinsic parameters between Livox LiDAR and camera

        这是Livox提供的手动校准Livox雷达和相机之间外参的方法,并在Mid-40,Horizon和Tele-15上进行了验证。其中包含了计算相机内参,获得标定数据,优化计算外参和雷达相机融合应用相关的代码。本方案中使用了标定板角点作为标定目标物,由于Livox雷达非重复性扫描的特点,点云的密度较大,比较易于找到雷达点云中角点的准确位置。相机雷达的标定和融合也可以得到不错的结果。

本方案使用标定板的四个角点来作为目标物 。标定场景最好选择一个较为空旷的环境,这样方便识别标定板,并且保证雷达到标定板有3米以上。这个案例中使用了低反射率泡棉制作的标定板(1m x 1.5m)。需要选取至少10个左右不同的角度和距离来摆放标定板(参考相机内参的标定物摆放),左右位置和不同的偏向角度最好都有采集数据。

编译和修改好的工程代码,所在位置为:

https://download.csdn.net/download/YOULANSHENGMENG/87698893

1.1 环境配置

我的基础环境为 ubuntu20.04   ros neotic pcl 1.10 提前还需要装好 Eigen  Ceres

# install Livox_SDK
git clone https://github.com/Livox-SDK/Livox-SDK.git
cd Livox-SDK
sudo ./third_party/apr/apr_build.sh
cd build && cmake ..
make
sudo make install

# install livox_ros_driver
cd ..
git clone https://github.com/Livox-SDK/livox_ros_driver.git ws_livox/src
cd ws_livox
catkin_make

# install camera/lidar calibration package
cd src
git clone https://github.com/Livox-SDK/livox_camera_lidar_calibration.git
cd ..
catkin_make
source devel/setup.bash

编译过程中遇到的问题:

 /usr/include/pcl-1.10/pcl/point_types.h: In function ‘const pcl::CPPFSignature& pcl::common::operator-=(pcl::CPPFSignature&, const float&)’:
/usr/include/pcl-1.10/pcl/point_types.h:574:1: error: ‘minusscalar’ is not a member of ‘pcl::traits’
  574 | POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::CPPFSignature,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/pcl-1.10/pcl/point_types.h:574:1: error: ‘minusscalar’ is not a member of ‘pcl::traits’
  574 | POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::CPPFSignature,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/pcl-1.10/pcl/point_types.h:574:1: error: ‘minusscalar’ is not a member of ‘pcl::traits’
  574 | POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::CPPFSignature,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/pcl-1.10/pcl/point_types.h:574:1: error: ‘minusscalar’ is not a member of ‘pcl::traits’
  574 | POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::CPPFSignature,

解决办法:修改编译文件,将和c++11的位置进行修改

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O3")

cmake_minimum_required(VERSION 2.8.3)
project(camera_lidar_calibration)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
#set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -g")
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  pcl_conversions
  pcl_ros
  cv_bridge
)

find_package(PCL 1.10 REQUIRED)
find_package(OpenCV)
find_package(Threads)
find_package(Ceres REQUIRED)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")

catkin_package(
 CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
  ${PCL_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
)

add_executable(cameraCalib src/cameraCalib.cpp)
target_link_libraries(cameraCalib ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})

add_executable(pcdTransfer src/pcdTransfer.cpp src/common.h)
target_link_libraries(pcdTransfer ${catkin_LIBRARIES} ${PCL_LIBRARIES})

add_executable(cornerPhoto src/corner_photo.cpp src/common.h)
target_link_libraries(cornerPhoto ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})


add_executable(getExt1 src/cam_lid_external1.cpp src/common.h)
target_link_libraries(getExt1 ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${CERES_LIBRARIES})

add_executable(getExt2 src/cam_lid_external2.cpp src/common.h)
target_link_libraries(getExt2 ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${CERES_LIBRARIES})


add_executable(projectCloud src/projectCloud.cpp src/common.h)
target_link_libraries(projectCloud ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})

add_executable(colorLidar src/color_lidar_display.cpp src/common.h)
target_link_libraries(colorLidar ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${CERES_LIBRARIES})


作者使用的硬件设备为:

1.2 执行标定

1)相机内参标定

将拍摄了标定板的相机的图像,放在data/camera/photos下,然后在data/camera/in.txt中写入所有需要使用的照片名称。可以使用以下的代码实现:

"""
#-*-coding:utf-8-*- 
# @author: wangyu a beginner programmer, striving to be the strongest.
# @date: 2022/7/7 20:25
"""
import os

# 文件夹路径
img_path = r'/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/camera/photos/'
# txt 保存路径
save_txt_path = r'./in.txt'

# 读取文件夹中的所有文件
imgs = os.listdir(img_path)

# 图片名列表
names = []

# 过滤:只保留png结尾的图片
for img in imgs:
    if img.endswith(".png"):
        names.append(img)

txt = open(save_txt_path,'w')

for name in names:
    #name = name[:-4]    # 去掉后缀名.png
    txt.write(name + '\n')  # 逐行写入图片名,'\n'表示换行

txt.close()

作者使用的标定板的样子为:

我使用的标定板, 内点是行向是9点和6点,边长是20mm

修改 对应的launch文件,如下进行修改:

<?xml version="1.0" encoding="UTF-8"?>
<launch>
    <param name="camera_in_path"        value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/camera/in.txt" />  <!-- the file to contain all the photos -->
    <param name="camera_folder_path"    value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/camera/photos/" />  <!-- the file to contain all the photos -->
    <param name="result_path"           value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/camera/result.txt" />  <!-- the file to save the intrinsic data -->
    
    <param name="row_number"            type="int" value="9" />  <!-- the number of block on the row -->
    <param name="col_number"            type="int" value="6" />  <!-- the number of block on the column -->
    <param name="width"                 type="int" value="20" />  <!-- the width of each block on the chessboard(mm) -->
    <param name="height"                type="int" value="20" />  <!-- the height of each block on the chessboard(mm)-->
    
    <node pkg="camera_lidar_calibration" name="cameraCalib" type="cameraCalib" output="screen"></node>

</launch>

执行下面的语句进行标定:

roslaunch camera_lidar_calibration cameraCalib.launch

标定的结果会保存在data/camera/result.txt中,包括重投影误差,内参矩阵和畸变纠正参数。以上文件夹需要创建。

最终得到的结果如图所示: 

 

2)准备图像中的角点坐标

首先需要把步骤2得到的内参和畸变纠正参数以下图的格式保存在data/parameters/intrinsic.txt文件下 [注 4]。distortion下面对应5个畸变纠正参数,按顺序是k1和k2 (RadialDistortion),p1和p2 (TangentialDistortion),最后一个是k3,一般默认是0

在launch文件中修改将对应的路径进行更改

<?xml version="1.0" encoding="UTF-8"?>
<launch>
  
    <param name="intrinsic_path"    value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/parameters/intrinsic.txt" />  <!-- intrinsic file -->
    <param name="input_photo_path"  value="/home/nvidia/LVI_ws/src/livox_camera_calib/data/frame4.png" />  <!-- photo to find the corner -->
    <param name="ouput_path"        value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/parameters/corner_photo.txt" />  <!-- file to save the photo corner -->
    <node pkg="camera_lidar_calibration" name="cornerPhoto" type="cornerPhoto" output="screen"></node>

</launch>

执行角点获取程序

 roslaunch camera_lidar_calibration cornerPhoto.launch

出现的问题是,图像显示后并不能在鼠标指向的时候显示图像中的角点,解决办法,因为在源程序中经过畸变矫正的图像,所以,将程序中经过图像矫正后的图像进行保存,然后使用保存后的图像,使用以下的程序,获得4个角点的坐标。以下的代码是基于python的,使用鼠标在界面上点击图像获得图像的坐标和RGB的值。

# import cv2
 
 
# def mouse(event, x, y, flags, param):
#     if event == cv2.EVENT_LBUTTONDOWN:
#         img1 = img.copy()
#         xy = "(%d,%d)" % (x, y)  # 设置坐标显示格式
#         cv2.circle(img1, (x, y), 1, (0, 255, 0), thickness=-1)
#         cv2.putText(img1, xy, (x+10, y-10), cv2.FONT_HERSHEY_PLAIN, 2, (0, 255, 0), thickness=1)
#         cv2.imshow("image", img1)  # 显示坐标
 
 
# def get_coordinate_by_click(img_path):
#     global img
#     img = cv2.imread(img_path)  # 图片路径
#     cv2.namedWindow("image", cv2.WINDOW_AUTOSIZE)  # 设置窗口标题和大小
#     # cv2.resizeWindow('image', 1000, 400)
#     cv2.setMouseCallback("image", mouse)
#     cv2.imshow("image", img)
#     cv2.waitKey(0)
#     cv2.destroyAllWindows()
 
 
# if __name__=='__main__':
#     img_path = "/home/nvidia/LVI_ws/src/livox_camera_calib/data/frame4.png"
#     get_coordinate_by_click(img_path)

import cv2
import numpy as np

img=cv2.imread('/home/nvidia/LVI_ws/src/livox_camera_calib/data/frame4_5.png')

def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        xy = "%d,%d" % (x, y)
        cv2.circle(img, (x, y), 1, (255, 0, 0), thickness = -1)
        cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
                    1.0, (0,0,0), thickness = 1)
        cv2.imshow("image", img)
cv2.namedWindow("image")
cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)
while(1):
    cv2.imshow("image", img)
    if cv2.waitKey(0)&0xFF==27:
        break
cv2.destroyAllWindows()

 输入角点的坐标的方向是从左上角的点开始,逆时针的旋转 ,输入正确之后,在corner_photo.txt中就会有角点的结果

3)获得雷达点云的角点坐标

雷达的点云获取,可以参考链接:livox_camera_lidar_calibration/README_cn.md at master · Livox-SDK/livox_camera_lidar_calibration · GitHub

查看点云的方式
roslaunch livox_ros_driver livox_lidar_rviz.launch
需要录制rosbag时输入另一个命令
roslaunch livox_ros_driver livox_lidar_msg.launch
需要注意:保存的rosbag数据格式是customMsg,后续程序中处理rosbag是对应的“livox custom msg format”格式。

       我直接使用了我已经转换好的PCD的文件 ,注意这里的PCD的点云,是激光长时间非重复式扫描的累加的一个文件。

使用pcl_viewer打开PCD文件,按住shift+左键点击即可获得对应的点坐标。注意和照片采用相同的角点顺序

pcl_viewer -use_point_picking xx.pcd

将xyz角点坐标按如下格式保存在data/corner_lidar.txt中,将所有PCD文件中雷达点云的角点坐标保存下来,如下图所示的格式: 

4)相机和激光的外参标定

外参计算节点会读取data/corner_photo.txt和data/corner_lidar.txt中的标定数据来计算外参,数据需要保存成特定的格式才能被外参计算节点正确读取。参考以下格式,每行数据只有超过10个字母程序才会将其读取为计算的参数,比如下图用来编号的1234,lidar0和0.bmp这些标题不会被读取为计算参数。程序读到空行就会停止读取参数开始计算,所以保存时不要空行。在计算前检查一下雷达和相机两个标定数据中是否每行对应的是同一个角点,并检查数据量是否相同。

修改getExt1.launch文件中,对应的TXT文件的绝对路径:

<?xml version="1.0" encoding="UTF-8"?>
<launch>
  
    <rosparam param="init_value">  [0.0, -1.0, 0.0, 0.0,
                                    0.0, 0.0, -1.0, 0.0,
                                    1.0, 0.0, 0.0,  0.0] </rosparam>  <!-- init value of roatation matrix(3*3 on the left) and the translation(3*1 vector on the right) -->

    <param name="intrinsic_path"    value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/parameters/intrinsic.txt" />  <!-- intrinsic file -->
    <param name="extrinsic_path"    value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/parameters/extrinsic.txt" />  <!-- extrinsic file -->
    <param name="input_lidar_path"  value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/parameters/corner_lidar.txt" />  <!-- get the lidar corner data -->
    <param name="input_photo_path"  value="/home/nvidia/calibration_ws/src/livox_camera_lidar_calibration/data/parameters/corner_photo.txt" />  <!-- get the photo corner data -->
    <param name="error_threshold"    type="int" value="12" />  <!-- the threshold of the reprojection error -->

    <node pkg="camera_lidar_calibration" name="getExt1" type="getExt1" output="screen"></node>

</launch>

执行的命令:

 roslaunch camera_lidar_calibration getExt1.launch

如果标定效果不好的话,就使用 getExt2节点,getExt1节点只优化外参,而getExt2节点在计算的时候会将一开始计算的内参作为初值和外参一起优化。输入指令程序会得到一个新的内参和外参,并用新的参数来进行重投影验证。一般使用getExt1节点即可,如果在外参初值验证过,并且异常值已经剔除后,优化还是有较大的残差,那么可以使用getExt2试一试。使用的前提需要保证标定数据量较大,并且要充分验证结果。

如果经过验证getExt2计算的结果确实更好,那么把新的内参更新在data/parameters/intrinsic.txt中。

1.3 标定完成后的精度验证

获得外参后我们可以用两个常见的应用看一下融合的效果。第一个是将点云投影到照片上,第二个是点云的着色

1)投影点云到照片

在projectCloud.launch文件中配置点云和照片的路径后,运行指令,将rosbag中一定数量的点投影到照片上并且保存成新的照片。

roslaunch camera_lidar_calibration projectCloud.launch

注意,使用mid-360激光雷达,因为雷达的ros驱动是 livox_ros_driver2,所以需要将源码中的消息类型进行更改。使用livox_ros_driver1录制的bag包不需要进行代码修改,切记修改后需要重新标定的。

 2) 点云着色

在colorLidar.launch文件中配置点云和照片的路径,运行指令,可以在rviz中检查着色的效果。

roslaunch camera_lidar_calibration colorLidar.launch

同样的,如果是MID-360的话,需要进行修改 

 着色效果:

 1.4 总结

1. 内参矩阵的格式如下图所示,一般在(0,0);(0,2);(1,1);(1,2)四个位置有对应的值。

                              

 2. 标定的基本原理是通过同一目标物在雷达坐标系下的xyz坐标相机坐标系下的xy坐标来计算并获得之间的转换关系。因为角点在点云和照片中都是比较明显的目标物,这样可以减少标定的误差。

3. 也可以使用多个标定板或者可以让雷达识别的棋盘格标定板。

4. 注意格式不要有变动,不然需要在程序中的common.h文件中的getIntrinsic和getDistortion程序中修改相关的代码。注意MATLAB中得到的内参矩阵是转置矩阵,输入到配置文件中时注意一下各个参数的位置。

5. 显示的照片是用畸变纠正参数修正过的。检查照片修正的是否正确,比如下图中左边的照片修正的有问题,可能是畸变参数写错了。右边的照片修正是正常的。

6,打开pcl_viewer后可以输入"h"来获得指引。

7,注意少于10个字段不能被读取为计算数据,如果点云xyz或者照片xy坐标比较短需要补足10个字段。

8,程序中的默认初值是根据Livox激光雷达自身坐标系,雷达和相机的相对位置设置的,要根据情况进行修改。如果初值差的很大可能会导致不好的优化结果。

9,如果迭代结束cost还是比较大的量级(比如10的4次方), 那可能是程序中初值设置的有问题,得到的只是一个局部最优解,那么需要重新设置初值计算。

10,点云投影到照片是通过内外参矩阵将雷达的点云投影到照片对应的位置,点云的颜色会根据距离从近到远显示从蓝到红;点云的着色是通过点云的xyz和得到的内外参矩阵算出对应的相机像素坐标,获取到这个像素的RGB信息后再赋给点云显示出来,这样雷达点云可以显示真实的颜色。

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

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

相关文章

C51 - SPI读写ADC

TSC20461> 项目概述2> 硬件设计3> TSC20463.1> TSC2046功能3.2> TSC2046控制命令3.3> 控制命令总结3.4> SPI协议3.5> 数据转换4> 软件编程4.1> 实现功能4.2> 编程思路4.3> SPI驱动4.4> TSC2046驱动5> 联调测试5.1> VBAT的1/4分压…

【论文简述】DELS-MVS: Deep Epipolar Line Search for Multi-View Stereo(WACV 2023)

一、论文简述 1. 第一作者&#xff1a;Mattia Rossi 2. 发表年份&#xff1a;2023 3. 发表期刊&#xff1a;WACV 4. 关键词&#xff1a;MVS、3D重建、极线搜素 5. 探索动机&#xff1a;目前的方法无论是深度值还是逆深度值&#xff0c;都需要提前确定深度值范围&#xff0…

java反序列化 URLDNS链分析

前言 终于可算是来到java反序列化&#xff0c;在菠萝师傅的一番提醒&#xff0c;我认识到自己不能继续在简单的游荡了&#xff0c;要来到难的地方了。 也庆祝自己终于拥有了勇气。 分析 基础 我相对喜欢先代码在讲原理&#xff0c;这里不怎么了解序列化可以去复习一下javase 可…

黑盒测试用例设计

目录 前言&#xff1a; 一、黑盒测试 二、实验目的 三、实验内容 四、实验步骤 五、实验过程 题目一 1、等价类划分表 2、设计测试用例 3、缺陷 4、代码实现 5、测试结果 题目二 设计测试用例 题目一示例代码&#xff08;java编写&#xff09; 总结 前言&#x…

苹果pencil和平替笔有哪些区别?性价比平替电容笔排行榜

而对于那些把ipad当做学习工具的学生党而言&#xff0c;电容笔就成了日常的必备品。但因为苹果Pencil的售价太贵了&#xff0c;学生们都买不起。因此&#xff0c;最好的选择还是平替电容笔。作为一个ipad的忠实用户&#xff0c;同时也是一个数码产品的热衷者&#xff0c;这两年…

1797F Li Hua and Path(Min-rt树,Max-rt树)

题目链接 题意 &#xff1a; 给你一个大小为nnn的树&#xff0c;我们想求解一个问题&#xff0c;问题的定义是找有多少条路径满足恰好满足路径的端点是路径的最小值ororor最大值条件之一&#xff0c;【注】不能同时满足路径的两个端点是最小值又是最大值 现在增加mmm个操作&am…

【Unity】基于AVFoundation开发MacOS摄像头(二)

【Unity】基于AVFoundation开发MacOS摄像头&#xff08;一&#xff09;_GrimRaider的博客-CSDN博客实现一个Camera设备驱动&#xff0c;代替unity自带WebCamTexturehttps://blog.csdn.net/GrimRaider/article/details/130127229 目标1&#xff1a;实现bridge&#xff0c;创建一…

【Java数据结构——环形链表】判断链表成环与寻找链表成环的入口节点(经典)

判断链表是否成环https://leetcode.cn/problems/linked-list-cycle/description/ 解题核心思路&#xff1a; 定义快慢指针初始引用指向链表的头节点&#xff0c;快指针每向后走两步&#xff0c;慢指针走一步。如果链表中存在环&#xff0c;则快慢指针一定会在某次移动后相遇。 …

一文看懂“低代码、零代码”是什么?有什么区别?

低代码和零代码近几年热度一直居高不下&#xff0c;乍一看&#xff0c;很容易混淆低代码和零代码开发平台—— 因为它们都是传统开发的替代方案&#xff0c;旨在通过类似于可视化编程的功能加速软件开发过程。 但二者根本不是一回事。从开发人员经验 、目标角色到使用场景&…

C++ 学习4

C设计原则 高内聚低耦合 内聚就是一个模块内各个元素彼此结合的紧密程度&#xff0c;高内聚就是一个模块内各个元素彼此结合的紧密程度高。 所谓高内聚是指一个软件模块是由相关性很强的代码组成&#xff0c;只负责一项任务&#xff0c;也就是常说的单一责任原则。 耦合&am…

计算机网络 - TCP的效率与特性

前言 本篇是介绍部分TCP的特性&#xff0c;了解TCP提高传输速率的机制&#xff1b;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流&#xff0c;共同进步&#xff01; 文章目录前言1. 滑动窗口2. 流量控制3.拥塞控制4.延时应答5. 捎带应答6. 面向字节流7. 异常…

spring bean

图灵课堂学习笔记 1. BeanFactory与ApplicationContext的关系 p56 ApplicationContext在BeanFactory基础上对功能进行了扩展&#xff0c;例如&#xff1a;监听功能、国际化功能等。BeanFactory的API更偏向底层&#xff0c;ApplicationContext的API大多数是对这些底层API的封…

python带你制作可以随机的自答题程序

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 目录前言环境使用:模块使用:程序实现思路: <模板> 获取题库一. 获取题库 --> 问题答案二. 进行自动答题操作代码展示题库采集自动答题尾语 &#x1f49d;环境使用: 解释器版本 >>> python 3.8 代码编辑器…

数学基础|线性代数回顾

因为学机器学习的时候发现自己线性代数忘光光了&#xff08;悲&#x1f613;&#xff0c;本篇捞一捞当年学线性代数看哔哩哔哩宋浩老师补充记的潦草笔记。 目录 &#x1f4da;线性代数知识点 &#x1f407;向量 &#x1f955;向量的线性组合 &#x1f955;线性相关无关的性…

JVM 工作原理和即时编译(JIT)

目录 1、什么是虚拟机&#xff1f; 2、JVM 虚拟机简介 3、JVM 的工作原理 4、什么是即时编译&#xff08;JIT&#xff09;&#xff1f; 5、解释型语言和编译型语言的区别 6、为什么说 Java 是一种半编译半解释的语言&#xff1f; 1、什么是虚拟机&#xff1f; 虚拟机是一…

直播美颜技术的演进及其应用:直播美颜SDK详解

直播美颜技术的应用&#xff0c;为直播开辟了新的业态&#xff0c;从最初简单的美颜滤镜&#xff0c;到现在的直播美颜SDK&#xff0c;其技术演进历程也是一步步走来。 一、直播美颜技术的演进 1、简单美颜滤镜 最初的直播美颜技术&#xff0c;就是通过简单的美颜滤镜来实现…

python内存回收gc模块

目录1. python 垃圾回收机制标记-清除的回收机制分代回收2. gc 模块参考资料对已经销毁的对象&#xff0c;Python不会自动释放其占据的内存空间。为了能够充分地利用分配的内存&#xff0c;避免程序跑到一半停止&#xff0c;要时不时地进行内存回收&#xff0c;这时候gc&#x…

超详细——Python中 pip 常用命令

人生苦短&#xff0c;我学Python 相信对于大多数熟悉Python的人来说&#xff0c;一定都听说并且使用过pip这个工具&#xff0c;但是对它的了解可能还不一定是非常的透彻&#xff0c;今天小编就来为大家介绍10个使用pip的小技巧&#xff0c;相信对大家以后管理和使用Python当中…

每天一道大厂SQL题【Day19】华泰证券真题实战(一)

每天一道大厂SQL题【Day19】华泰证券真题实战(一) 大家好&#xff0c;我是Maynor。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深大数据选手&#xff0c;深知SQL重要性&#xff0c;接下来我准备用100天时间&#xff0c;基于大数据岗面试中的经典SQL题&…

CSS中相对定位与绝对定位的区别及作用

CSS中相对定位与绝对定位的区别及作用场景复现核心干货相对定位绝对定位子绝父相&#x1f525;&#x1f525;定位总结绝对定位与相对定位的区别场景复现 在学习前端开发的过程中&#xff0c;熟练掌握页面布局和定位是非常重要的&#xff0c;因此近期计划出一个专栏&#xff0c…