ORB-SLAM2源码笔记(4)——帧Frame和关键帧KeyFrame

article/2025/4/23 3:04:39

Frame类中的相机参数为static类型,表示所有Frame对象共享一份相机参数

特征点提取ExtractORB

Frame类构造函数中调用成员变量mpORBextractorLeftmpORBextractorRight()运算符进行特征点提取.

畸变矫正前的左目特征点是mvKeys[i].

畸变矫正后的左目特征点是mvKeysUn[i].

在右目图片中对应特征点的横坐标为mvuRight[i],纵坐标与mvKeys[i]的纵坐标相同.

特征点的深度是mvDepth[i].

void Frame::ExtractORB(int flag, const cv::Mat &im) {if (flag == 0)		// flag==0, 表示对左图提取ORB特征点(*mpORBextractorLeft)(im, cv::Mat(), mvKeys, mDescriptors);else				// flag==1, 表示对右图提取ORB特征点(*mpORBextractorRight)(im, cv::Mat(), mvKeysRight, mDescriptorsRight);
}

定义函数ExtractORB,调用通过ORBextractor创建出来的对象mpORBextractorLeft和mpORBextractorRight进行特征提取。

  • 对于双目相机,通过双目特征点匹配关系计算特征点的深度值.
  • 对于RGBD相机,根据特征点深度构造虚拟的右目图像特征点.

通过这种预处理,在后面SLAM系统中不再区分双目特征点和RGBD特征点,它们以双目特征点的形式被处理.(仅通过判断mvuRight[idx]判断某特征点是否有深度) 

int ORBmatcher::SearchByProjection(Frame &F, const vector<MapPoint *> &vpMapPoints, const float th) {// ...for (size_t idx : vIndices) {if (F.mvuRight[idx] > 0) {		// 通过判断 mvuRight[idx] 判断该特征点是否有深度// 针对有深度的特征点特殊处理} else {// 针对单目特征点的特殊处理}}// ...
}

双目特征点匹配

粗匹配: 根据特征点描述子距离和金字塔层级判断匹配.粗匹配关系是按行寻找的,对于左目图像中每个特征点,在右目图像对应行上寻找匹配特征点.
精匹配: 根据特征点周围窗口内容相似度判断匹配.
亚像素插值: 将特征点相似度与匹配坐标之间拟合成二次曲线,寻找最佳匹配位置(得到的是一个小数).
记录右目匹配mvuRight和深度mvDepth信息.
离群点筛选: 以平均相似度的2.1倍为标准,筛选离群点.

 

 

