ORB-SLAM2源码学习:Initializer.cc⑧: Initializer::CheckRT检验三角化结果

前言

ORB-SLAM2源码学习:Initializer.cc⑦: Initializer::Triangulate特征点对的三角化_cv::svd::compute-CSDN博客

经过上面的三角化我们成功得到了三维点,但是经过三角化成功的三维点并不一定是有效的,需要筛选才能作为初始化地图点。 

1.函数声明 

int Initializer::CheckRT(const cv::Mat &R, const cv::Mat &t, const vector<cv::KeyPoint> &vKeys1, const vector<cv::KeyPoint> &vKeys2,const vector<Match> &vMatches12, vector<bool> &vbMatchesInliers,const cv::Mat &K, vector<cv::Point3f> &vP3D, float th2, vector<bool> &vbGood, float &parallax)

2.函数定义 

 我们把相机1的光轴中心作为世界坐标系的原点,从相机1到相机2的位姿:

则从相机2到相机1的位姿: 

对应关系: 

 则相机2的光轴中心O2在相机1的坐标系下的坐标为:

计算相机2 的光轴中心O2 在相机1 坐标系下的坐标是为了求解三维点分别在两个坐标系下和光轴中心的夹角。如果我们要求向量夹角,那么前提是这些向量都在同一个坐标系下。我们看相机1坐标系,此时O1是相机1 的光轴中心,也是相机1 坐标系原点, P3d 是相机1坐标系(世界坐标系)下的三维点,这就必须得到O2在相机1 坐标系下的坐标,也就是我们前面推导的过程。

计算夹角是为了判断三维点的有效性, 因为初始化地图点( 三角化得到的三维点)特别重要,后续跟踪都是以此为基础的,所以在确定三维点时要非常小心。确定一个合格的三维点需要通过以下条件:

1.三维点的3 个坐标都必须是有限的实数。

2.三维点深度值必须为正。

3.三维点和两帧图像光轴中心夹角需要满足一定的条件。夹角越大,视差越大, 三角化结果越准确。

4. 三维点的重投影误差小于设定的阈值。

经过上面条件的筛选,最后剩下的三维点才是合格的三维点。我们会记录当前位姿对应的合格三维点数目和视差。

具体的流程

1.计算前的参数准备与声明
// 对给出的特征点对及其R t , 通过三角化检查解的有效性,也称为 cheirality check// Calibration parameters//从相机内参数矩阵获取相机的校正参数const float fx = K.at<float>(0,0);const float fy = K.at<float>(1,1);const float cx = K.at<float>(0,2);const float cy = K.at<float>(1,2);//特征点是否是good点的标记,这里的特征点指的是参考帧中的特征点vbGood = vector<bool>(vKeys1.size(),false);//重设存储空间坐标的点的大小vP3D.resize(vKeys1.size());//存储计算出来的每对特征点的视差vector<float> vCosParallax;vCosParallax.reserve(vKeys1.size());
2.构建投影矩阵计算相机光心2在世界坐标系下的坐标

这里与前边推导的过程一致。

 // Camera 1 Projection Matrix K[I|0]// Step 1:计算相机的投影矩阵  // 投影矩阵P是一个 3x4 的矩阵,可以将空间中的一个点投影到平面上,获得其平面坐标,这里均指的是齐次坐标。// 对于第一个相机是 P1=K*[I|0]// 以第一个相机的光心作为世界坐标系, 定义相机的投影矩阵cv::Mat P1(3,4,				//矩阵的大小是3x4CV_32F,			//数据类型是浮点数cv::Scalar(0));	//初始的数值是0//将整个K矩阵拷贝到P1矩阵的左侧3x3矩阵,因为 K*I = KK.copyTo(P1.rowRange(0,3).colRange(0,3));// 第一个相机的光心设置为世界坐标系下的原点cv::Mat O1 = cv::Mat::zeros(3,1,CV_32F);// Camera 2 Projection Matrix K[R|t]// 计算第二个相机的投影矩阵 P2=K*[R|t]cv::Mat P2(3,4,CV_32F);R.copyTo(P2.rowRange(0,3).colRange(0,3));t.copyTo(P2.rowRange(0,3).col(3));//最终结果是K*[R|t]P2 = K*P2;// 第二个相机的光心在世界坐标系下的坐标cv::Mat O2 = -R.t()*t;
