当前位置: 首页 > 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. 递归删除目录及其目录下所有…...

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

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

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...