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

ORBBEC(奥比中光)AstraPro相机在ROS2下的标定与D2C(标定与配准)

文章目录

  • 1.rgb、depth相机标定矫正
    • 1.1.标定rgb相机
    • 1.2.标定depth相机
    • 1.3.rgb、depth相机一起标定(效果重复了,但是推荐使用)
    • 1.4.取得标定结果
      • 1.4.1.得到的标定结果的意义
    • 1.5.IR、RGB相机分别应用标定结果
      • 1.5.1.openCV应用标定结果
      • 1.5.2.ros2工程应用标定结果
  • 2.rgb、depth相机配准
    • 2.1.求外参(R、T矩阵)
    • 2.2.求两个相机之间的R、T矩阵
    • 2.3.进行D2C操作
  • 3.题外话

相机自带的D2C效果不好,颜色和点云没有很好地匹配上,自己按照下面的介绍手动匹配一下。

1.rgb、depth相机标定矫正

在下载来的sdk,里面没有标定的文件:ost.yaml.
需要自己进行标定、生成。

我所使用的相机型号是Astra_pro,它是一个单目结构光相机,有一个RGB摄像头+一个IR摄像头。实际上算是一个双目相机(rgb+ir)。【奥比中光Astra深度传感器工作原理】

在ros2(humble)中,需要先安装相机标定套件:

    sudo apt install ros-humble-camera-*sudo apt install ros-humble-launch-testing-ament-cmake

在我的系统中,可以分别对这两个进行相机进行标定
在这里插入图片描述
在标定时,具体的参数(相机、话题、格子数等等)要根据你实际的情况进行填写。

1.1.标定rgb相机

执行以下命令

ros2 run camera_calibration cameracalibrator --size 6x7 --square 0.015 --no-service-check image:=/camera/color/image_raw camera:=/camera/color

在这里插入图片描述

1.2.标定depth相机

深度摄像头看起来和RGB摄像头差别很大,实际上有很多相似之处。就Kinect而言,其通过一个红外散斑发射器发射红外光束,光束碰到障碍物后反射回深度摄像头,然后通过返回散斑之间的几何关系计算距离。其实,Kinect的深度摄像头就是一个装了滤波片的普通摄像头,只对红外光成像的摄像头(可以这么认为)。因此要对其标定,只需用红外光源照射物体即可,LED红外光源在淘宝上就20元一个。还有一点必须注意,在拍摄红外照片时,要用黑胶带(或其他东西)将Kinect的红外发射器完全挡住,否则其发出的散斑会在红外照片中产生很多亮点,不利于棋盘角点的检测。
————————————————
原文链接:https://blog.csdn.net/aichipmunk/article/details/9264703

我这里就偷懒了,直接用自带的红外散斑发射器来标定。追求准确的同学,最好还是按照上面说的遮住红外发射器+买一个红外光源。

ros2 run camera_calibration cameracalibrator --size 6x7 --square 0.015 --no-service-check image:=/camera/ir/image_raw camera:=/camera/ir

在这里插入图片描述

1.3.rgb、depth相机一起标定(效果重复了,但是推荐使用)

假如已经进行了上面rgb、depth相机的分别标定,这一步其实没必要进行,效果是一样的。
但是这个一起标定的话,有个好处:在后面计算外参时,可以直接拿到同一时刻两个相机分别拍到的图像。
【ROS下采用camera_calibration进行双目相机标定】

ros2 run camera_calibration cameracalibrator --size 6x7 --square 0.015 --approximate 0.1 --no-service-check left:=/camera/ir/image_raw left_camera:=/camera/ir right:=/camera/color/image_raw right_camera:=/camera/color

在这里插入图片描述

1.4.取得标定结果

参考上面提到的文章进行操作后,分别可以在/tmp目录下得到标定后的数据。
在这里插入图片描述无论是用camera_calibration进行单目标定和双目标定,貌似没有本质的区别,都是分别得到两个相机的内参。
得到的相机内参入下图所示:
在这里插入图片描述
以上图为例,可以知道相机的内参fx=628.54905,fy=631.37457;这是说相机镜头的焦距为628.54905mm吗?
不是,这个是以像素为单位的,镜头的焦距为628.54905像素。那1像素代表多少mm呢(像元尺寸)?
这个要看相机感光芯片的尺寸及芯片的分辨率。假设感光芯片尺寸为WH(单位mm),分辨率为UV,那么像元尺寸为[W/U, H/V).
在这里插入图片描述以上面的海康威视相机为例,假如我标定时使用的是这个相机(像元尺寸6.9um),然后得到的内参为fx=628.54905,fy=631.37457,那么,通过标定得知的镜头焦距:f=628.54905 * 6.9 um=4336.988445um=4.3mm。也就是说这个镜头大概是4.3mm的镜头。
关于靶面、像元的介绍,可以看看这里:【相机和镜头选型需要注意哪些问题】、【相机靶面尺寸详解+工业相机选型】