3.开始遍历所有的特征点对
//在遍历开始前,先将good点计数设置为0int nGood=0;// 开始遍历所有的特征点对for(size_t i=0, iend=vMatches12.size();i<iend;i++){// 跳过outliersif(!vbMatchesInliers[i])continue;....}    
3.1调用Triangulate函数进行三角化
 // Step 2 获取特征点对,调用Triangulate() 函数进行三角化,得到三角化测量之后的3D点坐标// kp1和kp2是匹配好的有效特征点const cv::KeyPoint &kp1 = vKeys1[vMatches12[i].first];const cv::KeyPoint &kp2 = vKeys2[vMatches12[i].second];//存储三维点的的坐标cv::Mat p3dC1;// 利用三角法恢复三维点p3dC1Triangulate(kp1,kp2,	//特征点P1,P2,		//投影矩阵p3dC1);		//输出,三角化测量之后特征点的空间坐标		
3.2合格的三维点的条件1的判断
// Step 3 第一关:检查三角化的三维点坐标是否合法(非无穷值)// 只要三角测量的结果中有一个是无穷大的就说明三角化失败,跳过对当前点的处理,进行下一对特征点的遍历 if(!isfinite(p3dC1.at<float>(0)) || !isfinite(p3dC1.at<float>(1)) || !isfinite(p3dC1.at<float>(2))){//其实这里就算是不这样写也没问题,因为默认的匹配点对就不是good点vbGood[vMatches12[i].first]=false;//继续对下一对匹配点的处理continue;}
3.3合格的三维点的条件2和3的判断
// Check parallax// Step 4 第二关:通过三维点深度值正负、两相机光心视差角大小来检查是否合法 //得到向量PO1cv::Mat normal1 = p3dC1 - O1;//求取模长,其实就是距离float dist1 = cv::norm(normal1);//同理构造向量PO2cv::Mat normal2 = p3dC1 - O2;//求模长float dist2 = cv::norm(normal2);//根据公式:a.*b=|a||b|cos_theta 可以推导出来下面的式子float cosParallax = normal1.dot(normal2)/(dist1*dist2);// Check depth in front of first camera (only if enough parallax, as "infinite" points can easily go to negative depth)// 如果深度值为负值,为非法三维点跳过该匹配点对// ?视差比较小时,重投影误差比较大。这里0.99998 对应的角度为0.36°,这里不应该是 cosParallax>0.99998 吗?// ?因为后面判断vbGood 点时的条件也是 cosParallax<0.99998 // !可能导致初始化不稳定if(p3dC1.at<float>(2)<=0 && cosParallax<0.99998)continue;// Check depth in front of second camera (only if enough parallax, as "infinite" points can easily go to negative depth)// 讲空间点p3dC1变换到第2个相机坐标系下变为p3dC2cv::Mat p3dC2 = R*p3dC1+t;	//判断过程和上面的相同if(p3dC2.at<float>(2)<=0 && cosParallax<0.99998)continue;
3.4计算重投影误差
// Step 5 第三关:计算空间点在参考帧和当前帧上的重投影误差,如果大于阈值则舍弃// Check reprojection error in first image// 计算3D点在第一个图像上的投影误差//投影到参考帧图像上的点的坐标x,yfloat im1x, im1y;//这个使能空间点的z坐标的倒数float invZ1 = 1.0/p3dC1.at<float>(2);//投影到参考帧图像上。因为参考帧下的相机坐标系和世界坐标系重合,因此这里就直接进行投影就可以了im1x = fx*p3dC1.at<float>(0)*invZ1+cx;im1y = fy*p3dC1.at<float>(1)*invZ1+cy;//参考帧上的重投影误差,这个的确就是按照定义来的float squareError1 = (im1x-kp1.pt.x)*(im1x-kp1.pt.x)+(im1y-kp1.pt.y)*(im1y-kp1.pt.y);// 重投影误差太大,跳过淘汰if(squareError1>th2)continue;// Check reprojection error in second image// 计算3D点在第二个图像上的投影误差,计算过程和第一个图像类似float im2x, im2y;// 注意这里的p3dC2已经是第二个相机坐标系下的三维点了float invZ2 = 1.0/p3dC2.at<float>(2);im2x = fx*p3dC2.at<float>(0)*invZ2+cx;im2y = fy*p3dC2.at<float>(1)*invZ2+cy;// 计算重投影误差float squareError2 = (im2x-kp2.pt.x)*(im2x-kp2.pt.x)+(im2y-kp2.pt.y)*(im2y-kp2.pt.y);// 重投影误差太大,跳过淘汰if(squareError2>th2)continue;
3.5统计经过检验的三维点信息
 // Step 6 统计经过检验的3D点个数,记录3D点视差角 // 如果运行到这里就说明当前遍历的这个特征点对靠谱,经过了重重检验,说明是一个合格的点,称之为good点 vCosParallax.push_back(cosParallax);//存储这个三角化测量后的3D点在世界坐标系下的坐标vP3D[vMatches12[i].first] = cv::Point3f(p3dC1.at<float>(0),p3dC1.at<float>(1),p3dC1.at<float>(2));//good点计数++nGood++;//判断视差角,只有视差角稍稍大一丢丢的才会给打good点标记//? bug 我觉得这个写的位置不太对。你的good点计数都++了然后才判断,不是会让good点标志和good点计数不一样吗if(cosParallax<0.99998)vbGood[vMatches12[i].first]=true;