void Frame::ComputeStereoMatches() {mvuRight = vector<float>(N, -1.0f);mvDepth = vector<float>(N, -1.0f);// step0. 右目图像特征点逐行统计: 将右目图像中每个特征点注册到附近几行上vector<vector<size_t> > vRowIndices(nRows, vector<size_t>());	// 图像每行的1右目特征点索引for (int iR = 0; iR < mvKeysRight.size(); iR++) {const cv::KeyPoint &kp = mvKeysRight[iR];const float &kpY = kp.pt.y;const int maxr = ceil(kpY + 2.0f * mvScaleFactors[mvKeysRight[iR].octave]);const int minr = floor(kpY - 2.0f * mvScaleFactors[mvKeysRight[iR].octave]);for (int yi = minr; yi <= maxr; yi++)vRowIndices[yi].push_back(iR);}// step1. + 2. 粗匹配+精匹配const float minZ = mb, minD = 0, maxD = mbf / minZ;		// 根据视差公式计算两个特征点匹配搜索的范围const int thOrbDist = (ORBmatcher::TH_HIGH + ORBmatcher::TH_LOW) / 2;vector<pair<int, int> > vDistIdx;		// 保存特征点匹配for (int iL = 0; iL < N; iL++) {const cv::KeyPoint &kpL = mvKeys[iL];const int &levelL = kpL.octave;const float &vL = kpL.pt.y, &uL = kpL.pt.x;const vector<size_t> &vCandidates = vRowIndices[vL];if (vCandidates.empty()) continue;// step1. 粗匹配,根据特征点描述子和金字塔层级进行粗匹配int bestDist = ORBmatcher::TH_HIGH;size_t bestIdxR = 0;const cv::Mat &dL = mDescriptors.row(iL);for (size_t iC = 0; iC < vCandidates.size(); iC++) {const size_t iR = vCandidates[iC];const cv::KeyPoint &kpR = mvKeysRight[iR];if (kpR.octave < levelL - 1 || kpR.octave > levelL + 1)continue;const float &uR = kpR.pt.x;if (uR >= minU && uR <= maxU) {const cv::Mat &dR = mDescriptorsRight.row(iR);const int dist = ORBmatcher::DescriptorDistance(dL, dR);if (dist < bestDist) {bestDist = dist;bestIdxR = iR;}}}// step2. 精匹配: 滑动窗口匹配,根据匹配点周围5✖5窗口寻找精确匹配if (bestDist < thOrbDist) {const float uR0 = mvKeysRight[bestIdxR].pt.x;const float scaleFactor = mvInvScaleFactors[kpL.octave];const float scaleduL = round(kpL.pt.x * scaleFactor);const float scaledvL = round(kpL.pt.y * scaleFactor);const float scaleduR0 = round(uR0 * scaleFactor);const int w = 5;cv::Mat IL = mpORBextractorLeft->mvImagePyramid[kpL.octave].rowRange(scaledvL - w, scaledvL + w + 1).colRange(scaleduL - w, scaleduL + w + 1);IL.convertTo(IL, CV_32F);IL = IL - IL.at<float>(w, w) * cv::Mat::ones(IL.rows, IL.cols, CV_32F);int bestDist = INT_MAX;int bestincR = 0;const int L = 5;vector<float> vDists;vDists.resize(2 * L + 1);const float iniu = scaleduR0 + L - w;const float endu = scaleduR0 + L + w + 1;for (int incR = -L; incR <= +L; incR++) {cv::Mat IR = mpORBextractorRight->mvImagePyramid[kpL.octave].rowRange(scaledvL - w, scaledvL + w + 1).colRange(scaleduR0 + incR - w, scaleduR0 + incR + w + 1);IR.convertTo(IR, CV_32F);IR = IR - IR.at<float>(w, w) * cv::Mat::ones(IR.rows, IR.cols, CV_32F);float dist = cv::norm(IL, IR, cv::NORM_L1);if (dist < bestDist) {bestDist = dist;bestincR = incR;}vDists[L + incR] = dist;}// step3. 亚像素插值: 将特征点匹配距离拟合成二次曲线,寻找二次曲线最低点(是一个小数)作为最优匹配点坐标const float dist1 = vDists[L + bestincR - 1];const float dist2 = vDists[L + bestincR];const float dist3 = vDists[L + bestincR + 1];const float deltaR = (dist1 - dist3) / (2.0f * (dist1 + dist3 - 2.0f * dist2));// step4. 记录特征点的右目和深度信息float bestuR = mvScaleFactors[kpL.octave] * ((float) scaleduR0 + (float) bestincR + deltaR);float disparity = (uL - bestuR);if (disparity >= minD && disparity < maxD) {mvDepth[iL] = mbf / disparity;mvuRight[iL] = bestuR;vDistIdx.push_back(pair<int, int>(bestDist, iL));}}}// step5. 删除离群点: 匹配距离大于平均匹配距离2.1倍的视为误匹配sort(vDistIdx.begin(), vDistIdx.end());const float median = vDistIdx[vDistIdx.size() / 2].first;const float thDist = 1.5f * 1.4f * median;for (int i = vDistIdx.size() - 1; i >= 0; i--) {if (vDistIdx[i].first < thDist)break;else {mvuRight[vDistIdx[i].second] = -1;mvDepth[vDistIdx[i].second] = -1;}}
}

对于RGBD特征,根据深度信息构造虚拟右目图像。

特征点分配AssigenFeaturesToGrid()

在对特征点进行预处理后,将特征点分配到4864列的网格中以加速匹配

对于双目和RGBD相机,分别执行以下Frame构造函数

