(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)
一、四大坐标系介绍
1,世界坐标系
从这个世界(world)的视角来看物体
世界坐标系是3D空间坐标,每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)表示
2,相机坐标系
相机本身具有一个坐标系,其也是3D空间坐标
从相机(camera)的视角来看物体,每个点的位置用 ( X c , Y c , Z c ) (X_c,Y_c,Z_c) (Xc,Yc,Zc)表示
3,图像坐标系
相机坐标系是3D空间的,而我们通过相机拍照得到的照片却是2D平面,这之间涉及到了透视投影(perspective projection),大白话就是相似三角形,将3D空间上的点映射到2D平面上
图像坐标系是实际的物理坐标系 ( x , y ) (x,y) (x,y),其原点位置一般在相机光轴成像与成像平面的交点位置,通常为成像平面的中心点,物理单位为mm
4,像素坐标系
我们在处理图像数据的时候,使用的是像素坐标系 ( u , v ) (u,v) (u,v),比如这个图像的大小为1080*720,即长和宽为1080和780个像素;分辨率等相关概念也是这个大概意思,单位是像素pixel
每个像素都有对应的实际物理尺寸,比如1像素=0.5mm
像素有些情况是矩形,分为x和y方向的长度
5,总结
我们需要通过一些手段,将原本在世界坐标系下的点转换到像素坐标系下
世界坐标系是因为物体本身真实存在的位置,而转到像素坐标系下是因为我们在进行图像处理的时候针对的是像素
故,相机标定的最终目的是实现世界坐标系和像素坐标系之间的转换
二、四大坐标系转换
1,世界坐标系——相机坐标系
相机坐标系和世界坐标系都是3D空间坐标系,任何一个空间中的点,都可以通过旋转
和平移
进行相互转换
假设世界坐标系下有个点 P w ( X w , Y w , Z w ) P_w(X_w,Y_w,Z_w) Pw(Xw,Yw,Zw),通过乘以一个变换矩阵(旋转R+平移T)就可以得到相机坐标系下的对应位置 P c ( X c , Y c , Z c ) P_c(X_c,Y_c,Z_c) Pc(Xc,Yc,Zc)
[ X c Y c Z c ] = [ R 11 R 12 R 13 R 21 R 22 R 23 R 31 R 32 R 33 ] [ X w Y w Z w ] + [ T 1 T 2 T 3 ] \begin{bmatrix} X_c\\ Y_c\\ Z_c \end{bmatrix}= \begin{bmatrix} R_{11}&R_{12}&R_{13}\\ R_{21}&R_{22}&R_{23}\\ R_{31}&R_{32}&R_{33} \end{bmatrix} \begin{bmatrix} X_w\\ Y_w\\ Z_w \end{bmatrix}+ \begin{bmatrix} T_1\\ T_2\\ T_3 \end{bmatrix} XcYcZc = R11R21R31R12R22R32R13R23R33 XwYwZw + T1T2T3
为了后续的计算方便,转换为齐次坐标系进行表示
[ X c Y c Z c 1 ] = [ R 11 R 12 R 13 T 1 R 21 R 22 R 23 T 2 R 31 R 32 R 33 T 3 0 0 0 1 ] [ X w Y w Z w 1 ] \begin{bmatrix} X_c\\ Y_c\\ Z_c\\ 1 \end{bmatrix}= \begin{bmatrix} R_{11}&R_{12}&R_{13}&T_1\\ R_{21}&R_{22}&R_{23}&T_2\\ R_{31}&R_{32}&R_{33}&T_3\\ 0&0&0&1 \end{bmatrix} \begin{bmatrix} X_w\\ Y_w\\ Z_w\\ 1 \end{bmatrix} XcYcZc1 = R11R21R310R12R22R320R13R23R330T1T2T31 XwYwZw1
其中这个变换矩阵(旋转R和平移T)称为相机外参
:
[ R 11 R 12 R 13 T 1 R 21 R 22 R 23 T 2 R 31 R 32 R 33 T 3 0 0 0 1 ] \begin{bmatrix} R_{11}&R_{12}&R_{13}&T_1\\ R_{21}&R_{22}&R_{23}&T_2\\ R_{31}&R_{32}&R_{33}&T_3\\ 0&0&0&1 \end{bmatrix} R11R21R310R12R22R320R13R23R330T1T2T31
相机外参实现了某点所在的世界坐标系
到相机坐标系
之间的转换
2,相机坐标系——图像坐标系
就此我们实现了世界坐标系下点 P w ( X w , Y w , Z w ) P_w(X_w,Y_w,Z_w) Pw(Xw,Yw,Zw)到其所对应的相机的坐标系下位置 P c ( X c , Y c , Z c ) P_c(X_c,Y_c,Z_c) Pc(Xc,Yc,Zc)之间的转换
相机坐标系是3D空间坐标系,而相机拍出来的图片是2D平面,这之间涉及透视投影(perspective projection),大白话为相似三角形
我们可以看到 X c , Y c , Z c , O c X_c,Y_c,Z_c,O_c Xc,Yc,Zc,Oc这个坐标系为相机坐标系,淡蓝色的平面 x , y , o x,y,o x,y,o为图像坐标系(成像平面)
相机成像的原理是小孔成像,故相机坐标系和图像坐标系的y轴是相反的
相机坐标系的原点 O c O_c Oc与图像坐标系的原点 o o o之间的距离为焦距 f f f(这里假设相机坐标系和图像坐标系的轴是相互平行且放置位置为正中心,但也有不平行情况,就需要考虑角度了
)
相机坐标系下的点 P c ( X c , Y c , Z c ) P_c(X_c,Y_c,Z_c) Pc(Xc,Yc,Zc)与相机坐标系原点 O c O_c Oc的连线过图像坐标系平面上的点 p ( x , y ) p(x,y) p(x,y)
也就是相机坐标系下的点 P c ( X c , Y c , Z c ) P_c(X_c,Y_c,Z_c) Pc(Xc,Yc,Zc)对应的图像坐标系下的位置为 p ( x , y ) p(x,y) p(x,y)
根据相似三角形可知:
{ x f = X c Z c y f = Y c Z c ⇒ { Z c ⋅ x = f ⋅ X c Z c ⋅ y = f ⋅ Y c \begin{cases} \frac{x}{f} = \frac{X_c}{Z_c}\\ \frac{y}{f} = \frac{Y_c}{Z_c} \end{cases} \Rightarrow \begin{cases} Z_c·x = f·X_c\\ Z_c·y = f·Y_c \end{cases} {fx=ZcXcfy=ZcYc⇒{Zc⋅x=f⋅XcZc⋅y=f⋅Yc
转化为矩阵形式
Z c [ x y 1 ] = [ f 0 0 0 0 f 0 0 0 0 1 0 ] [ X c Y c Z c 1 ] Z_c \begin{bmatrix} x\\y\\1\end{bmatrix} =\begin{bmatrix} f&0&0&0\\ 0&f&0&0\\ 0&0&1&0 \end{bmatrix} \begin{bmatrix} X_c\\ Y_c\\ Z_c\\ 1 \end{bmatrix} Zc xy1 = f000f0001000 XcYcZc1
其中 Z c Z_c Zc为点所在相机坐标系下的Z轴方向位置,是个常量,又称为比例因子
f f f为相机的焦距
通过该矩阵就可以实现相机坐标系
到图像坐标系
之间的转换
3,图像坐标系——像素坐标系
图像坐标系是物理坐标系,因为它涉及到具体的尺寸大小,每个像素都有其对应的物理尺寸
一般情况下像素是矩形,通常情况下假设 1 p i x e l = d x m m , 1 p i x e l = d y m m 1 pixel = dx mm,1 pixel = dy mm 1pixel=dxmm,1pixel=dymm,其中 d x dx dx和 d y dy dy表示一个像素的长宽分别为多少mm
已知有个小蓝点在图像坐标系
下的位置为 ( x , y ) (x,y) (x,y),图像坐标系原点所在像素坐标系
下的位置为 ( u 0 , v 0 ) (u_0,v_0) (u0,v0)
求解:小蓝点所对应的像素坐标系
为多少?
假设:1个像素的长和宽分别为 d x dx dx和 d y dy dy mm,图像坐标系下1mm对应像素坐标系下为 1 d x \frac{1}{dx} dx1个像素
小蓝点在图像坐标系下 ( x , y ) (x,y) (x,y)应像素坐标为 ( x ∗ 1 d x , y ∗ 1 d y ) (x * \frac{1}{dx} , y * \frac{1}{dy}) (x∗dx1,y∗dy1),即 ( x d x , y d y ) (\frac{x}{dx},\frac{y}{dy}) (dxx,dyy)
u = x d x + u 0 v = y d y + v 0 u = \frac{x}{dx} + u_0\\ v = \frac{y}{dy} + v_0 u=dxx+u0v=dyy+v0
整理成矩阵形式:
[ u v 1 ] = [ 1 d x 0 u 0 0 1 d y v 0 0 0 1 ] [ x y 1 ] \begin{bmatrix} u\\ v\\ 1 \end{bmatrix} = \begin{bmatrix} \frac{1}{dx}&0&u_0\\ 0&\frac{1}{dy}&v_0\\ 0&0&1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} uv1 = dx1000dy10u0v01 xy1
也可以写成另一种形式
[ x y 1 ] = [ d x 0 − u 0 d x 0 d y − v 0 d y 0 0 1 ] [ u v 1 ] \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} = \begin{bmatrix} dx&0&-u_0dx\\ 0&dy&-v_0dy\\ 0&0&1 \end{bmatrix} \begin{bmatrix} u\\ v\\ 1 \end{bmatrix} xy1 = dx000dy0−u0dx−v0dy1 uv1
由此可以得到一个矩阵,实现该点在图像坐标系 ( x , y ) (x,y) (x,y)和像素坐标系 ( u , v ) (u,v) (u,v)下的直接转换
4,各个坐标系转换相互推导结合
我们的最终目的是:世界坐标系
转换到像素坐标系
若已知世界坐标系下点的坐标为 P w ( X w , Y w , Z w ) P_w(X_w,Y_w,Z_w) Pw(Xw,Yw,Zw)
将世界坐标系 P w ( X w , Y w , Z w ) P_w(X_w,Y_w,Z_w) Pw(Xw,Yw,Zw)转换为相机坐标系 P c ( X c , Y c , Z c ) P_c(X_c,Y_c,Z_c) Pc(Xc,Yc,Zc)
[ X c Y c Z c 1 ] = [ R 11 R 12 R 13 T 1 R 21 R 22 R 23 T 2 R 31 R 32 R 33 T 3 0 0 0 1 ] [ X w Y w Z w 1 ] \begin{bmatrix} X_c\\ Y_c\\ Z_c\\ 1 \end{bmatrix}= \begin{bmatrix} R_{11}&R_{12}&R_{13}&T_1\\ R_{21}&R_{22}&R_{23}&T_2\\ R_{31}&R_{32}&R_{33}&T_3\\ 0&0&0&1 \end{bmatrix} \begin{bmatrix} X_w\\ Y_w\\ Z_w\\ 1 \end{bmatrix} XcYcZc1 = R11R21R310R12R22R320R13R23R330T1T2T31 XwYwZw1
将相机坐标系 P c ( X c , Y c , Z c ) P_c(X_c,Y_c,Z_c) Pc(Xc,Yc,Zc)转化为图像坐标系 p ( x , y ) p(x,y) p(x,y)
Z c [ x y 1 ] = [ f 0 0 0 0 f 0 0 0 0 1 0 ] [ X c Y c Z c 1 ] Z_c \begin{bmatrix} x\\y\\1\end{bmatrix} =\begin{bmatrix} f&0&0&0\\ 0&f&0&0\\ 0&0&1&0 \end{bmatrix} \begin{bmatrix} X_c\\ Y_c\\ Z_c\\ 1 \end{bmatrix} Zc xy1 = f000f0001000 XcYcZc1
将图像坐标系 ( x , y ) (x,y) (x,y)转化为像素坐标系 ( u , v ) (u,v) (u,v),这里的 ( u 0 , v 0 ) (u_0,v_0) (u0,v0)是图像坐标系的原点所对应的像素坐标系下的位置
[ u v 1 ] = [ 1 d x 0 u 0 0 1 d y v 0 0 0 1 ] [ x y 1 ] \begin{bmatrix} u\\ v\\ 1 \end{bmatrix} = \begin{bmatrix} \frac{1}{dx}&0&u_0\\ 0&\frac{1}{dy}&v_0\\ 0&0&1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} uv1 = dx1000dy10u0v01 xy1
最终进行前后整理可得:
Z c [ u v 1 ] = [ 1 d x 0 u 0 0 1 d y v 0 0 0 1 ] [ f 0 0 0 0 f 0 0 0 0 1 0 ] [ R 11 R 12 R 13 T 1 R 21 R 22 R 23 T 2 R 31 R 32 R 33 T 3 0 0 0 1 ] [ X w Y w Z w 1 ] Z_c \begin{bmatrix} u\\ v\\ 1 \end{bmatrix} = \begin{bmatrix} \frac{1}{dx}&0&u_0\\ 0&\frac{1}{dy}&v_0\\ 0&0&1 \end{bmatrix} \begin{bmatrix} f&0&0&0\\ 0&f&0&0\\ 0&0&1&0 \end{bmatrix} \begin{bmatrix} R_{11}&R_{12}&R_{13}&T_1\\ R_{21}&R_{22}&R_{23}&T_2\\ R_{31}&R_{32}&R_{33}&T_3\\ 0&0&0&1 \end{bmatrix} \begin{bmatrix} X_w\\ Y_w\\ Z_w\\ 1 \end{bmatrix} Zc uv1 = dx1000dy10u0v01 f000f0001000 R11R21R310R12R22R320R13R23R330T1T2T31 XwYwZw1
其中 Z c Z_c Zc表示该点在相机坐标系下的Z轴方向的位置,又称为比例因子,本质是常量
相机内参为:
[ 1 d x 0 u 0 0 1 d y v 0 0 0 1 ] [ f 0 0 0 0 f 0 0 0 0 1 0 ] \begin{bmatrix} \frac{1}{dx}&0&u_0\\ 0&\frac{1}{dy}&v_0\\ 0&0&1 \end{bmatrix} \begin{bmatrix} f&0&0&0\\ 0&f&0&0\\ 0&0&1&0 \end{bmatrix} dx1000dy10u0v01 f000f0001000
相机外参为:
[ R 11 R 12 R 13 T 1 R 21 R 22 R 23 T 2 R 31 R 32 R 33 T 3 0 0 0 1 ] \begin{bmatrix} R_{11}&R_{12}&R_{13}&T_1\\ R_{21}&R_{22}&R_{23}&T_2\\ R_{31}&R_{32}&R_{33}&T_3\\ 0&0&0&1 \end{bmatrix} R11R21R310R12R22R320R13R23R330T1T2T31
就此我们实现了世界坐标系和像素坐标系的转换,这就是相机标定的意义所在
5,总结
理想状态下的相机标定,其本质是求解相机的内外参数矩阵
相机外参矩阵需要求解旋转和平移共6个参数
相机内参菊展需要求解焦距 f f f、图像坐标系原点所在的像素坐标系的坐标 ( u 0 , v 0 ) (u_0,v_0) (u0,v0)也称为像主点坐标、单个像素点的长和宽 d x dx dx和 d y dy dy mm,共5个参数
相机内外参数矩阵需要求解11
个参数,这是不考虑畸变的理想状况,但实际相机都不可避免存在畸变,故还需要求解畸变系数
三、畸变
相机标定的最终目的是拿到相机的内外参数矩阵,这些内外参数针对同一个相机是固定的,只需要标定一次即可
相机硬件本身多多少少不可避免存在一定的误差,故需要求解畸变系数用于相机的校准,然后再进行求解内外参矩阵
畸变主要包括(影响最大):切向畸变
和径向畸变
,是相机本身无法避免的误差
1,切向畸变
切向畸变产生于相机组装过程中,透镜本身与相机传感器成像平面不平行
2,径向畸变
径向畸变产生于透镜本身的形状,光线在远离透镜中心的地方比靠近中心的地方更加弯曲
径向畸变主要包括:桶形畸变
和枕形畸变
切向畸变和径向畸变有对应的模型公式,网上一大堆教程,需要的小伙伴自行学习推导哈
畸变涉及到五个参数:径向畸变参数 k 1 、 k 2 、 k 3 k_1、k_2、k_3 k1、k2、k3;切向畸变参数 p 1 、 p 2 p_1、p_2 p1、p2
四、OpenCV代码实战
求解方法很多,这里以张正友标定法(也称为棋盘格标定法)为例进行演示
1,准备棋盘格数据
①OpenCV自带几张棋盘格图片,大致路径为:opencv\sources\samples\data
,当然也可以自己去拍几张棋盘格
把这几张图片放到VS项目中
②新建一个项目,需要用到OpenCV
③跑一下代码即可
2,完整代码
修改地方:
①棋盘格角点行列数:int CHECKERBOARD[2]{ 6,9 };
②图片所在文件夹路径:std::string path = "./image/*.jpg";
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <iostream>using namespace std;
using namespace cv;// Defining the dimensions of checkerboard
// 定义棋盘格的尺寸
int CHECKERBOARD[2]{ 6,9 }; // 一行有6个,一共有9行 数点的行列---6行9列int main()
{// Creating vector to store vectors of 3D points for each checkerboard image// 创建矢量以存储每个棋盘图像的三维点矢量std::vector<std::vector<cv::Point3f> > objpoints;// Creating vector to store vectors of 2D points for each checkerboard image// 创建矢量以存储每个棋盘图像的二维点矢量std::vector<std::vector<cv::Point2f> > imgpoints;// Defining the world coordinates for 3D points// 为三维点定义世界坐标系std::vector<cv::Point3f> objp;for (int i{ 0 }; i < CHECKERBOARD[1]; i++){for (int j{ 0 }; j < CHECKERBOARD[0]; j++){objp.push_back(cv::Point3f(j, i, 0));}}// Extracting path of individual image stored in a given directory// 提取存储在给定目录中的单个图像的路径std::vector<cv::String> images;// Path of the folder containing checkerboard images// 包含棋盘图像的文件夹的路径std::string path = "./image/*.jpg";// 使用glob函数读取所有图像的路径cv::glob(path, images);cv::Mat frame, gray;// vector to store the pixel coordinates of detected checker board corners// 存储检测到的棋盘转角像素坐标的矢量std::vector<cv::Point2f> corner_pts;bool success;// Looping over all the images in the directory// 循环读取图像for (int i{ 0 }; i < images.size(); i++){frame = cv::imread(images[i]);if (frame.empty()){continue;}if (i == 40){int b = 1;}cout << "the current image is " << i << "th" << endl;cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);// Finding checker board corners// 寻找角点// If desired number of corners are found in the image then success = true// 如果在图像中找到所需数量的角,则success = true// opencv4以下版本,flag参数为CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGEsuccess = cv::findChessboardCorners(gray, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_pts, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_FAST_CHECK | CALIB_CB_NORMALIZE_IMAGE);/** If desired number of corner are detected,* we refine the pixel coordinates and display* them on the images of checker board*/// 如果检测到所需数量的角点,我们将细化像素坐标并将其显示在棋盘图像上if (success){// 如果是OpenCV4以下版本,第一个参数为CV_TERMCRIT_EPS | CV_TERMCRIT_ITERcv::TermCriteria criteria(TermCriteria::EPS | TermCriteria::Type::MAX_ITER, 30, 0.001);// refining pixel coordinates for given 2d points.// 为给定的二维点细化像素坐标cv::cornerSubPix(gray, corner_pts, cv::Size(11, 11), cv::Size(-1, -1), criteria);// Displaying the detected corner points on the checker board// 在棋盘上显示检测到的角点cv::drawChessboardCorners(frame, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_pts, success);objpoints.push_back(objp);imgpoints.push_back(corner_pts);}cv::imshow("Image", frame);cv::waitKey(0);}cv::destroyAllWindows();cv::Mat cameraMatrix, distCoeffs, R, T;/** Performing camera calibration by* passing the value of known 3D points (objpoints)* and corresponding pixel coordinates of the* detected corners (imgpoints)*/// 通过传递已知3D点(objpoints)的值和检测到的角点(imgpoints)的相应像素坐标来执行相机校准cv::calibrateCamera(objpoints, imgpoints, cv::Size(gray.rows, gray.cols), cameraMatrix, distCoeffs, R, T);// 内参矩阵std::cout << "cameraMatrix : " << std::endl;std::cout << cameraMatrix << std::endl;// 透镜畸变系数std::cout << "distCoeffs : " << std::endl;std::cout << distCoeffs << std::endl;// rvecsstd::cout << "Rotation vector : " << std::endl;std::cout << R << std::endl;// tvecsstd::cout << "Translation vector : " << std::endl;std::cout << T << std::endl;return 0;
}
3,运行效果
求解得到内参矩阵
、透镜畸变系数
、旋转和平移向量
相关文章:
(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)
一、四大坐标系介绍 1,世界坐标系 从这个世界(world)的视角来看物体 世界坐标系是3D空间坐标,每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)表示 2,相机坐标系 相机本身具有一个坐标系&…...
Bootstrap 下拉菜单
Bootstrap 下拉菜单 Bootstrap 是一个流行的前端框架,它提供了许多预构建的组件,其中之一就是下拉菜单。下拉菜单是一个交互式元素,允许用户从一系列选项中选择一个。在本篇文章中,我们将详细介绍如何在 Bootstrap 中创建和使用下…...
WinHttp API接口辅助类实现GET POST网络通讯
1、简述 近期需要在MFC基础上开发网络Http通讯,开始使用的WinINet进行通讯,后面发现WinINet对连接超时这块不支持设置,在网上搜索了几种方式效果都不太好,于是决定用WinHttp API接口进行通讯,分别对GET、POST进行了封装。 2、使用到接口 2.1、WinHttpOpen WinHttpOpen 是…...
Elasticsearch实战应用
嘿,小伙伴们,今天咱们来唠唠Elasticsearch,这可是个超厉害的搜索引擎,能帮你在海量数据里快速找到想要的东西,就像给你的数据装上了“放大镜”。 一、啥是Elasticsearch 简单来说,Elasticsearch就是一个基…...
MySQL存储过程
存储过程: 事先经过编译并存储在数据库中的一段sql语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的,思想上就是sql语言层面的代码封装与重用 …...
安路FPGA开发工具TD:问题解决办法 及 Tips 总结
安路科技(Anlogic)是一家专注于高性能、低功耗可编程逻辑器件(FPGA)设计和生产的公司。其提供的开发工具TD(TangDynasty)是专门为安路FPGA系列产品设计的集成开发环境(IDE)。以下是对…...
高精度阶乘C++实现
高精度计算,实际上就是模拟竖式计算,代码如下,请慢慢消化,如有不足或建议,请在评论区留言 这个阶乘操作实际上就是高精度乘法的运用,可以非常容易的在考场上写出来 #include <bits/stdc.h> using na…...
PageHelper快速使用
依赖 <!--分页插件PageHelper--> <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.7</version> </dependency>示例 /** * 封装分页结果…...
“AI 辅助决策系统:决策路上的智慧领航员
在当今瞬息万变的时代,无论是企业的运营管理,还是个人在生活中的重大抉择,都需要精准、高效的决策。然而,信息的繁杂和未来的不确定性,常常让决策变得困难重重。这时,AI 辅助决策系统宛如一位智慧的领航员&…...
[Linux] linux 系统中如何添加自动启动程序
背景:在嵌入式系统中,需要开机自动启动所编写的程序【可执行文件】。 解决方法:原理就是Linux开机会自动执行一些文件。在/etc/profile中添加执行程序的脚本。/etc/profile 是一个系统级的配置文件,在用户登录Linux系统时自动执行…...
Linux之网络套接字
Linux之网络套接字 一.IP地址和端口号二.TCP和UDP协议2.1网络字节序 三.socket编程的常见API四.模拟实现UDP服务器和客户端五.模拟实现TCP服务器和客户端 一.IP地址和端口号 在了解了网络相关的基础知识之后我们知道了数据在计算机中传输的流程并且发现IP地址在其中占据了确定…...
LeetCode 2266.统计打字方案数:排列组合
【LetMeFly】2266.统计打字方案数:排列组合 力扣题目链接:https://leetcode.cn/problems/count-number-of-texts/ Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。 为了 打出 一个字母,Alice 需要 按 对应字母 i 次,…...
Jmeter 动态参数压力测试时间段预定接口
🎯 本文档详细介绍了如何使用Apache JMeter进行压力测试,以评估预定接口在高并发场景下的性能表现。通过创建线程组模拟不同数量的用户并发请求,利用CSV文件动态配置时间段ID和用户token,确保了测试数据的真实性和有效性。文档中还…...
Learning Prompt
说明:这是我的学习笔记,很多内容转自网络,请查阅文章末尾的参考资料。 目录 基本要求(C.R.E.A.T.E)总结文章(Summarise)改写文章(Rewrite)根据参考资料回答问题(Question & Answer)参考资料 基本要求(C.R.E.A.T.E) Character This is th…...
微信消息群发(定时群发)-UI自动化产品(基于.Net平台+C#)
整理 | 小耕家的喵大仙 出品 | CSDN(ID:lichao19897314) 关联源码及工具下载https://download.csdn.net/download/lichao19897314/90096681https://download.csdn.net/download/lichao19897314/90096681https://download.csdn.net/download/…...
华为HuaweiCloudStack(一)介绍与架构
本文简单介绍了华为HCS私有云解决方案,并从下至上介绍HCS的整体架构,部署架构、部署方式等内容。 目录 HCS简介 HCS架构 纵向结构 ?管理平台类型 HCS节点类型 FusionSphere OpenStack CPS ServiceOM SC 运营面 OC 运维面 HCS部署架构 regi…...
【博客之星】2024年度个人成长、强化学习算法领域总结
📢在2025年初,非常荣幸能通过审核进入到《2024年度CSDN博客之星总评选》TOP300的年度评选中,排名40。这还是第一次来到这个阶段,作为一名博士研究生,还是备受鼓舞的。在这里我将以回顾的方式讲述一下这一年在CSDN中走过…...
Git 分支策略
文章目录 1. Git Flow2. GitHub Flow3. GitLab Flow4. Trunk-Based Development5. Release Flow分支最佳实践 Git 分支策略是组织和管理工作特性开发、协作和版本控制的技术。选择合适的策略取决于团队规模、项目需求和部署需求。以下是常见的 Git 分支策略: 1. Git…...
《自动驾驶与机器人中的SLAM技术》ch8:基于预积分和图优化的紧耦合 LIO 系统
和组合导航一样,也可以通过预积分 IMU 因子加上雷达残差来实现基于预积分和图优化的紧耦合 LIO 系统。一些现代的 Lidar SLAM 系统也采用了这种方式。相比滤波器方法来说,预积分因子可以更方便地整合到现有的优化框架中,从开发到实现都更为便…...
Mysql学习笔记
连接数据库 找到 MySQL 安装目录下的 bin 目录,然后打开命令窗口,在命令窗口中按如下语法输入命令: mysql - h MySQL 数据库服务器的 IP 地址 - u 用户名 - p 然后按下回车键,输入密码即可 数据库操作 创建数据库 CREAT…...
Safari常用快捷键
一、书签边栏 1、显示或隐藏书签边栏:Control-Command-1 2、选择下一个书签或文件夹:向上头键或向下头键 3、打开所选书签:空格键 4、打开所选文件夹:空格键或右箭头键 5、关闭所选文件夹:空格键或左箭头键 6、更…...
OpenEuler学习笔记(二):用通俗的道理讲操作系统原理
用通俗的道理讲操作系统原理 基础概念类比 把OpenEuler操作系统想象成一个大型的工厂,这个工厂有各种各样的部门,每个部门都有自己的职责,共同协作来让整个工厂正常运转。内核就像是工厂的管理中心,它负责指挥和协调所有的工作。 …...
ros2-7.5 做一个自动巡检机器人
7.5.1 需求及设计 又到了小鱼老师带着做最佳实践项目了。需求:做一个在各个房间不断巡逻并记录图像的机器人。 到达目标点后首先通过语音播放到达目标点信息, 再通过摄像头拍摄一张图片保存到本地。 7.5.2 编写巡检控制节点 在chapt7_ws/src下新建功…...
使用 `scanpy` 观察 `AnnData` 对象内部数据结构
以下是使用 scanpy 观察 AnnData 对象内部数据结构的步骤: 一、导入必要的库: import scanpy as sc二、读取 AnnData 对象: 假设你的 AnnData 对象存储在一个文件中,例如 adata.h5ad,你可以使用以下代码读取它: adata = sc.read(adata.h5ad)如果你已经有了 adata 对象…...
《CPython Internals》阅读笔记:p232-p249
《CPython Internals》学习第 13天,p232-p249 总结,总计 18 页。 一、技术总结 无。 二、英语总结(生词:1) 1.overhead (1)overhead: over-(“above”) head(“top part, uppermost section”) overhead的字面意思是:above…...
Java并发08 - 并发安全容器详解
并发容器详解 文章目录 并发容器详解一:不使用并发容器如何保证安全二:阻塞队列容器2:ArrayBlockingQueue2.1:内部成员2.2:put方法的实现2.3:take方法的实现 3:LinkedBlockingQueue3.1ÿ…...
抽奖系统(3——奖品模块)
1. 图片上传 application.properties 配置上传文件路径 ## 文件上传 ## # 目标路径 pic.local-pathD:/PIC # spring boot3 升级配置名 spring.web.resources.static-locationsclasspath:/static/,file:${pic.local-path} tip: 1. 如果访问的是本地路径,…...
36.centos7上安装python3.6.5、安装卸载依赖包
查看openssl的版本号,默认python3.6.5需要OpenSSL 1.0.2以上的版本支持。 监测安装好的python,是否可以正确导入ssl和_ssl包 pip3安装依赖包 通过Pycharm工具导出requirements.txt文件 查看/usr/bin/目录下的软连接 pip3, python...
微透镜阵列精准全检,白光干涉3D自动量测方案提效70%
广泛应用的微透镜阵列 微透镜是一种常见的微光学元件,通过设计微透镜,可对入射光进行扩散、光束整形、光线均分、光学聚焦、集成成像等调制,进而实现许多传统光学元器件难以实现的特殊功能。 微透镜阵列(Microlens Array&#x…...
nature genetics | scATAC-seq预测scRNA-seq,识别影响基因表达的新染色质区域
–https://doi.org/10.1038/s41588-024-01689-8 Single-cell multi-ome regression models identify functional and disease-associated enhancers and enable chromatin potential analysis 研究团队和单位 Christina S. Leslie–Memorial Sloan Kettering Cancer Center …...
简述mysql 主从复制原理及其工作过程,配置一主两从并验证。
MySQL 主从同步是一种数据库复制技术,它通过将主服务器上的数据更改复制到一个或多个从服务器,实现数据的自动同步。 主从同步的核心原理是将主服务器上的二进制日志复制到从服务器,并在从服务器上执行这些日志中的操作。 MySQL主从同步是基…...
Java API:封装自定义响应类
本文介绍 Web 服务开发中自定义响应,涵盖标准 HTTP 响应状态码局限性、自定义响应价值、设计原则与实现、在 Spring Boot 项目应用、与其他响应格式对比总结及应用场景。 1. 标准HTTP响应与自定义响应 1.1标准HTTP响应状态码 在 Web 服务开发中,HTTP…...
【Unity3D】利用Hinge Joint 2D组件制作绳索效果
目录 一、动态绳索 (可移动根节点) 二、静态绳索 三、利用Skinning Editor(Unity2022.3.15f1正常使用) 四、注意事项 一、动态绳索 (可移动根节点) 动态绳索 DynamicRope空物体 Anchor和whitecircle是相同位置的物体ÿ…...
vim练级攻略(精简版)
vim推荐配置: curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh 0. 规定 Ctrl-λ 等价于 <C-λ> :command 等价于 :command <回车> n 等价于 数字 blank字符 等价于 空格,tab&am…...
嵌入式硬件篇---PID控制
文章目录 前言第一部分:连续PID1.比例(Proportional,P)控制2.积分(Integral,I)控制3.微分(Derivative,D)控制4.PID的工作原理5..实质6.分析7.各种PID控制器P控…...
技术洞察:C++在后端开发中的前沿趋势与社会影响
文章目录 引言C在后端开发中的前沿趋势1. 高性能计算的需求2. 微服务架构的兴起3. 跨平台开发的便利性 跨领域技术融合与创新实践1. C与人工智能的结合2. C与区块链技术的融合 C对社会与人文的影响1. 提升生产力与创新能力2. 促进技术教育与人才培养3. 技术与人文的深度融合 结…...
C语言程序设计之小系统
🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 目录 系统说明 1.1 系统概述 1.2 功能模块总体设计详细设计 3.1 程序中使用的函数 3.2各类问…...
pyinstaller : 无法将“pyinstaller”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
pyinstaller : 无法将“pyinstaller”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1pyinstaller --onefile --windowed 过年烟花.py~~~~~~~~~~~ …...
接口传参 data格式和json格式区别是什么
接口传参 data格式和json格式区别是什么 以下是接口传参 data 格式和 JSON 格式的区别: 定义和范围 Data 格式: 是一个较为宽泛的概念,它可以指代接口传递参数时所使用的任何数据的组织形式。包括但不限于 JSON、XML、Form 数据、纯文本、二进…...
ClickHouse 入门
简介 ClickHouse 是一个列式数据库,传统的数据库一般是按行存储,而ClickHouse则是按列存储,每一列都有自己的存储空间,并且只存储该列的数值,而不是存储整行的数据。这样做主要有几个好处,压缩率高&#x…...
Python自动化:基于faker批量生成模拟数据(以电商行业销售数据为例)
引言:个人认为,“造数据”是一个数据分析师的一项基本技能,当然啦,“造数据”不是说胡编乱造,而是根据自己的需求去构造一些模拟数据集,用于测试等用途,而且使用虚拟数据不用担心数据隐私和安全…...
3.3 OpenAI GPT-4, GPT-3.5, GPT-3 模型调用:开发者指南
OpenAI GPT-4, GPT-3.5, GPT-3 模型调用:开发者指南 OpenAI 的 GPT 系列语言模型,包括 GPT-4、GPT-3.5 和 GPT-3,已经成为自然语言处理领域的标杆。无论是文本生成、对话系统,还是自动化任务,开发者都可以通过 API 调用这些强大的模型来增强他们的应用。本文将为您详细介…...
【Spring Boot】掌握 Spring 事务:隔离级别与传播机制解读与应用
前言 🌟🌟本期讲解关于spring 事务传播机制介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废话…...
力扣203题—— 移除链表元素
题目 递归法使用 if(headnull){return null; }//假设remove返回后面已经去掉val值的链表 我们用head.next去存放他,接着我们要判断此时head head值是否等于val,如果等于我们就返回后继元素即可 head.nextremove(head.next,val); if(head.valval){return…...
Express中间件
目录 Express中间件 中间件的概念 next函数 全局中间与局部中间件 多个中间件 中间的5个注意事项 中间的分类 应用级中间件 路由级中间件 错误级中间件 Express内置中间件 express.json express.urlencoded 第三方中间件编辑 自定义中间件 Express中间件 中间…...
【AIGC】SYNCAMMASTER:多视角多像机的视频生成
标题:SYNCAMMASTER: SYNCHRONIZING MULTI-CAMERA VIDEO GENERATION FROM DIVERSE VIEWPOINTS 主页:https://jianhongbai.github.io/SynCamMaster/ 代码:https://github.com/KwaiVGI/SynCamMaster 文章目录 摘要一、引言二、使用步骤2.1 TextT…...
模块化架构与微服务架构,哪种更适合桌面软件开发?
前言 在现代软件开发中,架构设计扮演着至关重要的角色。两种常见的架构设计方法是模块化架构与微服务架构。它们各自有独特的优势和适用场景,尤其在C#桌面软件开发领域,模块化架构往往更加具有实践性。本文将对这两种架构进行对比࿰…...
Ubuntu 24.04 LTS 安装 tailscale 并访问 SMB共享文件夹
Ubuntu 24.04 LTS 安装 tailscale 安装 Tailscale 官方仓库 首先,确保系统包列表是最新的: sudo apt update接下来,安装 Tailscale 所需的仓库和密钥: curl -fsSL https://tailscale.com/install.sh | sh这会自动下载并安装 …...
fgets、scanf存字符串应用
题目1 夺旗(英语:Capture the flag,简称 CTF)在计算机安全中是一种活动,当中会将“旗子”秘密地埋藏于有目的的易受攻击的程序或网站。参赛者从其他参赛者或主办方偷去旗子。 非常崇拜探姬的小学妹最近迷上了 CTF&am…...
C#高级:用Csharp操作鼠标和键盘
一、winform 1.实时获取鼠标位置 public Form1() {InitializeComponent();InitialTime(); }private void InitialTime() {// 初始化 Timer 控件var timer new System.Windows.Forms.Timer();timer.Interval 100; // 设置为 100 毫秒,即每 0.1 秒更新一次timer.…...