4.得到最小的视差角 

如果满足要求的三维点数大于50就获取其中最小的视差角如果不满足数量要求就将视差角设置为0。

  // Step 7 得到3D点中较小的视差角,并且转换成为角度制表示if(nGood>0){// 从小到大排序,注意vCosParallax值越大,视差越小sort(vCosParallax.begin(),vCosParallax.end());// !排序后并没有取最小的视差角,而是取一个较小的视差角// 作者的做法:如果经过检验过后的有效3D点小于50个,那么就取最后那个最小的视差角(cos值最大)// 如果大于50个,就取排名第50个的较小的视差角即可,为了避免3D点太多时出现太小的视差角 size_t idx = min(50,int(vCosParallax.size()-1));//将这个选中的角弧度制转换为角度制parallax = acos(vCosParallax[idx])*180/CV_PI;}else//如果没有good点那么这个就直接设置为0了parallax=0;//返回good点计数return nGood;

完整的代码分析

/*用位姿来对特征匹配点三角化,从中筛选中合格的三维点R                                     旋转矩阵Rt                                     平移矩阵tvKeys1                                参考帧特征点vKeys2                                当前帧特征点vMatches12                            两帧特征点的匹配关系vbMatchesInliers                      特征点对内点标记K                                     相机内参矩阵vP3D                            三角化测量之后的特征点的空间坐标th2                                   重投影误差的阈值vbGood                          标记成功三角化点?parallax                        计算出来的比较大的视差角(注意不是最大,具体看后面代码)return int*/
int Initializer::CheckRT(const cv::Mat &R, const cv::Mat &t, const vector<cv::KeyPoint> &vKeys1, const vector<cv::KeyPoint> &vKeys2,const vector<Match> &vMatches12, vector<bool> &vbMatchesInliers,const cv::Mat &K, vector<cv::Point3f> &vP3D, float th2, vector<bool> &vbGood, float &parallax)
{   // 对给出的特征点对及其R t , 通过三角化检查解的有效性,也称为 cheirality check// Calibration parameters//从相机内参数矩阵获取相机的校正参数const float fx = K.at<float>(0,0);const float fy = K.at<float>(1,1);const float cx = K.at<float>(0,2);const float cy = K.at<float>(1,2);//特征点是否是good点的标记,这里的特征点指的是参考帧中的特征点vbGood = vector<bool>(vKeys1.size(),false);//重设存储空间坐标的点的大小vP3D.resize(vKeys1.size());//存储计算出来的每对特征点的视差vector<float> vCosParallax;vCosParallax.reserve(vKeys1.size());// Camera 1 Projection Matrix K[I|0]// Step 1:计算相机的投影矩阵  // 投影矩阵P是一个 3x4 的矩阵,可以将空间中的一个点投影到平面上,获得其平面坐标,这里均指的是齐次坐标。// 对于第一个相机是 P1=K*[I|0]// 以第一个相机的光心作为世界坐标系, 定义相机的投影矩阵cv::Mat P1(3,4,				//矩阵的大小是3x4CV_32F,			//数据类型是浮点数cv::Scalar(0));	//初始的数值是0//将整个K矩阵拷贝到P1矩阵的左侧3x3矩阵,因为 K*I = KK.copyTo(P1.rowRange(0,3).colRange(0,3));// 第一个相机的光心设置为世界坐标系下的原点cv::Mat O1 = cv::Mat::zeros(3,1,CV_32F);// Camera 2 Projection Matrix K[R|t]// 计算第二个相机的投影矩阵 P2=K*[R|t]cv::Mat P2(3,4,CV_32F);R.copyTo(P2.rowRange(0,3).colRange(0,3));t.copyTo(P2.rowRange(0,3).col(3));//最终结果是K*[R|t]P2 = K*P2;// 第二个相机的光心在世界坐标系下的坐标cv::Mat O2 = -R.t()*t;//在遍历开始前,先将good点计数设置为0int nGood=0;// 开始遍历所有的特征点对for(size_t i=0, iend=vMatches12.size();i<iend;i++){// 跳过outliersif(!vbMatchesInliers[i])continue;// Step 2 获取特征点对,调用Triangulate() 函数进行三角化,得到三角化测量之后的3D点坐标// kp1和kp2是匹配好的有效特征点const cv::KeyPoint &kp1 = vKeys1[vMatches12[i].first];const cv::KeyPoint &kp2 = vKeys2[vMatches12[i].second];//存储三维点的的坐标cv::Mat p3dC1;// 利用三角法恢复三维点p3dC1Triangulate(kp1,kp2,	//特征点P1,P2,		//投影矩阵p3dC1);		//输出,三角化测量之后特征点的空间坐标		// Step 3 第一关:检查三角化的三维点坐标是否合法(非无穷值)// 只要三角测量的结果中有一个是无穷大的就说明三角化失败,跳过对当前点的处理,进行下一对特征点的遍历 if(!isfinite(p3dC1.at<float>(0)) || !isfinite(p3dC1.at<float>(1)) || !isfinite(p3dC1.at<float>(2))){//其实这里就算是不这样写也没问题,因为默认的匹配点对就不是good点vbGood[vMatches12[i].first]=false;//继续对下一对匹配点的处理continue;}// Check parallax// Step 4 第二关:通过三维点深度值正负、两相机光心视差角大小来检查是否合法 //得到向量PO1cv::Mat normal1 = p3dC1 - O1;//求取模长,其实就是距离float dist1 = cv::norm(normal1);//同理构造向量PO2cv::Mat normal2 = p3dC1 - O2;//求模长float dist2 = cv::norm(normal2);//根据公式:a.*b=|a||b|cos_theta 可以推导出来下面的式子float cosParallax = normal1.dot(normal2)/(dist1*dist2);// Check depth in front of first camera (only if enough parallax, as "infinite" points can easily go to negative depth)// 如果深度值为负值,为非法三维点跳过该匹配点对// ?视差比较小时,重投影误差比较大。这里0.99998 对应的角度为0.36°,这里不应该是 cosParallax>0.99998 吗?// ?因为后面判断vbGood 点时的条件也是 cosParallax<0.99998 // !可能导致初始化不稳定if(p3dC1.at<float>(2)<=0 && cosParallax<0.99998)continue;// Check depth in front of second camera (only if enough parallax, as "infinite" points can easily go to negative depth)// 讲空间点p3dC1变换到第2个相机坐标系下变为p3dC2cv::Mat p3dC2 = R*p3dC1+t;	//判断过程和上面的相同if(p3dC2.at<float>(2)<=0 && cosParallax<0.99998)continue;// Step 5 第三关:计算空间点在参考帧和当前帧上的重投影误差,如果大于阈值则舍弃// Check reprojection error in first image// 计算3D点在第一个图像上的投影误差//投影到参考帧图像上的点的坐标x,yfloat im1x, im1y;//这个使能空间点的z坐标的倒数float invZ1 = 1.0/p3dC1.at<float>(2);//投影到参考帧图像上。因为参考帧下的相机坐标系和世界坐标系重合,因此这里就直接进行投影就可以了im1x = fx*p3dC1.at<float>(0)*invZ1+cx;im1y = fy*p3dC1.at<float>(1)*invZ1+cy;//参考帧上的重投影误差,这个的确就是按照定义来的float squareError1 = (im1x-kp1.pt.x)*(im1x-kp1.pt.x)+(im1y-kp1.pt.y)*(im1y-kp1.pt.y);// 重投影误差太大,跳过淘汰if(squareError1>th2)continue;// Check reprojection error in second image// 计算3D点在第二个图像上的投影误差,计算过程和第一个图像类似float im2x, im2y;// 注意这里的p3dC2已经是第二个相机坐标系下的三维点了float invZ2 = 1.0/p3dC2.at<float>(2);im2x = fx*p3dC2.at<float>(0)*invZ2+cx;im2y = fy*p3dC2.at<float>(1)*invZ2+cy;// 计算重投影误差float squareError2 = (im2x-kp2.pt.x)*(im2x-kp2.pt.x)+(im2y-kp2.pt.y)*(im2y-kp2.pt.y);// 重投影误差太大,跳过淘汰if(squareError2>th2)continue;// Step 6 统计经过检验的3D点个数,记录3D点视差角 // 如果运行到这里就说明当前遍历的这个特征点对靠谱,经过了重重检验,说明是一个合格的点,称之为good点 vCosParallax.push_back(cosParallax);//存储这个三角化测量后的3D点在世界坐标系下的坐标vP3D[vMatches12[i].first] = cv::Point3f(p3dC1.at<float>(0),p3dC1.at<float>(1),p3dC1.at<float>(2));//good点计数++nGood++;//判断视差角,只有视差角稍稍大一丢丢的才会给打good点标记//? bug 我觉得这个写的位置不太对。你的good点计数都++了然后才判断,不是会让good点标志和good点计数不一样吗if(cosParallax<0.99998)vbGood[vMatches12[i].first]=true;}// Step 7 得到3D点中较小的视差角,并且转换成为角度制表示if(nGood>0){// 从小到大排序,注意vCosParallax值越大,视差越小sort(vCosParallax.begin(),vCosParallax.end());// !排序后并没有取最小的视差角,而是取一个较小的视差角// 作者的做法:如果经过检验过后的有效3D点小于50个,那么就取最后那个最小的视差角(cos值最大)// 如果大于50个,就取排名第50个的较小的视差角即可,为了避免3D点太多时出现太小的视差角 size_t idx = min(50,int(vCosParallax.size()-1));//将这个选中的角弧度制转换为角度制parallax = acos(vCosParallax[idx])*180/CV_PI;}else//如果没有good点那么这个就直接设置为0了parallax=0;//返回good点计数return nGood;
}