1.4.1.得到的标定结果的意义

各标定参数的意义:

image_width、image_height代表图片的长宽
camera_name为摄像头名
camera_matrix规定了摄像头的内部参数矩阵
distortion_model指定了畸变模型
distortion_coefficients指定畸变模型的系数
rectification_matrix为矫正矩阵,一般为单位阵
projection_matrix为外部世界坐标到像平面的投影矩阵

也可以看看这个
【相机内参标定究竟标了什么?相机内参外参保姆级教程】

1.5.IR、RGB相机分别应用标定结果

得到标定结果后,有两种方法应用标定结果。

1.5.1.openCV应用标定结果

假如需要自己进行相机的画面矫正,可以使用opencv来进行。opencv只用到上面的camera_matrix、distortion_coefficients这两组数据
【opencv畸变校正的两种方法】

1.5.2.ros2工程应用标定结果

我这里可以直接修改卖家提供的源码里面的launch.xml文件的内容,让其加载标定结果。
设置好文件路径之后,出现 “Invalid camera calibration URL”的解决办法
要加上file://前缀,格式如下:
在这里插入图片描述假如出现 does not match narrow_stereo in时
在这里插入图片描述将ost.yaml里面相机的名字改成和报错的一致:
在这里插入图片描述 由于AstraPro的rgb、ir镜头的畸变不明显,标定校准后,畸变的校准效果也不明显,这里就不贴对比图上来了。

2.rgb、depth相机配准

两个相机都标定完之后,就需要进行配准,也就是要得到从ir图到rgb图的映射(旋转矩阵R、平移矩阵T),从而得到对应深度点的颜色值。
【视觉SLAM十四讲(第二版)第5讲习题解答】
在这里插入图片描述
根据【Kinect深度图与RGB摄像头的标定与配准】里面分析到的,要求RT,就需要先求出外参。

2.1.求外参(R、T矩阵)

从【Opencv——相机标定】的介绍可以看到,opencv的函数calibrateCamera在根据若干组棋盘格点坐标,计算得到相机内参时,也可以得到每张图片的外参。但是我们目前是用ros的camera_calibration得到的相机内参(虽然内部也是opencv,但是camera_calibration没有给我们保存外参),所以不能够直接得到可用的外参。
但是,我们可以从前面双目标定得到的结果中选取同一时刻拍摄的两张图片(一张是rgb相机的,一张是ir相机的)
在这里插入图片描述然后按照【OPENCV已知内参求外参】、【OPENCV标定外参】,利用上面的两张图片+各自相机的内参,分别算出每个相机的外参,主要代码如下:

#include <opencv2/opencv.hpp>
#include <opencv2/calib3d.hpp>using namespace std;
using namespace cv;// 根据已知的信息计算外参
int calcExtrinsics(string fileName, Mat cameraMatrix, Mat distCoeffs, Size board_size, double rectWidth,Mat &R, Mat &T)
{vector<Point2f> image_points;  /* 图像上检测到的角点 */Mat imageInput = imread(fileName, IMREAD_COLOR);cout << "image size:" << imageInput.cols << "," << imageInput.rows << endl;cout << "cameraMatrix:" << cameraMatrix << endl;cout << "distCoeffs:"   << distCoeffs   << endl;// 显示一下纠正后的图像,直观地检查一下传递进来的cameraMatrix、disCoeffs有没有问题Mat undistortMat;undistort(imageInput, undistortMat, cameraMatrix, distCoeffs);imshow("undistort mat", undistortMat);cout << "undistortMat size:" << undistortMat.cols << "," << undistortMat.rows << endl;/* 提取角点 */if (0 == findChessboardCorners(imageInput, board_size, image_points)){cout << "can not find chessboard corners!\n"; //找不到角点return -1;}else{Mat view_gray;cvtColor(imageInput, view_gray, COLOR_RGB2GRAY);/* 亚像素精确化 */find4QuadCornerSubpix(view_gray, image_points, Size(11,11)); //对粗提取的角点进行精确化//        // 看看点的排列顺序//        image_points_buf[0] += Point2f(-50, -100);//        image_points_buf[8] += Point2f(-60, -100);/* 在图像上显示角点位置 */Mat displayImg = imageInput.clone();drawChessboardCorners(displayImg, board_size, image_points, true); //用于在图片中标记角点imshow("Camera Calibration", displayImg);//显示图片}// 上面已经得到了标定板的二维坐标,现在来填充三维坐标vector<Point3f> object_points;for(int i = 0; i < board_size.height; i++){for(int j = 0; j < board_size.width; j++){object_points.push_back(Point3f(rectWidth * j, rectWidth * i, 0));}}//    cout << "object points:" << object_points << endl;cout << image_points.size() << " "<< object_points.size() << endl;//创建旋转矩阵和平移矩阵//    Mat rvecs = Mat::zeros(3, 1, CV_64FC1);//    Mat tvecs = Mat::zeros(3, 1, CV_64FC1);Mat rvec;Mat tvec;//求解pnpbool pnpResult = false;//    pnpResult = solvePnP(object_points, image_points, cameraMatrix, distCoeffs, rvec, tvec);pnpResult = solvePnPRansac(object_points, image_points, cameraMatrix, distCoeffs, rvec, tvec);cout << "pnp result:" << pnpResult << endl;if(pnpResult == false){return -2;}Mat rotM;Rodrigues(rvec, rotM);  //将旋转向量变换成旋转矩阵R = rotM;T = tvec;// 直观地检验一下计算到的R、T有没有问题{vector<Point2f> image_points2; /* 保存重新计算得到的投影点 */projectPoints(object_points, rvec, tvec, cameraMatrix, distCoeffs, image_points2);/* 在图像上显示角点位置 */Mat displayImg = imageInput.clone();drawChessboardCorners(displayImg, board_size, image_points2, true); //用于在图片中标记角点imshow("projectPoints image", displayImg);//显示图片}return 0;
}// 分别对两个相机进行外参计算
void calcExtrinsicsDemo()
{
//#define calc_rgb // 通过注释这个来切换// 图像路径std::string fileName;Size board_size = Size(7, 6);   // 标定板上每行、列的角点数double rectWidth = 0.015;       // 标定版棋盘格的大小,单位m//相机内参矩阵Mat cameraMatrix;//相机畸变系数Mat distCoeffs;#ifdef calc_rgbfileName = "/home/yong/Desktop/orbbec/calibration/dual/calibrationdata/right-0000.png";     // rgb 图像路径
#elsefileName = "/home/yong/Desktop/orbbec/calibration/dual/calibrationdata/left-0000.png";     // ir 图像路径
#endif#ifdef calc_rgb// rgb相机参数double camData[] = {628.549051,  0.000000,   324.691230,0.000000,    631.374570, 283.546017,0.000000,    0.000000,   1.000000};cameraMatrix = Mat(3, 3, CV_64F, camData);double distData[] = {0.195904,-0.299118,0.018483,0.005324,0.000000};distCoeffs = Mat(5, 1, CV_64F, distData);
#else// ir相机参数double camData[] = {588.560930, 0.000000  ,  306.212790,0.000000  , 590.708852,  250.991143,0.000000  , 0.000000  ,  1.000000};cameraMatrix = Mat(3, 3, CV_64F, camData);double distData[] = {-0.044573,0.212463,0.006501,-0.006851,0.000000};distCoeffs = Mat(5, 1, CV_64F, distData);
#endifMat R,T;calcExtrinsics(fileName, cameraMatrix, distCoeffs, board_size, rectWidth, R, T);cout << "R:" << R << endl;cout << "T:" << T << endl;}

2.2.求两个相机之间的R、T矩阵

通过上面的代码,计算得到了rgb、ir(depth)相机的外参:

    // rgb
//R:[0.9932208622695912, -0.104179968756072, -0.05156406561195055;
//     0.09876316392901367, 0.9902419675733234, -0.09831929163314773;
//     0.06130380251811834, 0.09256014134873089, 0.9938181242210883]
//        T:[-0.1985727556503669;
//                -0.1321870936778361;
//                0.5274038381890026]// ir
//R:[0.9949185009774844, -0.1001176653598934, 0.01065971367344506;
//     0.1005768682173857, 0.9931508653869539, -0.05946135014214975;
//     -0.004633572304179904, 0.06023131796689411, 0.9981736914704138]
//        T:[-0.1633382501071563;
//                -0.1003269691775472;
//                0.5162717136103199]

然后我们根据【Kinect深度图与RGB摄像头的标定与配准】里面的公式:
在这里插入图片描述计算一下R、T:

Mat R_rgb, T_rgb, R_ir, T_ir;{double data[] =  {0.9932208622695912, -0.104179968756072, -0.05156406561195055,0.09876316392901367, 0.9902419675733234, -0.09831929163314773,0.06130380251811834, 0.09256014134873089, 0.9938181242210883};R_rgb = Mat(3, 3, CV_64F, data).clone();}{double data[] =  {-0.1985727556503669, -0.1321870936778361, 0.5274038381890026};T_rgb = Mat(3, 1, CV_64F, data).clone();}{double data[] =  {0.9949185009774844, -0.1001176653598934, 0.01065971367344506,0.1005768682173857, 0.9931508653869539, -0.05946135014214975,-0.004633572304179904, 0.06023131796689411, 0.9981736914704138};R_ir = Mat(3, 3, CV_64F, data).clone();}{double data[] =  {-0.1633382501071563,-0.1003269691775472,0.5162717136103199};T_ir = Mat(3, 1, CV_64F, data).clone();}//    cout << R_rgb << endl << T_rgb;Mat R, T;R = R_rgb * R_ir.inv();T = T_rgb - R*T_ir;cout << "R:" << R << endl;cout << "T:" << T << endl;/*
R:[0.9980544085026888, -0.0005053133907268852, -0.06234695122237745;-0.00192747042416588, 0.9992391545866735, -0.03895377772019822;0.06231919869600642, 0.03899816148599567, 0.9972940694071134]
T:[-0.003415024268825395;-0.01214055388563491;0.02662079621125524]*/

2.3.进行D2C操作

有了R和T,我们就可以用rgb来对点云着色),注意,此时我们不是用ir图了,而是用depth图了,depth图是16uc1类型的,其数值表示深度(单位mm)。