// 双目相机Frame构造函数
Frame::Frame(const cv::Mat &imLeft, const cv::Mat &imRight, const double &timeStamp, ORBextractor *extractorLeft, ORBextractor *extractorRight, ORBVocabulary *voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth): mpORBvocabulary(voc), mpORBextractorLeft(extractorLeft), mpORBextractorRight(extractorRight), mTimeStamp(timeStamp), mK(K.clone()), mDistCoef(distCoef.clone()), mbf(bf), mThDepth(thDepth), mpReferenceKF(static_cast<KeyFrame *>(NULL)) {// step0. 帧ID自增mnId = nNextId++;// step1. 计算金字塔参数mnScaleLevels = mpORBextractorLeft->GetLevels();mfScaleFactor = mpORBextractorLeft->GetScaleFactor();mfLogScaleFactor = log(mfScaleFactor);mvScaleFactors = mpORBextractorLeft->GetScaleFactors();mvInvScaleFactors = mpORBextractorLeft->GetInverseScaleFactors();mvLevelSigma2 = mpORBextractorLeft->GetScaleSigmaSquares();mvInvLevelSigma2 = mpORBextractorLeft->GetInverseScaleSigmaSquares();// step2. 提取双目图像特征点thread threadLeft(&Frame::ExtractORB, this, 0, imLeft);thread threadRight(&Frame::ExtractORB, this, 1, imRight);threadLeft.join();threadRight.join();N = mvKeys.size();if (mvKeys.empty())return;// step3. 畸变矫正,实际上UndistortKeyPoints()不对双目图像进行矫正UndistortKeyPoints();// step4. 双目图像特征点匹配ComputeStereoMatches();// step5. 第一次调用构造函数时计算static变量if (mbInitialComputations) {ComputeImageBounds(imLeft);mfGridElementWidthInv = static_cast<float>(FRAME_GRID_COLS) / static_cast<float>(mnMaxX - mnMinX);mfGridElementHeightInv = static_cast<float>(FRAME_GRID_ROWS) / static_cast<float>(mnMaxY - mnMinY);fx = K.at<float>(0, 0);fy = K.at<float>(1, 1);cx = K.at<float>(0, 2);cy = K.at<float>(1, 2);invfx = 1.0f / fx;invfy = 1.0f / fy;// 计算完成,标志复位mbInitialComputations = false;}mvpMapPoints = vector<MapPoint *>(N, static_cast<MapPoint *>(NULL));	// 初始化本帧的地图点mvbOutlier = vector<bool>(N, false);	// 标记当前帧的地图点不是外点mb = mbf / fx;		// 计算双目基线长度// step6. 将特征点分配到网格中AssignFeaturesToGrid();
}
// RGBD相机Frame构造函数
Frame::Frame(const cv::Mat &imGray, const cv::Mat &imDepth, const double &timeStamp, ORBextractor *extractor, ORBVocabulary *voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth): mpORBvocabulary(voc), mpORBextractorLeft(extractor), mpORBextractorRight(static_cast<ORBextractor *>(NULL)), mTimeStamp(timeStamp), mK(K.clone()), mDistCoef(distCoef.clone()), mbf(bf), mThDepth(thDepth) {// step0. 帧ID自增mnId = nNextId++;// step1. 计算金字塔参数mnScaleLevels = mpORBextractorLeft->GetLevels();mfScaleFactor = mpORBextractorLeft->GetScaleFactor();mfLogScaleFactor = log(mfScaleFactor);mvScaleFactors = mpORBextractorLeft->GetScaleFactors();mvInvScaleFactors = mpORBextractorLeft->GetInverseScaleFactors();mvLevelSigma2 = mpORBextractorLeft->GetScaleSigmaSquares();mvInvLevelSigma2 = mpORBextractorLeft->GetInverseScaleSigmaSquares();// step2. 提取左目图像特征点ExtractORB(0, imGray);N = mvKeys.size();if (mvKeys.empty())return;// step3. 畸变矫正UndistortKeyPoints();// step4. 根据深度信息构造虚拟右目图像ComputeStereoFromRGBD(imDepth);mvpMapPoints = vector<MapPoint *>(N, static_cast<MapPoint *>(NULL));mvbOutlier = vector<bool>(N, false);// step5. 第一次调用构造函数时计算static变量if (mbInitialComputations) {ComputeImageBounds(imLeft);mfGridElementWidthInv = static_cast<float>(FRAME_GRID_COLS) / static_cast<float>(mnMaxX - mnMinX);mfGridElementHeightInv = static_cast<float>(FRAME_GRID_ROWS) / static_cast<float>(mnMaxY - mnMinY);fx = K.at<float>(0, 0);fy = K.at<float>(1, 1);cx = K.at<float>(0, 2);cy = K.at<float>(1, 2);invfx = 1.0f / fx;invfy = 1.0f / fy;// 计算完成,标志复位mbInitialComputations = false;}mvpMapPoints = vector<MapPoint *>(N, static_cast<MapPoint *>(NULL));	// 初始化本帧的地图点mvbOutlier = vector<bool>(N, false);	// 标记当前帧的地图点不是外点mb = mbf / fx;		// 计算双目基线长度// step6. 将特征点分配到网格中AssignFeaturesToGrid();
}