结束语

以上就是我学习到的内容,如果对您有帮助请多多支持我,如果哪里有问题欢迎大家在评论区积极讨论,我看到会及时回复。 

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

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

相关文章

macOS如何进入 Application Support 目录(cd: string not in pwd: Application)

错误信息 cd: string not in pwd: Application 表示在当前目录下找不到名为 Application Support 的目录。可能的原因如下&#xff1a; 拼写错误或路径错误&#xff1a;确保你输入的目录名称正确。目录名称是区分大小写的&#xff0c;因此请确保使用正确的大小写。正确的目录名…

记录一个连不上docker中的mysql的问题

引言 使用的debian12,不同发行版可能有些许差异&#xff0c;连接使用的工具是navicat lite 本来是毫无思绪的&#xff0c;以前在云服务器上可能是防火墙的问题&#xff0c;但是这个桌面环境我压根没有使用防火墙。 直到 ying192:~$ mysql -h127.0.0.1 -uroot ERROR 1045 (28…

Gradle自定义任务指南 —— 释放构建脚本的无限可能

文章目录 &#x1f50d;Gradle任务⚙️ 自定义任务的5大核心配置项1. 任务注册&#xff08;Registering Tasks&#xff09;2. group & description3. dependsOn4. inputs & outputs5. 类型化任务&#xff08;Task Types&#xff09; 任务常见配置参数传递方式1&#xf…