#include <Eigen/Core>
#include <Eigen/LU>void depthToColor(Mat depthMat, Mat bgrMat)
{Eigen::Matrix3f R_ir2rgb;R_ir2rgb <<0.9980544085026888, -0.0005053133907268852, -0.06234695122237745,-0.00192747042416588, 0.9992391545866735, -0.03895377772019822,0.06231919869600642, 0.03899816148599567, 0.9972940694071134;Eigen::Vector3f T_ir2rgb;T_ir2rgb <<-0.003415024268825395,-0.01214055388563491,0.02662079621125524;Eigen::Matrix3f K_ir;           // ir内参矩阵K_ir <<588.560930, 0.000000  ,  306.212790,0.000000  , 590.708852,  250.991143,0.000000  , 0.000000  ,  1.000000;Eigen::Matrix3f K_rgb;          // rgb内参矩阵K_rgb <<628.549051,  0.000000,   324.691230,0.000000,    631.374570, 283.546017,0.000000,    0.000000,   1.000000;//    Eigen::Matrix3f R;
//    Eigen::Vector3f T;
//    R = K_rgb*parm->R_ir2rgb*K_ir.inverse();
//    T = K_rgb*parm->T_ir2rgb;cout << "K_rgb:\n" << K_rgb << endl;cout << "K_ir:\n" << K_ir << endl;
//    cout << "R:\n" << R << endl;
//    cout << "T:\n" << T << endl;// 4.2 计算投影Mat result(480, 640, CV_8UC3);int i = 0;for (int row = 0; row < 480; row++){for (int col = 0; col < 640; col++){unsigned short* p = (unsigned short*)depthMat.data;unsigned short depthValue = p[row * 640 + col];//cout << "depthValue       " << depthValue << endl;if (depthValue != std::numeric_limits<unsigned short>::infinity() &&depthValue != -std::numeric_limits<unsigned short>::infinity() &&depthValue != 0 &&depthValue != 65535){// 投影到彩色图上的坐标// 1)构造一个三维向量p_ir = (x, y, z),其中x,y是该点的像素坐标,z是该像素的深度值;Eigen::Vector3f p_ir(col, row, 1.0f);// 2)用Kinect内参矩阵H_ir的逆,乘以p_ir得到对应的空间点坐标P_ir,具体公式见上文第四部分(配准);Eigen::Vector3f P_ir = K_ir.inverse() *  (p_ir *  (depthValue / 1000.f)); // (除以1000,是为了从毫米变米)// 现在这个P_ir,可以放到点云去显示// 3)由于P_ir是该点在Kinect坐标系下的坐标,我们需要将其转换到RGB摄像头的坐标系下,具体的,就是乘以一个旋转矩阵R,再加上一个平移向量T,得到P_rgb;Eigen::Vector3f P_rgb = R_ir2rgb * P_ir + T_ir2rgb;// 4)用RGB摄像头的内参矩阵H_rgb乘以P_rgb,得到p_rgb,// p_rgb也是一个三维向量,其x和y坐标即为该点在RGB图像中的像素坐标,取出该像素的颜色,作为深度图像中对应像素的颜色;Eigen::Vector3f p_rgb = K_rgb * P_rgb;int X = static_cast<int>(p_rgb [0] / p_rgb [2]);                // !!!Z_rgb*p_rgb -> p_rgbint Y = static_cast<int>(p_rgb [1] / p_rgb [2]);                // !!!Z_rgb*p_rgb -> p_rgb//cout << "X:       " << X << "     Y:      " << Y << endl;if ((X >= 0 && X < 640) && (Y >= 0 && Y < 480)){//cout << "X:       " << X << "     Y:      " << Y << endl;result.data[i * 3]     = bgrMat.data[3 * (Y * 640 + X)];result.data[i * 3 + 1] = bgrMat.data[3 * (Y * 640 + X) + 1];result.data[i * 3 + 2] = bgrMat.data[3 * (Y * 640 + X) + 2];}else{result.data[i * 3] = 0;result.data[i * 3 + 1] = 0;result.data[i * 3 + 2] = 0;}}else{result.data[i * 3] = 0;result.data[i * 3 + 1] = 0;result.data[i * 3 + 2] = 0;}i++;}}imshow("result", result);
}

