(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及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.mzph.cn/bicheng/68635.shtml

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

相关文章

openwrt下oaf插件编译安装,实现上网行为监控

文章目录 入门级APP青少年模式设备屏幕使用时间电脑浏览器使用时间限制Surpal 介绍安装使用进阶级专业级旁路由方案openwrt路由器固件编译OAF(Open App Filter)安装编译带有oaf的固件固件烧写设备上电启动应用特征库设置黑白名单及应用访问限制骨灰级ref守护孩子视力,用科技“…

目标检测新视野 | YOLO、SSD与Faster R-CNN三大目标检测模型深度对比分析

目录 引言 YOLO系列 网络结构 多尺度检测 损失函数 关键特性 SSD 锚框设计 损失函数 关键特性 Faster R-CNN 区域建议网络&#xff08;RPN&#xff09; 两阶段检测器 损失函数 差异分析 共同特点 基于深度学习 目标框预测 损失函数优化 支持多类别检测 应…

Linux之网络套接字

Linux之网络套接字 一.IP地址和端口号二.TCP和UDP协议2.1网络字节序 三.socket编程的常见API四.模拟实现UDP服务器和客户端五.模拟实现TCP服务器和客户端 一.IP地址和端口号 在了解了网络相关的基础知识之后我们知道了数据在计算机中传输的流程并且发现IP地址在其中占据了确定…

Mysql常见问题处理集锦

Mysql常见问题处理集锦 root用户密码忘记&#xff0c;重置的操作(windows上的操作)MySQL报错&#xff1a;ERROR 1118 (42000): Row size too large. 或者 Row size too large (&#xff1e; 8126).场景&#xff1a;报错原因解决办法 详解行大小限制示例&#xff1a;内容来源于网…

ReactiveSwift 简单使用

记录 ReactiveSwift 简单使用 导入 ReactiveSwift 库创建 TestViewModel 文件 enum JKTypeType: Int {case cloudcase devicecase weater }// 通过监听属性变化 class TestViewModel: NSObject {lazy var recordType: Property<JKTypeType> {return Property(recordTy…

分类问题(二元,多元逻辑回归,费歇尔判别分析)spss实操

分类模型&#xff1a; 二分类和多分类&#xff1a; 对于二分类模型 &#xff0c;我们将介绍逻辑回归和Fisher线性判别分析两种分类算法; 对于多分类模型&#xff0c;我们将简单介绍Spss中的多分类线性判别分析和多分类逻辑回归的操作步骤 二分类: 基于广义线性模型&#x…

Ubuntu/centOS 如何安装 OpenGL

OpenGL安装与入门教程 什么是OpenGL? OpenGL是一个图形渲染API&#xff0c;它具有操作系统独立、窗口系统独立的特点&#xff0c;能够生成由几何图元和图像基元组成的高质量彩色图像。 OpenGL APIs可以使用以下几个库: Gl OpenGL API实现 (http://www.opengl.org)Glu Open…

在 Vue 3 项目中集成和使用 vue3-video-play

前言 随着视频内容的普及&#xff0c;视频播放功能在现代 Web 应用中变得越来越重要。如果你正在开发一个 Vue 3 项目&#xff0c;并且需要快速集成视频播放功能&#xff0c;vue3-video-play 是一个轻量级且易于使用的 Vue 3 组件。本文将介绍如何在 Vue 3 项目中使用 vue3-vi…

合并两个有序数组(88)合并两个有序链表(21)

88. 合并两个有序数组 - 力扣&#xff08;LeetCode&#xff09; 21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff08;88&#xff09;&#xff1a; class Solution { public:void merge(vector<int>& nums1, int m, vector<int>&…

NPC与AI深度融合结合雷鸟X3Pro AR智能眼镜:引领游戏行业沉浸式与增强现实新纪元的畅想

if… NPC&#xff08;非玩家角色&#xff09;与AI&#xff08;人工智能&#xff09;的深度融合&#xff0c;正引领游戏行业迈向一个全新的沉浸式与增强现实&#xff08;AR&#xff09;相结合的新时代。这一创新不仅预示着游戏体验的质变&#xff0c;更可能全面革新游戏设计与叙…

Dom的学习

DOM&#xff08;文档对象模型&#xff0c;Document Object Model&#xff09;是一个编程接口&#xff0c;用于HTML和XML文档。它将文档表示为一个树形结构&#xff0c;其中每个节点都是文档的一部分&#xff0c;例如元素、属性和文本内容。通过DOM&#xff0c;开发者可以使用编…

游戏行业销售数据分析可视化

完整源码项目包获取→点击文章末尾名片&#xff01; &#x1f31f;分析&#xff1a; 可看出最近五年用户最喜爱的游戏类型依然还是Action-动作类&#xff08;当然市场发行的也很多&#xff09; Sports-运动类和Shooter-射击类顺序互换,但我估计现在大环境局势紧张可以会推动射击…

Linux 管道操作

Linux 管道操作 在 Linux 中&#xff0c;管道&#xff08;Pipe&#xff09;是一个非常强大且常用的功能&#xff0c;它允许将一个命令的输出直接传递给另一个命令作为输入&#xff0c;从而能够高效地处理和分析数据。管道在多个命令之间建立数据流&#xff0c;减少了文件的读写…

深度学习加速性能分析与Roofline Model

深度学习加速性能分析 动因:由于深度学习加速器普遍采用时分复用(当然随着Graphcore等dataflow类型的芯片除外,他们是空间划分)。此时,硬件资源在不同时刻执行的计算发生变化,很难以单一时刻的计算类型进行硬件设计。所以寻找平均资源利用率就变得更重要方法:针对不同任…

第12章:Python TDD完善货币加法运算(一)

写在前面 这本书是我们老板推荐过的&#xff0c;我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后&#xff0c;我突然思考&#xff0c;对于测试开发工程师来说&#xff0c;什么才更有价值呢&#xff1f;如何让 AI 工具更好地辅助自己写代码&#xff0c;或许…

Golang Gin系列-4:Gin Framework入门教程

在本章中&#xff0c;我们将深入研究Gin&#xff0c;一个强大的Go语言web框架。我们将揭示制作一个简单的Gin应用程序的过程&#xff0c;揭示处理路由和请求的复杂性。此外&#xff0c;我们将探索基本中间件的实现&#xff0c;揭示精确定义路由和路由参数的技术。此外&#xff…

靠右行驶数学建模分析(2014MCM美赛A题)

笔记 题目 要求分析&#xff1a; 比较规则的性能&#xff0c;分为light和heavy两种情况&#xff0c;性能指的是 a.流量与安全 b. 速度限制等分析左侧驾驶分析智能系统 论文 参考论文 两类规则分析 靠右行驶&#xff08;第一条&#xff09;2. 无限制&#xff08;去掉了第一条…

PyTorch使用教程(11)-cuda的使用方法

1. 基本概念 CUDA&#xff08;Compute Unified Device Architecture&#xff09;是NVIDIA开发的一种并行计算平台和编程模型&#xff0c;专为图形处理器&#xff08;GPU&#xff09;设计&#xff0c;旨在加速科学计算、工程计算和机器学习等领域的高性能计算任务。CUDA允许开发…

金融项目实战 07|Python实现接口自动化——连接数据库和数据清洗、测试报告、持续集成

目录 一、投资模块&#xff08;投资接口投资业务&#xff09; 二、连接数据库封装 和 清洗数据 1、连接数据库 2、数据清洗 4、调用 三、批量执行测试用例 并 生成测试报告 四、持续集成 1、代码上传gitee 2、Jenkin持续集成 一、投资模块&#xff08;投资接口投资业务…

Ubuntu22.04安装paddle GPU版本

文章目录 确立版本安装CUDA与CUDNN安装paddle 确立版本 查看官网信息&#xff0c;确立服务版本&#xff1a;https://www.paddlepaddle.org.cn/documentation/docs/zh/2.6/install/pip/linux-pip.html 安装CUDA与CUDNN 通过nvidia-smi查看当前显卡驱动版本&#xff1a; 通过…