windows11关闭系统更新详细操作步骤

文章目录 1.打开注册表2.修改注册表内容2.1 新建文件2.2 修改值 3.修改设置 1.打开注册表 winR输入regedit(如下图所示) 2.修改注册表内容 进HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 2.1 新建文件 右侧界面右键即可 2.2 修改值 重命名为如下…

matlab绘图——彩色螺旋图

代码生成的图形是一个动态的彩色螺旋&#xff0c;展示了如何利用极坐标和颜色映射创建视觉吸引力强的图形。该图形可以用于数据可视化、艺术创作或数学演示&#xff0c;展示了 MATLAB 在图形处理方面的强大能力。通过调整 theta 和 r 的范围&#xff0c;可以创建出不同形状和复…

啥是EPS?

文章目录 1. 什么是EPS?2. 主要构成3. EPS的设计如何符合功能安全?4. 代表性的厂家1. 什么是EPS? EPS(Electric Power Steering,电动助力转向系统)是一种利用电动机提供转向助力的系统,取代了传统的液压助力转向系统(HPS)。EPS通过传感器检测驾驶员的转向意图,并由电…

QT:控件属性及常用控件(3)-----输入类控件(正则表达式)

输入类控件既可以进行显示&#xff0c;也能让用户输入一些内容&#xff01; 文章目录 1.Line Edit1.1 用户输入个人信息1.2 基于正则表达式的文本限制1.3 验证两次输入的密码是否一致1.4 让输入的密码可以被查看 2.Text Edit2.1 输入和显示同步2.1 其他信号出发情况 3.ComboBox…