根据原文的介绍:
在这里插入图片描述

在应用R、T矩阵时,可以根据实际情况微调一下T矩阵的x、y
在这里插入图片描述

但是经过尝试,假如调好了近处的物体,远处的物体和颜色又对不齐;反之亦然。可能是硬件的问题。
另外,我用这种方式得到点云与官方的点云在X、Y方向有较大的偏差,可能是我通过标定得到的内参和官方的内参存在较大差异导致的。
在这里插入图片描述

3.题外话

我们用的点云来源自IR相机,点云的坐标(XYZ)是基于IR相机坐标系的。因此手眼标定时,要用IR相机去参与标定,而不是RGB相机。
我们先小试牛刀,将点云的坐标变换到标定板坐标系下,效果如下:
在这里插入图片描述
在这里插入图片描述

可以看到,我虽然斜着放置相机,但是经过标定后,点云的姿态是能够与标定板表示的坐标系基本对齐的。

方法其实也就是拿IR相机针对标定板得到的外参(R、T)组成变换矩阵transform,由于此时的transform是标定板到相机的变换,而我们要将相机坐标系下的坐标转变为标定板坐标系下的坐标,因此需要求逆矩阵cam2ObjTransform,然后用它来对点云作变换。

在这里插入图片描述


参考:
【1.Astra相机标定】
【【Nav2中文网】ROS2单目相机标定教程】
【深度图与彩色图的配准与对齐】
【Kinect深度图与RGB摄像头的标定与配准】
【RGBD相机实用问题】
【相机内参标定究竟标了什么?相机内参外参保姆级教程】

相关文章:

ORBBEC(奥比中光)AstraPro相机在ROS2下的标定与D2C(标定与配准)

文章目录 1.rgb、depth相机标定矫正1.1.标定rgb相机1.2.标定depth相机1.3.rgb、depth相机一起标定&#xff08;效果重复了&#xff0c;但是推荐使用&#xff09;1.4.取得标定结果1.4.1.得到的标定结果的意义 1.5.IR、RGB相机分别应用标定结果1.5.1.openCV应用标定结果1.5.2.ros…...

常量与变量:编程中重要的两种数据类型

常量与变量 在编程中&#xff0c;我们常常需要存储一些数据。这些数据有些是恒定不变的&#xff0c;有些却是可以随时变化的。对于恒定不变的数据&#xff0c;我们称之为常量&#xff1b;对于可以变化的数据&#xff0c;我们则称之为变量。这两种数据类型在程序中非常重要&…...

( 数组和矩阵) 287. 寻找重复数 ——【Leetcode每日一题】

