(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及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{Zcx=fXcZcy=fYc

转化为矩阵形式
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=dxmm1pixel=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}) (xdx1,ydy1),即 ( 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 = dx000dy0u0dxv0dy1 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 k1k2k3;切向畸变参数 p 1 、 p 2 p_1、p_2 p1p2

四、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,运行效果

在这里插入图片描述
在这里插入图片描述
求解得到内参矩阵透镜畸变系数旋转和平移向量

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从CRUD到高级功能:EF Core在.NET Core中全面应用(三)

目录 IQueryable使用 原生SQL使用 实体状态跟踪 全局查询筛选器 并发控制使用 IQueryable使用 在EFCore中IQueryable是一个接口用于表示可查询的集合&#xff0c;它继承自IEnumerable但具有一些关键的区别&#xff0c;使得它在处理数据库查询时非常有用&#xff0c;普通集…

STM32之CubeMX图形化工具开发介绍(十七)

STM32F407 系列文章 - STM32CubeMX&#xff08;十七&#xff09; 目录 前言 一、CubeMX 二、下载安装 1.下载 2.安装 3.图解步骤 三、用户界面 1.项目配置 2.项目生成 3.项目文件解释 4.新建工程 5.查看原工程 四、FAQ 总结 前言 STMCube源自意法半导体&#xf…

idea中远程调试中配置的参数说明

Ⅰ 远程调试中配置的端口号与服务本身端口号区别 一、远程调试中配置端口号的作用 在 IDEA 中进行远程调试时配置的端口号主要用于建立开发工具&#xff08;如 IDEA&#xff09;和远程服务之间的调试连接。当你启动远程调试时&#xff0c;IDEA 会监听这个配置的端口号&#xf…

gitlab使用多数据库

1. 说明 默认情况下&#xff0c;GitLab 使用一个单一的应用数据库&#xff0c;称为主数据库。为了扩展 GitLab&#xff0c;您可以将 GitLab 配置为使用多个应用数据库。 设置多个数据库后&#xff0c;GitLab 将使用第二个应用数据库用于 CI/CD 功能&#xff0c;称为 CI 数据库…

【博客之星2024】技术创作与成长的全景回顾与突破 —— “千里之行,始于足下“

《热爱生命》 汪国真 我不去想是否能够成功 既然选择了远方 便只顾风雨兼程 我不去想能否赢得爱情 既然钟情于玫瑰 就勇敢地吐露真诚 我不去想身后会不会袭来寒风冷雨 既然目标是地平线 留给世界的只能是背影 我不去想未来是平坦还是泥泞 只要热爱生命 一切&#xff0c;都在意料…

leetcode刷题记录(七十二)——146. LRU 缓存

&#xff08;一&#xff09;问题描述 146. LRU 缓存 - 力扣&#xff08;LeetCode&#xff09;146. LRU 缓存 - 请你设计并实现一个满足 LRU (最近最少使用) 缓存 [https://baike.baidu.com/item/LRU] 约束的数据结构。实现 LRUCache 类&#xff1a; * LRUCache(int capacity)…

两份PDF文档,如何比对差异,快速定位不同之处?

PDF文档比对是通过专门的工具或软件&#xff0c;自动检测两个PDF文件之间的差异&#xff0c;并以可视化的方式展示出来。这些差异可能包括文本内容的修改、图像的变化、表格数据的调整、格式的改变等。比对工具通常会标记出新增、删除或修改的部分&#xff0c;帮助用户快速定位…

TongESB7.1.0.0如何使用dockercompose运行镜像(by lqw)

文章目录 安装准备安装 安装准备 1.安装好docker和dockercompose&#xff1a; docker、docker-compose安装教程&#xff0c;很详细 2.上传好安装相关文件 安装 使用以下命令导入管理端镜像和运行时镜像 docker load -i tongesb_manage_7100.tar docker load -i tongesb_se…

Java基于SSM框架的社区团购系统小程序设计与实现(附源码,文档,部署)

Java基于SSM框架的社区团购系统小程序设计与实现 博主介绍&#xff1a;✌程序猿徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f4…

【Linux】gawk编辑器二

一、变量 gawk编程语言支持两种变量&#xff1a;内建变量和自定义变量。 1、内建变量 gawk使用内建变量来引用一些特殊的功能。 字段和记录分隔符变量 数据字段变量 此变量允许使用美元符号&#xff08;$&#xff09;和字段在记录中的位置值来引用对应的字段。要引用记录…

【Linux】Linux入门(三)权限

目录 前提权限概念whoami指令 Linux权限管理文件访问者的分类&#xff08;人&#xff09;file指令权限信息权限的表示方法 chmod指令 更改权限chown指令 修改文件&#xff0c;文件夹所属用户和用户组 权限掩码umask&#xff08;权限掩码&#xff09; 粘滞位 前提 请先看下面这…

Low-Level 大一统:如何使用Diffusion Models完成视频超分、去雨、去雾、降噪等所有Low-Level 任务?

Diffusion Models专栏文章汇总:入门与实战 前言:视频在传输过程中常常因为各种因素(如恶劣天气、噪声、压缩和传感器分辨率限制)而出现质量下降,这会严重影响计算机视觉任务(如目标检测和视频监控)的性能。现有的视频修复方法虽然取得了一些进展,但通常只能针对特定的退…

生产环境中常用的设计模式

生产环境中常用的设计模式 设计模式目的使用场景示例单例模式保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点- 日志记录器- 配置管理器工厂方法模式定义一个创建对象的接口&#xff0c;让子类决定实例化哪个类- 各种工厂类&#xff08;如视频游戏工厂模式创…

点云目标检测训练数据预处理---平面拟合与坐标转换(python实现)

在做centerpoint训练之前&#xff0c;需要先对点云数据进行标注&#xff0c;然后制作kittti数据集。不用nuScenes或者waymo数据集的理由也很简单&#xff0c;因为麻烦&#xff0c;没有kitti数据集直观。 kitti数据集的格式如下&#xff0c;可以看到数据集中只有航向角&#xff…

一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用

一文大白话讲清楚webpack基本使用——2——css相关loader的配置和使用 1. 建议按文章顺序从头看是看 第一篇&#xff1a;一文大白话讲清楚啥是个webpack第二篇&#xff1a;一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建然后看本篇&#xff0c;Loader的配置…

Python基于OpenCV和PyQt5的人脸识别上课签到系统【附源码】

博主介绍&#xff1a;✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…

2024年第十五届蓝桥杯青少组国赛(c++)真题—快速分解质因数

快速分解质因数 完整题目和在线测评可点击下方链接前往&#xff1a; 快速分解质因数_C_少儿编程题库学习中心-嗨信奥https://www.hixinao.com/tiku/cpp/show-3781.htmlhttps://www.hixinao.com/tiku/cpp/show-3781.html 若如其他赛事真题可自行前往题库中心查找&#xff0c;题…

使用Edge打开visio文件

使用Edge打开visio文件 打开Edge浏览器搜索‘vsdx edge’ 打开第一个搜索结果 Microsoft Support 根据上述打开的页面进行操作 第一步&#xff1a;安装Visio Viewer 第二步&#xff1a;添加注册表 桌面新增文本文件&#xff0c;将下面的内容放入新建文本中&#xff0c;修…

AT8870单通道直流电机驱动芯片

AT8870单通道直流电机驱动芯片 典型应用原理图 描述 AT8870是一款刷式直流电机驱动器&#xff0c;适用于打印机、电器、工业设备以及其他小型机器。两个逻辑输入控制H桥驱动器&#xff0c;该驱动器由四个N-MOS组成&#xff0c;能够以高达3.6A的峰值电流双向控制电机。利用电流…

基础入门-传输加密数据格式编码算法密文存储代码混淆逆向保护安全影响

知识点&#xff1a; 1、传输格式&传输数据-类型&编码&算法 2、密码存储&代码混淆-不可逆&非对称性 一、演示案例-传输格式&传输数据-类型&编码&算法 传输格式 JSON XML WebSockets HTML 二进制 自定义 WebSockets&#xff1a;聊天交互较常…