24_游戏启动逻辑梳理总结

首先这个项目从游戏根入口GameRoot.cs的初始化开始 分为 服务层初始化Svc.cs 与 业务系统层初始化Sys.cs 而服务层 分为 资源加载服务层ResSvc.cs 与 音乐播放服务层AudioSvc.cs 而在 资源加载服务层ResSvc.cs中 初始化了 名字的 配置文件 而音乐播放服务层AudioSvc.cs 暂时没…

【25考研】中科院软件考研复试难度分析!

中科院软件复试不需要上机&#xff01;且对专业综合能力要求较高&#xff01;提醒同学一定要认真复习&#xff01; 一、复试内容 二、参考书目 官方并未明确给出&#xff0c;建议同学参考初试书目&#xff1a; 1&#xff09;《数据结构&#xff08;C语言版&#xff09;》严蔚…

大华相机DH-IPC-HFW3237M支持的ONVIF协议

使用libONVIF C库。 先发现相机。 配置 lib目录 包含 编译提示缺的文件&#xff0c;到libonvif里面拷贝过来。 改UDP端口 代码 使用msvc 2022的向导生成空项目&#xff0c;从项目的main示例拷贝过来。 CameraOnvif.h #pragma once#include <QObject> #include &l…

16.好数python解法——2024年省赛蓝桥杯真题