❓287. 寻找重复数 难度&#xff1a;中等 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返回 这个重复的数 。 你…...

【学习笔记】「JOISC 2022 Day2」复制粘贴 3

看了正解。我觉得很厉害。虽然用减枝水过去了。 区间 d p dp dp。但是这个转移怎么看都不是 O ( 1 ) O(1) O(1)的。 border \text{border} border 那么 trick \text{trick} trick应该都能看出来。能进行剪切操作当且仅当 s [ l , p ] s [ q , r ] s_{[l,p]}s_{[q,r]} s[l,p]​…...

武忠祥老师每日一题||定积分基础训练(三)

常用的基本不等式&#xff1a; sin ⁡ x < x < t a n x , x ∈ ( 0 , π 2 ) \sin x<x<\ tan x,x\in(0,\frac{\pi}{2}) sinx<x< tanx,x∈(0,2π​) e x ≥ 1 x , x ∈ ( − ∞ , ∞ ) e^x\ge1x,x\in(-\infty,\infty) ex≥1x,x∈(−∞,∞) x 1 x ≤ ln …...

Docker安装常用软件-Apollo(有问题)

零&#xff1a;apollo概念介绍 官网网站&#xff1a;GitHub - apolloconfig/apollo: Apollo is a reliable configuration management system suitable for microservice configuration management scenarios. gitee网址&#xff1a;mirrors / ctripcorp / apollo GitCode …...

f(x)与|f(x)|,f ‘ (x),F(x)常见关系。

1.f(x)与|f(x)|关系。 1.连续关系。(f(x)在"[a,b]上连续" > |f(x)|在"[a,b]连续") ①如果f(x)在[a,b]上连续。则|f(x)|在[a,b]上连续. &#xff08;因为f(x)在x0的连续点>x0必为|f(x)|的连续点&#xff09; 注&#xff1a;”[a,b]连续“包括&#…...

今天面了一个来字节要求月薪23K,明显感觉他背了很多面试题...

最近有朋友去字节面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…...

如何使用二元三次回归分析建立预测模型?(分析、原理、代码示例)

二元三次回归是一种用于建立两个自变量与一个因变量之间关系的回归模型&#xff0c;常用于数据分析和预测。下面我会更详细地解释一下二元三次回归的原理、分析和示例代码。 1、原理 二元三次回归分析用多项式回归建立预测模型&#xff0c;其中包括两个自变量&#xff08;通常…...

面向万物智联的应用框架的思考和探索(上)

原文&#xff1a;面向万物智联的应用框架的思考和探索&#xff08;上&#xff09;&#xff0c;点击链接查看更多技术内容。 应用框架&#xff0c;是操作系统连接开发者生态&#xff0c;实现用户体验的关键基础设施。其中&#xff0c;开发效率和运行体验是永恒的诉求&#xff0c…...

《Python机器学习基础教程》第1章学习笔记

目录 第1章 引言 1.1 为何选择机器学习 1.1.1 机器学习能够解决的问题 第1章 引言 机器学习又称为预测分析或统计学习&#xff0c;是一个交叉学科&#xff0c;是从数据中提取知识。 1.1 为何选择机器学习 智能应用早期&#xff0c;使用专家设计的规则体系来设计。 缺点&…...

ClickHouse 内存管理是如何实现的

概述 本文介绍Clickhouse内存管理的实现原理。通过本文的分析&#xff0c;可以对Clickhouse的内存管理有一个概要的理解。 Clickouse内存管理组成 ClickHouse 使用内存管理系统来控制内存资源的分配和释放。内存管理系统的主要组成部分是&#xff1a; 内存池&#xff1a;Cl…...

docker容器技术

什么是docker Docker 使用 Google 公司推出的 Go 语言 进行开发实现&#xff0c;基于 Linux 内核的 cgroup&#xff0c;namespace&#xff0c;以及 OverlayFS 类的 Union FS 等技术&#xff0c;对进程进行封装隔离&#xff0c;属于 操作系统层面的虚拟化技术。由于隔离的进程独…...

设计模式七大设计原则

文章目录 1、什么是设计模式2、单一职责原则3、开闭原则4、接口隔离原则5、依赖倒置原则6、迪米特法则&#xff08;最少知道原则&#xff09;7、里式替换原则8、组合优于继承 设计模式主要是为了满足一个字 变&#xff0c;这个字&#xff0c;可能是需求变更、可能是场景变更&a…...

【Hello Network】TCP协议相关理解