Tracking线程每收到一帧图像,就调用函数Tracking::GrabImageMonocular()Tracking::GrabImageStereo()Tracking::GrabImageRGBD()创建一个Frame对象,赋值给mCurrentFrame.

函数跟踪结束后,会将mCurrentFrame赋值给mLastFrame

关键帧KeyFrame 

​​​​​​ORB-SLAM2代码详解05: 关键帧KeyFrame_ncepu_Chen的博客-CSDN博客_slam 关键帧 

 能看到同一地图点的两关键帧之间存在共视关系,共视地图点的数量被称为权重mConnectedKeyFrameWeights记录了当前关键帧的共视关键帧及权重

mvpOrderedConnectedKeyFrames记录了所有共视关键帧,按权重从大到小排序

mvOrderedWeights记录了所有共视权重,按从大到小排序

基于当前关键帧对地图点的观测构造共视图UpdateConnections()

void KeyFrame::UpdateConnections() {// 1. 通过遍历当前帧地图点获取其与其它关键帧的共视程度,存入变量KFcounter中vector<MapPoint *> vpMP;{unique_lock<mutex> lockMPs(mMutexFeatures);vpMP = mvpMapPoints;}map<KeyFrame *, int> KFcounter; for (MapPoint *pMP : vpMP) {map<KeyFrame *, size_t> observations = pMP->GetObservations();for (map<KeyFrame *, size_t>::iterator mit = observations.begin(); mit != observations.end(); mit++) {if (mit->first->mnId == mnId)		// 与当前关键帧本身不算共视continue;KFcounter[mit->first]++;}}// step2. 找到与当前关键帧共视程度超过15的关键帧,存入变量vPairs中vector<pair<int, KeyFrame *> > vPairs;int th = 15;int nmax = 0;KeyFrame *pKFmax = NULL;   for (map<KeyFrame *, int>::iterator mit = KFcounter.begin(), mend = KFcounter.end(); mit != mend; mit++) {if (mit->second > nmax) {nmax = mit->second;pKFmax = mit->first;}if (mit->second >= th) {vPairs.push_back(make_pair(mit->second, mit->first));(mit->first)->AddConnection(this, mit->second);				// 对超过阈值的共视边建立连接}}//  step3. 对关键帧按照共视权重降序排序,存入变量mvpOrderedConnectedKeyFrames和mvOrderedWeights中sort(vPairs.begin(), vPairs.end());list<KeyFrame *> lKFs;list<int> lWs;for (size_t i = 0; i < vPairs.size(); i++) {lKFs.push_front(vPairs[i].second);lWs.push_front(vPairs[i].first);}{unique_lock<mutex> lockCon(mMutexConnections);mConnectedKeyFrameWeights = KFcounter;mvpOrderedConnectedKeyFrames = vector<KeyFrame *>(lKFs.begin(), lKFs.end());mvOrderedWeights = vector<int>(lWs.begin(), lWs.end());// step4. 对于第一次加入生成树的关键帧,取共视程度最高的关键帧为父关键帧if (mbFirstConnection && mnId != 0) {mpParent = mvpOrderedConnectedKeyFrames.front();mpParent->AddChild(this);mbFirstConnection = false;}}
}

当关键帧和地图点的连接关系发生变化,UpdateConnections()就会被调用

生成树mpParent、mspChildrens

在ORB-SLAM2中,保存所有关键帧构成的最小生成树(优先选择权重大的边作为生成树的边),在回环闭合时只需对最小生成树做BA优化就能以最小代价优化所有关键帧和地图点的位姿,相比于优化共视图大大减少了计算量

 新关键帧的父关键帧会被设为其共视程度最高的共视关键帧

void KeyFrame::UpdateConnections() {// 更新共视图信息// ...// 更新关键帧信息: 对于第一次加入生成树的关键帧,取共视程度最高的关键帧为父关键帧// 该操作会改变当前关键帧的成员变量mpParent和父关键帧的成员变量mspChildrensunique_lock<mutex> lockCon(mMutexConnections);if (mbFirstConnection && mnId != 0) {mpParent = mvpOrderedConnectedKeyFrames.front();mpParent->AddChild(this);mbFirstConnection = false;}
}

KeyFrame的删除过程也采取先标记再清除的方式,参与回环检测的关键帧具有不被删除的特权

