【二】[详细]针孔相机模型、相机镜头畸变模型、相机标定与OpenCV实现
目录
1.4大坐标系
2.相机成像原理
3.光圈(控制进光量)
4.现实生活中的相机系统
5.坐标系的关系
图像坐标系和相机坐标的关系
像素坐标系和图像坐标系的关系
相机坐标系到世界坐标系的关系
6.相机畸变
1.径向畸变(Radial Distortion)
2.切向畸变(Tangential Distortion)
7.图像插值
8.标定
理论:
DLT求解相机标定原理:
张正友标定法:
实现过程:
实验代码:
函数讲解:
FindChessboardCorners()
drawChessboardCorners()
cornerSubPix()
calibrateCamera()
initUndistortRectifyMap()
remap()
undistort()
projectPoints()
参考:
1.4大坐标系
首先,相机的成像过程涉及到四个坐标系:世界坐标系、相机坐标系、图像坐标系、像素坐标系。接下来依次介绍:
- 世界坐标系(单位:m)
客观三维世界的绝对坐标系。因为相机安放在三维空间中,我们需要世界坐标系这个基准坐标系来描述相机的位置,并且用它来描述安放在此三维环境中的其它任何物体的位置,表示为:
- 相机坐标系(单位:m)
以相机的光心为坐标原点,X 轴和Y 轴分别平行于图像坐标系的 X 轴和Y 轴,相机的光轴为Z 轴,表示为:
- 图像坐标系(单位:mm)
以CCD 图像平面的中心为坐标原点,X轴和Y 轴分别平行于图像平面的两条垂直边。图像坐标系是用物理单位(例如毫米)表示像素在图像中的位置。表示为:
- 像素坐标系(单位:像素(pixel))
以图像的左上角点为坐标原点,水平方向向右为x轴(u轴),数值方向向下为y轴(v轴)。表示为:
2.相机成像原理
如何成像:
- 在物体和胶片之间,增加一块带有小孔的屏障,这就构成了小孔成像,用数学模型表示就叫做:针孔相机模型,而屏障上的小孔称之为光圈,并且胶片上获得倒立的图像。
- object到barrier的距离为Z,也就是深度,film到barrier的距离为f,也就是焦距。
- 针孔相机模型: f为焦距,X为三维坐标中点,x为相机坐标系中的点
3.光圈(控制进光量)
光圈越小,进的光线减少,画面越暗,背景虚化越小
光圈越大,进的光线增加,画面越亮,背景虚化越大
4.现实生活中的相机系统
这也说明了,尽管从物理原理来说,小孔成像的像应该是倒像,但是由于相机的自身设计,像一般变为正的了。
5.坐标系的关系
图像坐标系和相机坐标的关系
首先,我们可以通过两个正的相似三角形可以得到图像坐标系和相机坐标系的关系:
用齐次坐标系和矩阵表示上述关系:
像素坐标系和图像坐标系的关系
接着,对于像素坐标系和图像坐标系的关系,它们之间相差了一个缩放和一个原点的平移。我们设像素坐标在 u 轴上缩放了 1/dx倍,在 v 上缩放了 1/dy倍,那么我们可以表示为:
用矩阵的形式表示:
- 两种关系合并:
相机坐标系到世界坐标系的关系
相机坐标系到世界坐标系存在一个位姿的变换,[R|T],写成矩阵的形式如下:
组合在一起:
其中, 相机的内参K 为:
R和T分别为世界坐标系和相机坐标系之间的旋转矩阵和平移矩阵,两者组成了相机的外参矩阵,
相机的外参矩阵和内参矩阵构成了相机的投影矩阵P= K[R |t]
6.相机畸变
1.径向畸变(Radial Distortion)
简单来说,由透镜形状(相机镜头径向曲率的不规则变化)引起的畸变称为径向畸变,是导致相机成像变形的主要因素。径向畸变主要分为桶形畸变和枕型畸变。在针孔模型中,一条直线投影到像素平面上还是一条直线。 但在实际中,相机的透镜往往使得真实环境中的一条直线在图片中变成了曲线。越靠近图像的边缘现象越明显。 由于透镜往往是中心对称的,这使得不规则畸变通常径向对称。(成像中心处的径向畸变最小,距离中心越远,产生的变形越大,畸变也越明显 )
- 正向畸变(枕型畸变):从图像中心开始,径向曲率逐渐增加。
- 负向畸变(桶形畸变):边缘的径向曲率小于中心的径向曲率。(鱼眼相机)
实际摄像机的透镜总是在成像仪的边缘产生显著的畸变,这种现象来源于“筒形”或“鱼眼”的影响。如下图,光线在原理透镜中心的地方比靠近中心的地方更加弯曲。对于常用的普通透镜来说,这种现象更加严重。筒形畸变在便宜的网络摄像机中非常厉害,但在高端摄像机中不明显,因为这些透镜系统做了很多消除径向畸变的工作。
径向畸变模型: r 为像平面坐标系中点(x, y)与图像中心(x0, y0)的像素距离。
- 当k1为0.01,0.02,0.03,0.04,-0.01,-0.02,-0.03,-0.04时,1+k1*r^2的函数曲线
- 当k1一定时,随着r的增加,畸变影响越大
- 随着k1的增加或者减小,畸变影响变小
- 1+r^2,1+r^4,1+r^6,1+r^8的函数曲线 (次方越高,函数曲线越接近)
- k2为0.01,0.02,0.03,-0.01,-0.02,-0.03时,1+0.01*x^2+k2*x^4的曲线
- 高次的影响
2.切向畸变(Tangential Distortion)
切向畸变是由于相机镜头在制造安装过程中并非完全平行于成像平面造成的。不同于径向畸变在图像中心径向方向上发生偏移变形,切向畸变主要表现为图像点相对理想成像点产生切向偏移。
切向畸变模型可以描述为:p 1和p 2 —镜头的切向畸变系数。
最终需要得到的5个畸变参数:
畸变参数的一般顺序是k1,k2,p1,p2,k3。之所以把k3放在最后其实也很容易理解,因为前面说了一般k1,k2用来处理径向畸变足矣,k3相对而言用的比较少。 在获得了畸变参数以后,也就找到了真实观测的带畸变的像素与无畸变的像素间的关系,重采样即可实现影像校正。
- 非畸变图像中的像素点(u,v)--->非畸变的图像坐标系(x,y)
- 畸变后的图像坐标系(x',y'),由畸变模型(x,y)-->(x',y')
- 根据相机模型,得到畸变图像上的像素点坐标(u',v')
7.图像插值
- 最近邻插值(INTER_NEAREST)
将目标图像中的点对应到原图像中后,找到最相邻的整数坐标点的像素值,作为该点的像素值输出。由最邻近插值法得到的图像放大后有很严重的马赛克,会出现明显的块状效应,缩小后的图像有很严重的失真。
- 双线性插值(先两次x轴方向上的线性插值,再y方向上一次线性插值)
8.标定
理论:
相机标定的基本原理:确定场景中一系列点的三维坐标并拍摄这个场景,然后观测这些点在图像上投影的位置。有了足够多的三维点和图像上对应的二维点,就可以根据投影方程推断出准确的相机参数。
- 实质:已知x、X,求K、R、t
DLT求解相机标定原理:
- 一组2D-3D对应点提供关于P的两个线性方程
- n组2D-3D对应点提供关于P的2n个线性方程
- 当n≥6时,P可以通过DLT线性解出最小二乘解(P的自由度为11),然后从P中分解相机内外参数K、R、t,这样我们就得到了其内参和外参。
但是,对于DLT标定方法来说,存在一定的问题,因为我们都知道相机得到的图像不是理想的,还存在着畸变,然而该方法没有考虑相机的畸变。
张正友标定法:
张正友标定法主要利用平面标定板进行实现,虽然精度上不及使用三维标定物,但是这种方法更加的实用(打印一张黑白棋盘格、一块足够平的木板)
实现过程:
OpenCV推荐使用国际象棋棋盘的图案生成用于校准的三维场景点的集合。这个图案在每个方块的角点位置创建场景点,并且由于图案是平面的,因此我们可以假设棋盘位于Z=0且X 和Y 的坐标轴与网格对齐的位置。这样,校准时就只需从不同的视角拍摄棋盘图案。下面是一个6 × 9的图案:
- 寻找棋盘格中的角点
bool found = cv::findChessboardCorners(image,boardSize, imageCorners);
- 对寻找到的角点进行亚像素提纯
cornerSubPix(gray,corners,cv::Size(5, 5), cv::Size(-1, -1),TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
- 可以打印并显示检测到的角点
drawChessboardCorners(img,board_size,corners,found);
- 保存2D角点和3D点
image_points.push_back(corners); object_points.push_back(objectCorners);
- 标定
calibrateCamera(object_points,image_points,img.size(),instrisincMatrix,distortionCoeff,rvecs,tvecs);
矫正
得到标定参数以后,我们需要使用畸变参数对图像进行矫正,OpenCV中对畸变图像进行畸变校正主要用的函数有:
- undistort()函数
- initUndistortRectifyMap()结合remap()函数
其实undistort()就是initUndistortRectifyMap()和remap()的简单组合,效果是一样的。
- 计算重投影误差
projectPoints(Mat(objectPoints[i]), rvecs[i], tvecs[i], cameraMatrix,distCoeffs, imagePoints2);
注意:根据经验,10~20个棋盘图像就足够了,但是必须在不同的深度,从不同的视角拍摄。这个函数的两个重要输出对象是相机矩阵和畸变参数。
实验代码:
完整代码链接:里面包含了实现的代码和采集的29张棋盘格照片
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <string>
#include <vector>
using namespace std;
using namespace cv;
void computeReprojectionErrors(const vector< vector< Point3f > >& objectPoints,const vector< vector< Point2f > >& imagePoints,const vector< Mat >& rvecs, const vector< Mat >& tvecs,const Mat& cameraMatrix , const Mat& distCoeffs) {vector< Point2f > imagePoints2;for (int i = 0; i < (int)objectPoints.size(); ++i) {double err;projectPoints(Mat(objectPoints[i]), rvecs[i], tvecs[i], cameraMatrix,distCoeffs, imagePoints2);err =(double) norm(Mat(imagePoints[i]), Mat(imagePoints2), CV_L2)/objectPoints[i].size();cout<<"第"<<i+1<<"图片的误差为: "<<err<<endl;}
}
vector< vector< Point3f > > object_points;
vector< vector< Point2f > > image_points;
int main() {// 水平和垂直方向内部角点的数量int board_width=6;int board_height=9;//图片的数量int num_imgs=29;string base_path="../calib_imgs/1";Size board_size=Size(board_width,board_height);vector<Point2f> corners;std::vector<cv::Point3f> objectCorners;// 处理所有视角Mat img,gray;for (int k = 1; k <= num_imgs; k++){char filename[100];sprintf(filename,"%s/left%d.jpg",base_path.c_str(),k);img=imread(filename,CV_LOAD_IMAGE_COLOR);cvtColor(img,gray,CV_BGR2GRAY);bool found=false;found=findChessboardCorners(img,board_size,corners,CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);if(found){cornerSubPix(gray,corners,cv::Size(5, 5), cv::Size(-1, -1),TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));drawChessboardCorners(img,board_size,corners,found);}// 场景中的三维点:// 在棋盘坐标系中,初始化棋盘中的角点// 角点的三维坐标(X,Y,Z)= (j,i,0)// 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和yfor (int i=0; i<board_size.height; i++) {for (int j=0; j<board_size.width; j++) {objectCorners.push_back(cv::Point3f(j, i, 0.0f));
// cout<<"("<<j<<","<<i<<")"<<endl;}}if (found) {cout << k << ". Found corners!" << endl;image_points.push_back(corners);object_points.push_back(objectCorners);objectCorners.clear();}
// imshow("1",img);
// waitKey(0);}cv::Mat instrisincMatrix=cv::Mat::eye(3,3,CV_64F);cv::Mat distortionCoeff=cv::Mat::zeros(4,1,CV_64F);vector<Mat> rvecs, tvecs;int flag = 0;flag |= CV_CALIB_FIX_K4;flag |= CV_CALIB_FIX_K5;calibrateCamera(object_points,image_points,img.size(),instrisincMatrix,distortionCoeff,rvecs,tvecs);cout<<"instrisincMatrix: "<<endl<<instrisincMatrix<<endl;cout<<"distortionCoeff: "<<endl<<distortionCoeff<<endl;computeReprojectionErrors(object_points, image_points, rvecs, tvecs, instrisincMatrix, distortionCoeff);//通过畸变校正效果查看摄像机标定效果cv::Mat R = cv::Mat::eye(3, 3, CV_32FC1);cv::Mat mapx, mapy, undistortImg;cv::initUndistortRectifyMap(instrisincMatrix, distortionCoeff, R, instrisincMatrix, img.size(), CV_32FC1, mapx, mapy);cv::remap(img, undistortImg, mapx, mapy, CV_INTER_LINEAR);cv::imshow("undistortImg", undistortImg);cv::waitKey(0);return 0;
}
函数讲解:
FindChessboardCorners()
bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners,int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );
- 功能:用来寻找棋盘图的内角点位置。
- 参数:
- Image:输入的棋盘图,必须是8位的灰度或者彩色图像。
- patternSize:棋盘图中每行和每列角点的个数(内点)。
- imageCorners:存储检测到的内部角点的像素坐标
- Flags:各种操作标志,可以是0或者下面值的组合:
CV_CALIB_CB_ADAPTIVE_THRESH -使用自适应阈值(通过平均图像亮度计算得到)将图像转换为黑白图,而不是一个固定的阈值。
CV_CALIB_CB_NORMALIZE_IMAGE -在利用固定阈值或者自适应的阈值进行二值化之前,先使用cvNormalizeHist来均衡化图像亮度。
CV_CALIB_CB_FILTER_QUADS -使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。
drawChessboardCorners()
cv::drawChessboardCorners(image,boardSize, imageCorners,found); // 找到的角点
- 功能:画出棋盘图像上的角点,用线条依次连接起来
- 参数:
- Image:输入的棋盘图,必须是8位的灰度或者彩色图像。
- boardSize:棋盘图中每行和每列角点的个数(内点)。
- imageCorners:存储检测到的内部角点的像素坐标
- found:是否成功找到(bool)
cornerSubPix()
void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone, TermCriteria criteria);
- 功能:亚像素角点检测
- 参数:
- cv::InputArray image:输入图像
- cv::InputOutputArray corners: 角点(既作为输入,也作为输出)
- cv::Size winSize:区域大小为 NXN; N=(winSize*2+1)
- cv::Size zeroZone:类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略
- cv::TermCriteria criteria : 停止优化的标准
TermCriteria:
cv::TermCriteria::TermCriteria ( int type, int maxCount, double epsilon)
- type:迭代终止的条件类型(cv::TermCriteria::MAX_ITER (迭代次数达到了最大次数)、cv::TermCriteria::EPS(角点位置变化的最小值),可以选其一,或两者均选)
- maxCount:最大迭代的次数
- epsilon:收敛的阈值
calibrateCamera()
double calibrateCamera( InputArrayOfArrays objectPoints,InputArrayOfArrays imagePoints, Size imageSize,InputOutputArray cameraMatrix, InputOutputArray distCoeffs,OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) );
- 功能:相机标定
- 参数:
- objectPoints: 三维点
- imagePoints,: 图像点
- imageSize:图像尺寸
- cameraMatrix:输出相机矩阵
- distCoeffs: 输出畸变矩阵
- rvecs, tvecs: Rs、Ts
- flag:设置选项
initUndistortRectifyMap()
void initUndistortRectifyMap( InputArray cameraMatrix,InputArray distCoeffs,InputArray R,InputArray newCameraMatrix,Size size,int m1type,OutputArray map1,OutputArray map2 )
- 功能:
这个函数用于计算无畸变和修正转换关系,并以映射的形式表示结果以进行重新映射。无畸变的图像看起来就像原始的图像,就像这个图像是用内参为newCameraMatrix的且无畸变的相机采集得到的。
在单目相机例子中,newCameraMatrix一般和cameraMatrix相等,或者可以用cv::getOptimalNewCameraMatrix来计算,获得一个更好的有尺度的控制结果。
在双目相机例子中,newCameraMatrix一般是用cv::stereoRectify计算而来的,设置为P1或P2。 此外,根据R,新的相机在坐标空间中的取向是不同的。例如,它帮助配准双目相机的两个相机方向,从而使得两个图像的极线是水平的,且y坐标相同(在双目相机的两个相机谁水平放置的情况下)。 该函数实际上为反向映射算法构建映射,供反向映射使用。也就是,对于在已经修正畸变的图像中的每个像素(u,v),该函数计算原来图像(从相机中获得的原始图像)中对应的坐标系
- 参数:
remap()
void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
- 功能:重映射,把一副图像中某位置的像素放到另一幅图像的指定位置的过程。
例如:g(x,y)为目标图像函数,f(x,y)为源图像,h(x,y)为映射函数
如果要是实现按x的翻转,则h(x,y)=(l.cols-x,y);
- 参数:
src:输入图像,即原图像,需要单通道8位或者浮点类型的图像
dst :输出图像,即目标图像,需和原图形一样的尺寸和类型
map1:它有两种可能表示的对象:(1)表示点(x,y)的第一个映射;(2)表示CV_16SC2,CV_32FC1等
map2:它有两种可能表示的对象:(1)若map1表示点(x,y)时,这个参数不代表任何值;(2)表示 CV_16UC1,CV_32FC1类型的Y值
interpolation:插值方式,有四中插值方式:(1)INTER_NEAREST——最近邻插值
(2)INTER_LINEAR——双线性插值(默认)(3)INTER_CUBIC——双三样条插值(默认)
(4)INTER_LANCZOS4——lanczos插值(默认)
borderMode:边界模式,默认BORDER_CONSTANT
borderValue:边界颜色,默认Scalar()黑色
undistort()
void undistort(InputArray src, OutputArray dst, InputArray cameraMatrix, InputArray distCoeffs, InputArray newCameraMatrix=noArray() )
- 功能:矫正畸变
- 参数:
- src –(输入)失真图像。
- dst –(输出)校正的图像,其大小和类型与相同
src
。- cameraMatrix –相机内参矩阵 。
- distCoeffs – 相机的畸变矩阵 。如果向量为空,则假定零畸变系数。
- newCameraMatrix –新的内参矩阵。默认情况下,它与
cameraMatrix
相同。可以使用getOptimalNewCameraMatrix()计算newCameraMatrix。
projectPoints()
void projectPoints( InputArray objectPoints,InputArray rvec, InputArray tvec,InputArray cameraMatrix, InputArray distCoeffs,OutputArray imagePoints,OutputArray jacobian = noArray(),double aspectRatio = 0 );
- 功能:通过给定的内参数和外参数计算三维点投影到二维图像平面上的坐标
- 参数:
- objectPoints:输入三维点
- rvec,tvec:相机的位姿R,T
- cameraMatrix:内参矩阵
- distCoeffs:畸变矩阵
- imagePoints:输出像素坐标系坐标
- jacobian:
参考:
https://www.cnblogs.com/zyly/p/9373991.html
https://blog.csdn.net/tiemaxiaosu/article/details/51734667
相机畸变与标定:http://zhaoxuhui.top/blog/2018/04/17/CameraCalibration.html
综述|相机标定方法:https://cloud.tencent.com/developer/article/1500292
最详细、最完整的相机标定讲解:https://blog.csdn.net/a083614/article/details/78579163
OpenCV相机标定和姿态更新:https://www.cnblogs.com/mikewolf2002/p/5746667.html
SLAM 中常用的相机模型&畸变模型总结:https://blog.csdn.net/OKasy/article/details/90665534
Opencv畸变矫正原理与损失有效像素原理分析:https://www.cnblogs.com/riddick/p/6711263.html
双目视觉自标定技术的研究:https://wenku.baidu.com/view/f8639568011ca300a6c39057.html?sxts=1585838430474
Zhengyou Zhang: A Flexible New Technique for Camera Calibration. IEEE T-PAMI), 2000.
[图像]畸变校正详解:https://blog.csdn.net/humanking7/article/details/45037239
超实用!图像去畸变矫正及双线性内插法:https://blog.csdn.net/Yong_Qi2015/article/details/107031879
【二】[详细]针孔相机模型、相机镜头畸变模型、相机标定与OpenCV实现相关推荐
- 针孔相机模型和相机镜头畸变模型
针孔相机模型和相机镜头畸变模型 一.针孔相机模型 图1. 针孔相机模型 针孔相机模型(如图1所示)存在四个坐标系:世界坐标系.摄像机坐标系.图像物理坐标系和图像像素坐标系.假设现实世界的空间点的世界坐 ...
- 针孔相机投影模型以及畸变模型
Overview 欢迎访问 持续更新:https://cgabc.xyz/posts/ff73e084/ 世界坐标系 到 像素坐标系 世界坐标系中三维点M=[X,Y,Z]TM=[X,Y,Z]^TM=[ ...
- 2.3ORBSLAM3之相机模型与畸变模型
1.简介 主要内容: 1. 对SLAM中常见的相机模型进行介绍,包括针孔相机模型和鱼眼相机模型 2. 对每种相机模型的畸变模型进行介绍 3. 对VSLAM中常见的几种去畸变方法进行介绍 4. 对常见的 ...
- 相机标定:相机模型和畸变模型
一.相机标定方案 相机内参标定是确定内参和畸变参数(equidistqant畸变模型)或者(radial tangential模型)的过程. 本文首先介绍SLAM中常用的相机模型和畸变模型,随后介绍我 ...
- 相机标定 matlab opencv ROS三种方法标定步骤(1)
一 . 理解摄像机模型,网上有很多讲解的十分详细,在这里我只是记录我的整合出来的资料和我的部分理解 计算机视觉领域中常见的三个坐标系:图像坐标系,相机坐标系,世界坐标系,实际上就是要用矩阵来表 示各个 ...
- 鱼眼相机标定以及OpenCV实现
在另一篇文章中我已经写过有关普通相机模型及其OpenCV标定实现,这篇文章将主要关注鱼眼相机模型及其OpenCV标定实现. 先看一张鱼眼相机拍摄出来的结果: 从图中可以看出很明显的畸变.对鱼眼相机标定 ...
- matlab相机标定畸变参数,相机标定的原理与意义及OpenCVMatlab实现差异小结.doc
2011-01-30 相机标定的原理与意义及OpenCV.Matlab实现差异小结 分类:?OpenCV点滴2011-01-30 20:35?2292人阅读?评论(3)?收藏?举报 ??? 本文是一篇 ...
- 相机标定 matlab opencv ROS三种方法标定步骤(2)
二 ubuntu下Opencv的相机标定 一般直接用Opencv的源码就可以进行相机的标定,但是可能只是会实现结果,却不懂实现的过程,我也是模模糊糊的看了<计算机视觉中的多视图几何>以及 ...
- OpenCV | 双目相机标定之OpenCV获取左右相机图像+MATLAB单目标定+双目标定
博主github:https://github.com/MichaelBeechan 博主CSDN:https://blog.csdn.net/u011344545 原本网上可以搜到很多关于双目相机标 ...
- 研电赛项目之双目测距,涉及matlab相机标定,opencv多线程编程,摄像头读取,行人检测、BM立体匹配等等
1 前言 今年参加了十五届研电赛,前天刚提交了作品,还有几天就答辩了,趁这几天总结一下这一个多月的收获. 本次研电赛作品为汽车行驶防碰撞系统,主要面向大型汽车在低速行驶场景下的防碰撞问题,通过双目相机 ...
最新文章
- Android 标签 (FlexboxLayout实现标签)
- JAVA入门到精通-第73讲-学生管理系统5-dao.sqlhelper
- 三巨头对中国人工智能技术的支撑性作用
- WPF中获取鼠标相对于桌面位置
- 七牛云智能日志管理平台正式发布
- JAVA去掉HTMl以及CSS样式
- 训练指南——数学专题一的总结
- SQLServer数据库差异备份
- ROS的学习(十五)验证publisher和subscriber
- 虚点连边 分层最短路
- “放管服”改革背景下公安车驾管业务办理情况调研
- 什么是反馈电路?反馈有什么作用?
- 直播源php代理用什么主机,流媒体直播系统_流媒体直播php源码_流媒体直播源码...
- nls_lang环境变量linux设置,设置NLS_LANG环境变量
- lizard的基本使用
- 2022年文化艺术品产权交易所研究报告
- 前端系列之实战(城市医院预约挂号平台2.基本样式编写)
- 《On Java 8》- 面向对象之代码复用(组合、继承、委托)
- 我用Python分析5W+视频数据,看看谁才是最咕UP主
- 【北邮国院大二下】产品开发与营销知识点整理 Topic11
热门文章
- 苹果手机小圆点怎么设置?悬浮球设置,轻松学会
- 整理常用的PHP函数
- 改善客户服务体验的 5 种方法
- 今天是第几天python_“昔我往矣,杨柳依依。今我来思,雨雪霏霏”全诗赏析
- 全民热议“10万彩礼结不了婚”的背后,百合网做了什么?
- windows server 2008r2更新server pack 1补丁包和勒索病毒nsa,永恒之蓝 补丁包
- 深入浅出面板数据分析
- 活着就是要做有意义的事,做有意义的事就是好好活着
- Pytorch使用CPU
- linux audit 服务,linux 的 audit 服務