作者&#xff1a;小萌新 专栏&#xff1a;网络 作者简介&#xff1a;大二学生 希望能和大家一起进步 本篇博客简介&#xff1a;补充下对于TCP协议的各种理解 TCP协议相关实验 TCP相关试验理解CLOSE_WAIT状态理解TIME_WAIT状态解决TIME_WAIT状态引起的bind失败的方法理解listen的…...

实施CRM目标有哪几步?如何制定CRM目标?

在当今竞争激烈的商业环境中&#xff0c;与客户建立持久的关系是企业重要的工作。CRM客户管理系统能有效帮助企业管理优化流程、管理客户&#xff0c;提高销售成功率&#xff0c;推动收入增长。那么您了解如何实施CRM吗&#xff1f;下面说说实施CRM目标是什么&#xff0c;如何设…...

船舶建造概论(船舶建造工艺任务与现代造船模式)

船舶建造概论 1 船舶建造概论1.1 船舶建造工艺主要任务1.2 船舶建造流程&#xff08;1&#xff09;钢材料预处理&#xff08;2&#xff09; 钢材料加工&#xff08;3&#xff09;分段制作&#xff08;4&#xff09;总段制作&#xff08;5&#xff09;船台合拢&#xff08;6&…...

项目内训(2023.5.6)

目录 Nacos是什么&#xff1f; 领域模型是什么&#xff1f; domain模块一般是干什么的&#xff1f; 在小乌龟中合并其他分支的作用是什么&#xff1f; nacos的配置文件 服务集群、服务提供、服务更加灵活庞大、消费服务、访问比较麻烦&#xff0c;A和B服务一起访问 系统结…...

【操作系统OS】学习笔记第二章 进程与线程(下)【哈工大李治军老师】

基于本人观看学习 哈工大李治军老师主讲的操作系统课程 所做的笔记&#xff0c;仅进行交流分享。 特此鸣谢李治军老师&#xff0c;操作系统的神作&#xff01; 如果本篇笔记帮助到了你&#xff0c;还请点赞 关注 支持一下 ♡>&#x16966;<)!! 主页专栏有更多&#xff0…...

Linux命令集(Linux文件管理命令--rmdir指令篇)

Linux命令集&#xff08;Linux文件管理命令--rmdir指令篇&#xff09; Linux文件管理命令集&#xff08;rmdir指令篇&#xff09;5. rmdir(remove directory)1. 删除空的目录 folder12. 强制删除目录 folder1&#xff08;包括非空目录&#xff09;3. 递归删除目录及其目录下所有…...

在技术圈超卷的当下,学历到底是敲门砖还是枷锁?

前言 最近&#xff0c;突然之间被“孔乙己文学”刷屏了&#xff0c;短时间内“孔乙己文学”迅速走红&#xff0c;孔乙己是中国文学中的一位经典人物&#xff0c;他的长衫被认为是他的象征之一&#xff0c;孔乙己的长衫折射出很多现象&#xff0c;既有社会的&#xff0c;也有教育…...

Linux cgroup

前言 Cgroup和namespace类似&#xff0c;也是将进程进程分组&#xff0c;但是目的与namespace不一样&#xff0c;namespace是为了隔离进程组之前的资源&#xff0c;而Cgroup是为了对一组进程进行统一的资源监控和限制。 Cgroup的组成 subsystem 一个subsystem就是一个内核模…...

PID整定二:基于Ziegler-Nichols的频域响应

PID整定二&#xff1a;基于Ziegler-Nichols的频域响应 1参考2连续Ziegler-Nichols方法的PID整定2.1整定方法2.2仿真示例 1参考 1.1根轨迹图的绘制及分析 1.2计算机控制技术01-3.4离散系统的根轨迹分析法 1.3PID控制算法学习笔记 2连续Ziegler-Nichols方法的PID整定 2.1整定…...

【tkinter 专栏】专栏前言

文章目录 前言本章内容导图1. tkinter 工具及特点2. 为什么使用 Python 进行 GUI 设计?2.1 Python 可以做什么2.2 使用 tkinter 可以干什么?3. 如何学习使用 tkinter 进行 GUI 设计?4. 开发环境搭建4.1 Python 的版本4.2 安装 Python4.2.1 下载 Python 安装包4.2.2 安装 Pyt…...

解决Linux中文字体模糊的4种方法