当一个关键帧被删除时,其父关键帧所有子关键帧的生成树信息也会受到影响,需要为其所有子关键帧寻找新的父关键帧,如果父关键帧找的不好的话,就会产生回环,导致生成树就断开.

采用类似于最小生成树算法中的加边法重新构建生成树结构: 每次循环取权重最高的候选边建立父子连接关系,并将新加入生成树的子节点到加入候选父节点集合sParentCandidates

在回环检测中回环矫正函数在调用本质图BA优化前会先添加当前关键帧和闭环匹配关键帧之间的回环关系。

 


http://chatgpt.dhexx.cn/article/PAnQKdMd.shtml

相关文章

《UnityAPI.Keyframe关键帧》(Yanlz+Unity+SteamVR+云技术+5G+AI+VR云游戏+Keyframe+inTangent+outTangent+立钻哥哥++OK++)

《UnityAPI.Keyframe关键帧》 版本 作者 参与者 完成日期 备注 UnityAPI_Keyframe_V01_1.0 严立钻 2020.06.28 #《UnityAPI.Keyframe关键帧》发布说明&#xff1a; “UnityAPI.Keyframe关键帧”是对UnityAPI中Keyframe关键帧类的剖析和拓展&…

ORB-SLAM2算法10之图像关键帧KeyFrame

文章目录 0 引言1 KeyFrame类1.1 构造函数1.2 成员函数1.3 关键帧之间共视图1.3.1 AddConnection1.3.2 UpdateBestCovisibles1.3.3 UpdateConnections1.3.4 EraseConnection1.3.5 SetBadFlag 1.4 地图点1.5 生成树 2 KeyFrame用途 0 引言 ORB-SLAM2算法7详细了解了System主类和…

CSS3 @keyframe动画的基本用法与常见错误用法

前言 随着CSS3的推出与普及&#xff0c;其各种属性开始被广泛使用。尤其是其动画功能&#xff0c;对于一些简单的动画实现&#xff0c;实在没必要用Javascript去实现&#xff0c;这是keyframes动画就派上了用场。今天来讲一下keyframes的一些基本的用法和常见坑。 【本文志于…

【微信小程序】动画入门keyframe

【微信小程序—动画工坊】动画入门 前情 需要了解的前置知识&#xff1a; 子代选择器基本布局 分析 可以将任务进行一下拆分。 如何让小球跑动起来&#xff1f; 通过keyframe创造动画函数&#xff0c;然后再通过animation绑定创造动画函数 keyframe的百分比代表动画的进度…

ORB-SLAM2 --- KeyFrame::UpdateConnections 函数

目录 一、函数作用 二、函数流程 三、code 四、函数解析 一、函数作用 更新关键帧之间的连接图。 更新变量 mConnectedKeyFrameWeights&#xff1a;当前关键帧的共视信息&#xff0c;记录当前关键帧共视关键帧的信息&#xff08;哪一帧和当前关键帧有共视&#xff0c;共视…

三谈属性动画——Keyframe以及ViewPropertyAnimator

Android动画和Transition系列文章 初识属性动画——使用Animator创建动画再谈属性动画——介绍以及自定义Interpolator插值器三谈属性动画——Keyframe以及ViewPropertyAnimator让View具有减速效果的动画——FlingAnimation让View具有弹性效果的动画——SpringAnimation让View…

ORB-SLAM2 --- KeyFrame::SetBadFlag函数