问题描述 一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位…)上的数字是奇数,偶数位(十位、千位、十万位…)上的数字是偶数,我们就称之为“好数”。 给定一个正整数N,请计算从1到N一共有多少个好数。 输入格式 一个整数N。 输出格式 一个整数代表答案。 样例输入 1 …

Vue3.5 企业级管理系统实战(三):页面布局及样式处理 (Scss UnoCSS )

本章主要是关于整体页面布局及样式处理&#xff0c;在进行这一章代码前&#xff0c;先将前两章中的示例代码部分删除&#xff08;如Home.vue、About.vue、counter.ts、App.vue中引用等&#xff09; 1 整体页面布局 页面整体布局构成了产品的框架基础&#xff0c;通常涵盖主导…

SQL调优讨论

说明&#xff1a;狭义的SQL调优&#xff0c;指对慢SQL&#xff08;一般是Select语句&#xff0c;或包含Select的语句&#xff09;优化&#xff0c;在不改变查询结果的情况下提高SQL执行效率。广义上的SQL调优&#xff0c;指对某个慢查询优化&#xff0c;通过一些类操作提供查询…

Django基础之ORM

一.前言 上一节简单的讲了一下orm&#xff0c;主要还是做个了解&#xff0c;这一节将和大家介绍更加细致的orm&#xff0c;以及他们的用法&#xff0c;到最后再和大家说一下cookie和session&#xff0c;就结束了全部的django基础部分 二.orm的基本操作 1.settings.py&#x…

PageView组件的功能和用法

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了如何屏蔽事件关的内容,本章回中将介绍PageView Widget.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在这里介绍的PageView是指左右滑动或者上下滑动显示不同的页面&#xff0c;Flutter把它…

Flutter:自定义Tab切换,订单列表页tab,tab吸顶

1、自定义tab切换 view <Widget>[// 好评<Widget>[TDImage(assetUrl: assets/img/order4.png,width: 36.w,height: 36.w,),SizedBox(width: 10.w,),TextWidget.body(好评,size: 24.sp,color: controller.tabIndex 0 ? AppTheme.colorfff : AppTheme.color999,),]…

论文笔记(六十三)Understanding Diffusion Models: A Unified Perspective(一)

Understanding Diffusion Models: A Unified Perspective&#xff08;一&#xff09; 文章概括引言&#xff1a;生成模型背景&#xff1a;ELBO、VAE 和分层 VAE证据下界&#xff08;Evidence Lower Bound&#xff09;变分自编码器 &#xff08;Variational Autoencoders&#x…

QT6 + CMAKE编译OPENCV3.9

参考文档 [1] https://blog.csdn.net/rjkf_css/article/details/135676077 前提条件 配置好相关运行环境&#xff1a;QT6、OPENCV3.9的sources文件 OPENCV下载网页&#xff1a;https://opencv.org/releases/ QT6下载教程&#xff1a;https://blog.csdn.net/caoshangpa/article…

Zemax 非序列模式下的颜色检测器和颜色混合

在 Zemax 的非序列模式中&#xff0c;探测器用于捕获系统中射线的信息。可以使用各种类型的探测器来捕获光学系统性能的不同方面&#xff0c;例如矩形探测器&#xff0c;它存储撞击它的 NSC 源射线的能量数据。 另一种经常使用的探测器类型是 Detector Color&#xff0c;它是一…

金融级分布式数据库如何优化?PawSQL发布OceanBase专项调优指南

前言 OceanBase数据库作为国产自主可控的分布式数据库&#xff0c;在金融、电商、政务等领域得到广泛应用&#xff0c;优化OceanBase数据库的查询性能变得愈发重要。PawSQL为OceanBase数据库提供了全方位的SQL性能优化支持&#xff0c;助力用户充分发挥OceanBase数据库的性能潜…