在Linux中&#xff0c;字体是非常重要的一部分&#xff0c;因为它们直接影响到用户的视觉体验。如果Linux字体模糊不清&#xff0c;那么用户将很难阅读文本&#xff0c;这将极大地降低用户的工作效率。本文将介绍Linux Mint中文字体模糊的问题&#xff0c;并提供一些解决方案。…...

【Android入门到项目实战-- 7.3】—— 如何调用手机摄像头和相册

目录 一、调用摄像头拍照 二、打开相册选择照片 学完本篇文章可以收获如何调用手机的摄像头和打开手机相册选择图片功能。 一、调用摄像头拍照 先新建一个CameraAlbumTest项目。 修改activity_main.xml,代码如下&#xff1a; 按钮打开摄像头&#xff0c;ImageView将拍到的…...

浅聊AIOT

引言 IoT是(Internet of Things)的简称&#xff0c;也就是人们常说的物联网&#xff1b;随着智能硬件的发展和推广&#xff0c;制造成本也随之下降&#xff0c;很多的厂家也慢慢地拥抱网络互联&#xff0c;逐步实现设备互联&#xff0c;也就进入了人们常说的万物互联时代。虽然…...

Python之模块和包(九)

1、模块 1、模块概述 模块是一个包含了定义的函数和变量等的文件。模块可以被程序引入&#xff0c;以使用该模块中的函数等功能。通俗讲&#xff1a;模块就好比是工具包&#xff0c;要想使用这个工具包中的工具(就好比函数)&#xff0c;就需要导入这个模块。 2、import 在P…...

C++-----动态规划

目录 一、动态规划的基本思想 二、设计动态规划法的步骤 三、动态规划问题的特征 4.1 矩阵连乘积问题 4.1.1 分析最优解的结构 4.1.2 建立递归关系 4.1.3 计算最优值 4.1.3 计算最优值 4.1.3 构造最优解 4.2 动态规划算法的基本要素 4.2.1 最优子结构 4.2.2 重叠子问题 …...

2.2 Linux控制台访问CLI

系列文章目录 第1章 Linux Shell简介 第2章 Shell基础 <本章所在位置> 第3章 Bash Shell基础命令 第4章 Bash Shell命令进阶 第5章 Linux Shell深度理解 第6章 Linux环境变量 第7章 Linux文件权限 第8章 Linux文件系统的管理 第9章 Linux软件安装 第10章 Linux文本编辑器…...

主页模板/网站做优化

一、准备工作1、安装JDK并且配置好环境变量二、安装mysql1、下载mysql安装包&#xff0c;放到带安装的目录下。2、配置环境变量3、新增my.ini文件新建my.ini文件并编辑写入如下内容&#xff0c;不需要另外创建data目录&#xff0c;下一步初始化操作的时候会自动创建。在安装目录…...

wordpress 分类页/青岛seo排名公司

.net获取任务管理器内存A basic question.. “What is the Garbage Collector?”一个基本的问题。“什么是垃圾收集器&#xff1f;” The usual answer given back: “Garbage collector is a background thread run by the CLR for freeing up the memory space used by the…...

做购物网站数据库分析/网络营销软文范文

1&#xff0e;明确终端服务的2种模式 ----Windows 2000终端服务有2种运行模式: 远程管理模式和应用程序服务器模式。远程管理模式允许系统管理员远程管理服务器&#xff0c;而且只允许2个终端会话同时登录终端服务器。应用程序服务器模式允许用户运行一个以上应用程序&#xff…...

企业官方网站建设规划/自媒体账号申请

不知道哦是不是不小心点了哪里&#xff0c;pycharm开始不停闪烁并且显示updating indices, 暂停服务重启电脑都不起作用&#xff0c;用以下操作就成功解决了问题。 File-> 选中Invalidate Caches/Restart ->Invalidate Caches/Restart 好像是因为项目中有大量的文件&…...

网站设计数据库怎么做/刷赞网站推广免费链接

命令1 & 命令2 & 命令3 ... (无论前面命令是否故障,照样执行后面) 命令1 && 命令2 && 命令3.... (仅当前面命令成功时,才执行后面) 命令1 || 命令2 || 命令3.... (仅当前面命令失败时.才执行后面)1、start 用来启动一…...

自做装逼头像网站/关键词推广优化app

TCP主动关闭连接 appl: close(), --> FIN FIN_WAIT_1 //主动关闭socket方&#xff0c;调用close关闭socket,发FIN <-- ACK FIN_WAIT_2 //对方操作系统的TCP层&#xff0c;给ACK响应。然后给FIN <-- FIN …...