目录 1.函数作用 2.code 3.函数解析 1.函数作用 真正地执行删除关键帧的操作。 需要删除的是该关键帧和其他所有帧、地图点之间的连接关系。 2.code void KeyFrame::SetBadFlag() { // Step 1 首先处理一下删除不了的特殊情况{unique_lock<mutex> lock(mMutexConn…

【视觉SLAM】Fast Relocalisation and Loop Closing in Keyframe-Based SLAM

See discussions, stats, and author profiles for this publication at: https://www.researchgate.net/publication/263621033 Article in Proceedings - IEEE International Conference on Robotics and Automation June 2014 DOI: 10.1109/ICRA.2014.6906953 先读Abstrac…

Android属性动画 Keyframe

转载请标明出处&#xff1a;http://blog.csdn.net/zhaoyanjun6/article/details/118963313 本文出自【赵彦军的博客】 文章目录 KeyFrame实战 KeyFrame KeyFrame 主要用于自定义控制动画速率&#xff0c;KeyFrame 直译过来就是关键帧。 而关键帧这个概念是从动画里学来的&…

ORB-SLAM2代码详解05: 关键帧KeyFrame

pdf版本笔记的下载地址: ORB-SLAM2代码详解05_关键帧KeyFrame,排版更美观一点,这个网站的默认排版太丑了&#xff08;访问密码&#xff1a;3834&#xff09; ORB-SLAM2代码详解05: 关键帧KeyFrame 各成员函数/变量共视图: mConnectedKeyFrameWeights基于对地图点的观测重新构造…

@keyframes详解

一、transform 和keyframes动画的区别&#xff1a; keyframes动画是循环的&#xff0c;而transform 只执行一遍. 二、keyframes CSS3中添加的新属性animation是用来为元素实现动画效果的&#xff0c;但是animation无法单独担当起实现动画的效果。承载动画的另一个属性——keyfr…

KeyFrame类

关键帧类主要是进行Covisbility Graph&#xff0c; Essential&#xff0c;Spanning Tree 三个图的维护&#xff0c;更新。 其中不涉及关键帧的筛选策略问题&#xff0c;只设置了剔除某关键帧和剔除关键帧后如何更新图的方法。总体来说&#xff0c;不难理解。 PS:本文设计多线程…

自定义控件三部曲之动画篇(八)——PropertyValuesHolder与Keyframe

前言&#xff1a;只有比牛人跑的更快&#xff0c;才有可能追上他的脚步。 相关文章&#xff1a; 《Android自定义控件三部曲文章索引》:http://blog.csdn.net/harvic880925/article/details/50995268 前几篇给大家讲了ValueAnimator、ObjectAnimator的知识&#xff0c;讲解了…

ORB-SLAM2从理论到代码实现(十四):KeyFrame类

1. 原理分析 KeyFrame为关键帧&#xff0c;关键帧之所以存在是因为优化需要&#xff0c;所以KeyFrame的几乎所有内容都是位优化服务的。该类中的函数较多&#xff0c;我们需要归类梳理一下&#xff0c;明白其功能原理&#xff0c;才能真正弄懂它的内容。 图优化需要构建节点和…

css基础(九)--keyframe

33.keyframe 关键帧&#xff0c;类似于flash中的关键帧&#xff0c;以keyframes开头紧跟着动画名称加上花括号&#xff5b;。。。&#xff5d;&#xff0c;括号中表示不同时间段样式规则 keyframes changecolor{ 0%{ background: red; } 100%{ background: green; } } 样式规…

windows10 企业版 ltsc系统的激活

具体步骤参考下面的网址内容&#xff1a; https://www.landiannews.com/archives/51131.html

win10哪个版本最好用,推荐win10企业版LTSC

win10企业版LTSC又被称为win10企业版2019长期服务版本&#xff0c;这个版本小编认为是目前最好用的win10版本,在win10企业版2016长期服务版本的基础上&#xff0c;微软做了大量优化和升级。win10企业版LTSC更加快捷和轻便。 现在很多网站上都是有人修改过的win10企业版LTSC安装…

一键解决Win10 LTSC 2021官方镜像存在的问题

一键解决Win10 LTSC 2021官方镜像存在的问题 由于适用了win10 ltsc 2021之后&#xff0c;发现官方镜像存在一些致命的bug。但是本人又喜欢这个官方精简的系统&#xff0c;所以进行了一些修复。并将搜集到的办法其汇总成一个一键修复脚本 Win10_LTSC_2021_FixPacks。来让其他用户…

Windows:MULTIPROCESSOR CONFIGURATION NOT SUPPORTED蓝屏(32位(win10/LTSC 2019/LTSC 2021))

网上的答案帮助不大&#xff0c;全靠摸索&#xff0c;记录一下 Content 1.环境2.案发现场(bushi3.解决方案 1.环境 所有32位win10操作系统应该都有这个问题&#xff08;旧版没装过&#xff09;&#xff0c;我的配置: CPU: i5 2400主板:戴尔DELL H61内存8G&#xff08;没必要关…

win10ltsc转版本,win10ltsc升级win11,无损

之前电脑有些卡&#xff0c;一时兴起&#xff0c;就装了比较精简的ltsc&#xff0c;一开始还挺好用。但后来用着用着发现确实少了很多东西&#xff0c;地图&#xff0c;相机&#xff0c;商店什么的都没了。后来又索性加装了一根内存条。 但是ltsc上的文件我又不想丢&#xff0…