ISP图像信号处理——白平衡校正和标定介绍以及C++实现

从数码相机直接输出的未经过处理过的RAW图到平常看到的JEPG图有一系列复杂的图像信号处理过程,称作ISP(Image Signal Processing)。这个过程会经过图像处理和压缩

参考文章1:http://t.csdn.cn/LvHH5

参考文章2:http://t.csdn.cn/c97t5

参考文章3:http://t.csdn.cn/UbAOu

http://t.csdn.cn/HuI67

参考文章4:http://t.csdn.cn/lwUAc

参考文章5:http://t.csdn.cn/HuI67

参考文章(下面整理的笔记):Understanding White Balance Control - 知乎 (zhihu.com)

人眼具有颜色恒常性,可以避免光源变化带来的颜色变化,但是图像传感器不具备这种特性,从而造成色偏,白平衡就是需要校正这个颜色的偏差。

颜色恒常性是指在照度发生变化的条件下人们对物体表面颜色的知觉趋于稳定的心理倾向。

色温描述的是具有一定表面温度的“黑体”(blackbody)的辐射光的光谱特性。简单的理解就是颜色随温度的变化规律,比如生铁就是黑色,加热会变成橘红色,继续加热到液态会呈现偏白的颜色,这种随温度而产生的颜色变化就光谱特性。

白平衡校正

  • 手动白平衡:在拍照前通过拍摄一个18度灰的卡片,然后计算出当时环境的白平衡增益值对后面的图片进行校正;

  • 自动白平衡:相机通过本身的算法,通过获取的图像自动计算出增益值对图像进行校正的方式。

AWB(Automatic White Balance),自动白平衡理解

为了将拍摄场景中的白色物体在显示时正确还原为白色,首先需要知道真实的白色物体在sensor RGB 空间中呈现什么颜色。常用的方法是通过实验标定标准白色在一些典型色温下呈现的sensor RGB 颜色,然后通过几个标定的色温点可以外推白色在所有可能色温下呈现的颜色,从而建立场景色温与sensor RGB 白色的对应关系,这个对应关系通常用白平衡增益来描述。

白平衡增益通常记为(R/G, B/G),即红色和蓝色相对于绿色的比例。目前对白平衡增益存在两种不同的定义:

1.一部分厂家将(R/G, B/G)定义为sensor捕捉到的图像中红色和蓝色的统计值,因此在高色温(如D65)下B/G大于R/G。

海思的光源的色温曲线(普朗克曲线)表现为下图所示的形状。

通过对不同sensor的色温曲线标定数据可知:在D50-D65之间 R/G、B/G的比值基本相近,相差不大。在低色温的时候,主要是G和B分量在改变,在高色温的时候主要是G和B分量在改变。

以海思的色温曲线为例:从直角双曲线的两个坐标方向来看,在D50-D65这个R/G、B/G为分界点,沿着R/G的方向看,最后应该会有一个B/G的饱和点。同理,沿B/G方向看,R/G也会有一个饱和点,饱和区域的时候其两个坐标方向上看应该呈现一条类似接近直线的曲线段。

或者也可以这么理解:

色温越低,R/G的比值越大,B/G的比值越小,当R/G达到某一阈值后,B/G则缓慢变小直至达到一个最小值而不再改变。

同理,色温越高,B/G的比值越大,R/G的比值越小,当B/G达到某一阈值后,R/G则缓慢变小直至达到一个最小值而不再改变。

直角双曲线靠近坐标的部分与坐标轴近似平行的直线段,比较符合色温曲线的变化规律。

根据G/R和G/B用直角双曲线函数拟合的图像和海思的普朗克曲线十分相似,如下图所示。

在这种定义下,D65光源下的白色具有较大的B/G统计值。

2.另一部分厂家则将(R/G, B/G)定义成为了使sensor捕捉的图像达到白平衡需要施加的增益系数,因此在高色温下B/G小于R/G。

在这种定义下,D65光源下的白色需要较大的R/G增益才能达到白平衡。

以R/G,B/G值代表增益系数,而非图像的统计值,在此定义下,白平衡标定的大致过程是:

  • 以标定好的若干个色温点(A, TL84, D50, D65, D75等)为核心可以拟合出一条色温曲线
  • 以色温曲线上的点为圆心,以一定半径画椭圆,可以得到一些列椭圆。
  • 所有椭圆所覆盖的(R/G,B/G)集合就认为是真实场景中的白色物体在全部色温下的可能值。不落在这个范围内的颜色不认为是白色。

某些特殊光源(如CWF)光谱特征偏离黑体光谱较大,因此需要单独标定。

一个好的白平衡算法需要能够检测出画面中存在的特殊场景并加以针对性的强化。点云分析是一种非常有效的提取图像特征的方法,但由于需要分析每一个像素的白平衡增益,所以计算量非常大。

理想的白平衡控制时序如下图所示,其基本流程是:

  1. 在第N帧图像结束时ISP硬件采集关于白平衡的统计信息
  2. 白平衡算法根据第N帧的统计数据预测第N+1帧的控制参数
  3. 摄像机固件在第N+1帧图像到达之前将白平衡控制参数写入ISP硬件寄存器
  4. 第N+1帧图像使用新的白平衡参数进行曝光

但是实际上由于两帧的时间间隔往往很小,不容易保证算法完成一系列的计算和配置,因此实际的白平衡控制往往采用隔帧生效的时序,其基本流程如下图所示

  1. 在第N帧图像结束时ISP硬件采集关于白平衡的统计信息
  2. 在第N+1帧开始后,白平衡算法根据第N帧的统计数据预测第N+2帧的控制参数,需要在第N+1帧结束前完成所有计算
  3. 摄像机固件在第N+2帧图像到达之前将新的白平衡控制参数写入ISP硬件寄存器
  4. 第N+2帧图像使用新的白平衡参数进行曝光

白平衡校正算法

1.灰度世界算法

基于一个假说:任一幅图像,当它有足够多的色彩变化,则它的RGB分量的均值会趋于相等。这是一个在自动白平衡方面应用极为广泛的理论。对此算法的流程如下:

  • 计算各个颜色通道的平均值;
  • 寻找一个参考值K,一般情况选取Gmean;
  • 计算Rgain = Gmean/Rmean, Bgain = Gmean/Bmean;
  • 对图像中的每个像素都乘以对应的gain值进行校正;
  • 以下C++代码,不知道本人缺少什么运行条件,在自己电脑上最后显示结果不太理想;大家也可以试试,该代码出自:http://t.csdn.cn/edydD
//自动白平衡  //灰度世界算法
void GrayWorldAlgorithm(Mat& src,Mat& dst)
{assert(3==src.channels());//求BGR分量均值auto mean = mean(src);//需要调整的BGR分量的增益float gain_B(0),gain_G(0),gain_R(0);float K = (mean[0]+mean[1]+mean[2])/3.0f;gain_B = K/mean[0];gain_G = K/mean[1];gain_R = K/mean[2];vector<Mat> channels;split(src,channels);//调整三个通道各自的值channels[0] = channels[0]*gain_B;channels[1] = channels[1]*gain_G;channels[2] = channels[2]*gain_R;//通道合并cv::merge(channels,dst);
}

下面的灰度世界法是本人自己根据理解写的,但是显示结果存疑。有点怀疑是不是BGR的赋值跟输入图像的拜尔分布有关,赋值顺序有误?有能力者找到错误的可以帮我纠出(感谢感谢):

//灰度世界法,输入三通道彩色图
Mat awbgray(Mat img_rgb8)
{Mat img_awb = Mat::zeros(height, width, CV_32FC3);Mat imgR = Mat::zeros(height, width, CV_8UC1);Mat imgG = Mat::zeros(height, width, CV_8UC1);Mat imgB = Mat::zeros(height, width, CV_8UC1);double Rsum=0, Gsum=0,Bsum=0;/*unsigned char* srcdata;unsigned char *dstdata;*/for (int row = 0; row < height; row++){//ptr得到行数据的头指针,得到row行指针/*uchar* data = img_awb.ptr<uchar>(row);*/Vec3b* inptr = img_rgb8.ptr<Vec3b>(row);for (int col = 0; col < width; col++){//BGGR分布?//imgB.at<Vec3b>(row, col)[0]   b通道/*uchar bdata = data[col * img_awb.channels() + 0];*/imgB.at<uchar>(row, col) = (*(inptr + col))[0];imgG.at<uchar>(row, col) = (*(inptr + col))[1];imgR.at<uchar>(row, col) = (*(inptr + col))[2];Bsum += imgB.at<uchar>(row, col);Gsum += imgG.at<uchar>(row, col);Rsum += imgR.at<uchar>(row, col);}}double Rmean=0, Gmean=0, Bmean = 0;Rmean = Rsum / (height * width);Gmean = Gsum / (height * width);Bmean = Bsum / (height * width);double K = (Rmean + Gmean + Bmean) / 3;cout << "Rmeanvalue:" << Rmean << endl;cout << "Gmeanvalue:" << Gmean << endl;cout << "Bmeanvalue:" << Bmean << endl;cout << "rgbmeanvalue:" << K << endl;double Rgain = K / Rmean;double Ggain = K / Gmean;double Bgain = K / Bmean;//重新调整计算RGB值for (int row = 0; row < height; row++){Vec3b* inptr = img_rgb8.ptr<Vec3b>(row);Vec3f* outptr = img_awb.ptr<Vec3f>(row);for (int col = 0; col < width; col++){(*(outptr + col))[2] = Rgain * (*(inptr + col))[2];(*(outptr + col))[1] = Ggain * (*(inptr + col))[1];(*(outptr + col))[0] = Bgain * (*(inptr + col))[0];}}//convertScaleAbs(img_awb, img_awb);//转为CV_8UC1/*imshow("img_awb", img_awb);waitKey(0);*/return img_awb;
}

该方法运行得到的结果,通过图像监视观察函数中的图像变化,放大可以查看像素值,没有在VS安装的可以自行安装Imagewatch,安装教程:VS2022安装Image Watch插件_image watch for visual studio 2022_Aqder的博客-CSDN博客

感觉处理后的结果不太理想,不知道是不是代码有误,可指出。

(左为输入,右为输出,不是一一对应的截图):

2.完美反射法

(perfect Reflector)基于这样一种假设,一幅图像中最亮的像素相当于物体有光泽或镜面上的点,它传达了很多关于场景照明条件的信息。如果景物中有纯白的部分,那么就可以直接从这些像素中提取出光源信息。因为镜面或有光泽的平面本身不吸收光线,所以其反射的颜色即为光源的真实颜色,这是因为镜面或有光泽的平面的反射比函数在很长的一段波长范围内是保持不变的。那么在这个假设下,图像中就一定存在一个纯白色的的像素或者最亮的点。

完美反射法就是利用这种特性来对图像进行调整。算法执行时,将待检测图像中亮度最高的像素作为参考白点,以此点为基础就可计算出gain值从而进行校正。完美反射算法流程如下:
  (1)遍历原始图像,统计RGB三通道之和的直方图;
  (2)遍历原始图像,找到RGB三通道各自的最大值Bmax、Gmax、Rmax
  (3)设定比例 r ,对RGB之和的直方图进行倒叙遍历,找到使白点像素个数超过总像素个数比例的阈值,T;
  (4)遍历原始图像,计算RGB之和大于 T 的像素,各个通道取平均,得到Bavg、Gavg、Ravg;
  (5)遍历原始图像,分别计算RGB三通道的调整值Aout=A / Aavg * Amax;
  (6)防溢出处理,这里可以采用简单的截断即可。

有看到其他博文资料不使用比例和阈值的完美反射法,但是运行结果和上面一样存疑。

设定比例r为10%,使用C++,代码如下:

​
//白平衡校正,完美反射法,使用比例r和阈值T,
Mat awbreflect2(Mat img_rgb8)
{int histrgbsum[255 * 3 + 1] = { 0 };double Rmax = 0, Gmax = 0, Bmax = 0;//uchar maxrgb[3] = { 0 };for (int row = 0; row < height; row++){const uchar* inptr = img_rgb8.ptr<uchar>(row);for (int col = 0; col < width; col++){//统计RGB三通道之和的直方图int sum = *(inptr + 3 * col) + *(inptr + 3 * col + 1) + *(inptr + 3 * col + 2);histrgbsum[sum]++;//找到RGB三通道各自的最大值Bmax、Gmax、RmaxBmax = max(Bmax, (double)*(inptr + 3 * col));Gmax = max(Gmax, (double)*(inptr + 3 * col + 1));Rmax = max(Rmax, (double)*(inptr + 3 * col + 2));/*maxrgb[0] = max(maxrgb[0], *(inptr + 3 * col));maxrgb[1] = max(maxrgb[1], *(inptr + 3 * col+1));maxrgb[2] = max(maxrgb[2], *(inptr + 3 * col+2));*/}}//设定比例r为10%double num = 0,ratio=0.1;int threshold = 0;int len = 0;len=sizeof(histrgbsum) / sizeof(histrgbsum[0]);//int len = end(histrgbsum) - begin(histrgbsum);cout << "histagram length:" << len << endl;for (len; len >= 0; len--){num += histrgbsum[len];//计算R+G+B的数量超过像素总数的ratio的像素值if (num > height * width * ratio){//使白点像素个数超过总像素个数的比例时,为阈值Tthreshold = len;break;}}//计算RGB之和大于 T 的像素,对大于阈值的像素各通道取平均,得到Bavg、Gavg、Ravg;double Rsum = 0, Gsum = 0, Bsum = 0;double Ravg = 0, Gavg = 0, Bavg = 0;int pixnum = 0;for (int row = 0; row < height; row++){const uchar* inptr = img_rgb8.ptr<uchar>(row);for (int col = 0; col < width; col++){//计算RGB之和,上面的局部变量又用一遍int sum = *(inptr + 3 * col) + *(inptr + 3 * col + 1) + *(inptr + 3 * col + 2);if (sum > threshold){Bsum += *(inptr + 3 * col);Gsum += *(inptr + 3 * col + 1);Rsum += *(inptr + 3 * col + 2);pixnum++;}}}Ravg = Rsum / (double)pixnum;Gavg = Gsum / (double)pixnum;Bavg = Bsum / (double)pixnum;//创建与输入图像一样大小类型的矩阵Mat img_awb = Mat::zeros(img_rgb8.size(), img_rgb8.type());//量化0-255,重新计算RGB值,分别计算RGB三通道的调整值Aout=A / Aavg * Amaxdouble Rout = 0, Gout = 0, Bout = 0;for (int row = 0; row < height; row++){const uchar* inptr = img_rgb8.ptr<uchar>(row);uchar* outptr = img_awb.ptr<uchar>(row);for (int col = 0; col < width; col++){Bout = (double)*(inptr + 3 * col) / Bavg * Bmax;Gout = (double)*(inptr + 3 * col+1) / Gavg * Gmax;Rout = (double)*(inptr + 3 * col+2) / Ravg * Rmax;Bout = min(max((double)0, Bout), (double)255);Gout = min(max((double)0, Gout), (double)255);Rout = min(max((double)0, Rout), (double)255);//将计算好的RGB值赋给新矩阵*(outptr + 3 * col) = (uchar)Bout;*(outptr + 3 * col+1) = (uchar)Gout;*(outptr + 3 * col+2) = (uchar)Rout;}}return img_awb;}​

断点运行之后,图像监视下白平衡处理后得到的结果(左输入,右输出,不是一一对应的截图):

3.动态阈值法

YUV颜色空间(亦称YCrCb)主要用于优化彩色视频信号的传输,Y表示亮度,U和V表示色度(色调和饱和度)。亮度是通过RGB输入信号来建立的,方法是将RGB信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面─色调与饱和度,分别用Cr和Cb来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之同的差异。

动态阈值算法通过将RGB变化到YCrCb颜色空间进行分析来确定白点,其选择参考白点的阈值是动态变化的。我们通过对图片的YCrCb坐标空间的分析,可以找到一个接近白色的区域,该区域是包含着参考白点的,通过设定一个阈值来规定某些点为参考白点。因此该算法是一个动态的自适应白平衡算法。

白平衡算法通常分为两步:白色点的检测,白色点的调整。本方法采用一个动态的阀值来检测白色点。详细算法过程参考如下:

(1)把图像w*h从RGB空间转换到YCrCb空间。转换公式如下:

(2)通过限定YUV的区域来判断是否为白点,通过四个限制条件俩限制白点,满足条件的点就是白点,参与后续的计算,否则,点直接舍弃。

首先,为了增强算法的鲁棒性,将图像分为12部分,把图像分成宽高比为4:3个块(块数可选)。

然后对每个块,分别计算Cr,Cb的平均值Mr,Mb。

再对每个块,根据Mr,Mb,用下面公式分别计算Cr,Cb的方差Dr,Db。

最后判定每个块的近白区域(near-white region)。判别准则为:

其中sign为符号函数,即正数返回1,负数返回0。

设一个“参考白色点”的亮度矩阵RL,大小为w*h。若符合判别式,则作为“参考白色点”,并把该点(i,j)的亮度(Y分量)值赋给RL(i,j);若不符合,则该点的RL(i,j)值为0。

上面几步为白点检测,下面几步为白点调整:

(1)选取参考“参考白色点”中最大的10%的亮度(Y分量)值,并选取其中的最小值Lu_min;

(2)调整RL,若RL(i,j)<Lu_min, RL(i,j)=0; 否则,RL(i,j)=1;

(3)分别把R,G,B与RL相乘,得到R2,G2,B2。 分别计算R2,G2,B2的平均值,得到Rav,Gav,Bav;

(4)得到调整增益: Ymax=double(max(max(Y));

Rgain=Ymax/Rav;

Ggain=Ymax/Gav;

Bgain=Ymax/Bav;

(5)调整原图像:Ro= R*Rgain; Go= G*Ggain; Bo= B*Bgain。

实现代码本人未尝试,C++可以参考(过程较为复杂):

OpenCV图像处理专栏十一 | IEEE Xplore 2015的图像白平衡处理之动态阈值法 (qq.com)

4.其他算法

除了上面比较常见的几种,还有基于模糊逻辑,基于色温,基于边缘和多方法融合法等等。

最后,再次想吐槽csdn的发布文章的编辑页面,类似换行,空格,撤消等等,编辑与图片接近的地方经常会跳转编辑处,还很容易误删图片。有时候看别人文章,里面的一些公式,格式,图片等等,可能因为不兼容或者乱码等问题影响观看和理解,也是学习中一方面的阻碍。

写出一篇文章没想到最后的困难居然是编辑,用多了word,真心觉得这里编辑功能太不智能,需要花费更多时间。还挂着中国开发者网络的头衔,内部工作人员能不能更新升级以下这个编辑发布文章里面的页面和功能。

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

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

相关文章

基于蜉蝣优化的BP神经网络(分类应用) - 附代码

基于蜉蝣优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于蜉蝣优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.蜉蝣优化BP神经网络3.1 BP神经网络参数设置3.2 蜉蝣算法应用 4.测试结果&#xff1a;5.M…

AAD基础知识(identity/token/PRT)

简介 AAD(Azure Active Directory/Azure AD)是微软基于云身份验证和访问控制的解决方案&#xff0c;通过SSO登录其他o365应用(word/outlook/teams…) 微软在2023年7月把AAD重命名为Microsoft Entra ID&#xff0c;官网&#xff1a;https://www.microsoft.com/zh-cn/security/b…

【多任务案例:猫狗脸部定位与分类】

【猫狗脸部定位与识别】 1 引言2 损失函数3 The Oxford-IIIT Pet Dataset数据集4 数据预处理4 创建模型输入5 自定义数据集加载方式6 显示一批次数据7 创建定位模型8 模型训练9 绘制损失曲线10 模型保存与预测 1 引言 猫狗脸部定位与识别分为定位和识别&#xff0c;即定位猫狗…

通过 HelpLook ChatBot AI自动问答机器人降低客户服务成本

在当今竞争激烈的商业环境中&#xff0c;提供卓越的客户服务对于维持忠诚的客户群和推动业务增长至关重要。客户服务涵盖了公司与其客户之间的所有互动&#xff0c;包括解答问题、解决问题和提供支持。它在塑造客户对品牌的看法方面起着关键作用&#xff0c;并且可以显著影响他…

C语言判断语句

判断结构要求程序员指定一个或多个要评估或测试的条件&#xff0c;以及条件为真时要执行的语句&#xff08;必需的&#xff09;和条件为假时要执行的语句&#xff08;可选的&#xff09;。 C 语言把任何非零和非空的值假定为 true&#xff0c;把零或 null 假定为 false。 下面…

react create-react-app v5 从零搭建(使用 npm run eject)

前言&#xff1a; 好久没用 create-react-app做项目了&#xff0c;这次为了个h5项目&#xff0c;就几个页面&#xff0c;决定自己搭建一个&#xff08;ps:mmp 好久没用&#xff0c;搭建的时候遇到一堆问题&#xff09;。 我之前都是使用 umi 。后台管理系统的项目 使用 antd-…

DevExpress ChartControl 画间断线

效果如下&#xff1a; 解决办法&#xff1a;数据源间断位置加入double.NaN demo下载

动态链接那些事

1、为什么要动态链接 1.1 空间浪费 对于静态链接来说&#xff0c;在程序运行之前&#xff0c;会将程序所需的所有模块编译、链接成一个可执行文件。这种情况下&#xff0c;如果 Program1 和 Program2 都需要用到 Lib.o 模块&#xff0c;那么&#xff0c;内存中和磁盘中实际上就…

Sui第五轮资助: 17个项目共获105万美元资助金

近日&#xff0c;Sui基金会宣布17个项目获得了105万美元的资助&#xff0c;用于建设项目以推动Sui的采用和发展。要获得资助&#xff0c;项目必须提交详细的提案&#xff0c;说明构建的项目、预算明细、关键里程碑、团队经验&#xff0c;以及对Sui社区的预期贡献。了解更多Sui资…

Azure Arc 概要:功能、管理和应用场景详解,AZ900 考点示例

文章目录 本文大纲一、什么是 Azure Arc二、使用 Azure Arc 可以做什么操作三、使用 Azure Arc 可以管理什么资源3.1 如何使用Azure Arc与服务器? 四、Azure Arc 支持的主要场景五、在 AZ900 中的考点示例5.1 示例题 15.2 示例题 2 本文大纲 本文思维导图概述的主要内容&…

已解决 Bug——IndexError: index 3 is out of bounds for axis 0 with size 3问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

软件工程与计算总结(二)软件工程的发展

本章开始介绍第二节内容&#xff0c;主要是一些历史性的东西~ 一.软件工程的发展脉络 1.基础环境因素的变化及其对软件工程的推动 抽象软件实体和虚拟计算机都是软件工程的基础环境因素&#xff0c;它们能从根本上影响软件工程的生产能力&#xff0c;而且是软件工程无法反向…

十四天学会C++之第三天(数组和字符串)

1. 数组的定义和初始化 数组是一种由相同数据类型的元素组成的集合&#xff0c;这些元素按照一定的顺序存储在连续的内存位置上。数组的大小在创建时是固定的&#xff0c;无法在运行时改变。 在C中&#xff0c;数组的定义和声明非常简单。定义一个数组&#xff1a; 数据类型…

vtk 动画入门 1 代码

实现效果如图&#xff1a; #include <vtkAutoInit.h> //VTK_MODULE_INIT(vtkRenderingOpenGL2); //VTK_MODULE_INIT(vtkInteractionStyle); VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle); //VTK_MODULE_INIT(vtkRenderingFreeType); #in…

IDEA Rogstry中找不到compiler.automake.allow.when.app.running问题解决

网上大部分人教我们 先 File > Settings 然后 勾选 Build 下的 Compiler中的 Build project automatically 这些步骤都不会有问题 然后就会让我们 ctrl shift alt / 点 Rogstry 打开后 我人就麻了 根本没有什么 compiler.automake.allow.when.app.running 也不用慌 我们…

YTM32的电源管理与低功耗系统详解

YTM32的电源管理与低功耗系统详解 苏勇&#xff0c;2023年10月 文章目录 YTM32的电源管理与低功耗系统详解缘起原理与机制电源管理模型的功耗模式正常模式&#xff08;Normal&#xff09;休眠模式&#xff08;Sleep&#xff09;深度休眠模式&#xff08;DeepSleep&#xff09;…

大语言模型之十五-预训练和监督微调中文LLama-2

这篇博客是继《大语言模型之十二 SentencePiece扩充LLama2中文词汇》、《大语言模型之十三 LLama2中文推理》和《大语言模型之十四-PEFT的LoRA》 前面博客演示了中文词汇的扩充以及给予LoRA方法的预训练模型参数合并&#xff0c;并没有给出LoRA模型参数是如何训练得出的。 本篇…

WebSocket实战之六心跳重连机制

一、前言 WebSocket应用部署到生产环境&#xff0c;我们除了会碰到因为经过代理服务器无法连接的问题&#xff08;注&#xff1a;该问题可以通过搭建WSS来解决&#xff0c;具体配置请看 WebSocket实战之四WSS配置 &#xff09;&#xff0c;另外一个问题就是外网环境不稳定经常…

基本的五大排序算法

目录&#xff1a; 一&#xff0c;直接插入算法 二&#xff0c;希尔排序算法 三&#xff0c;选择排序 四&#xff0c;堆排序 五&#xff0c;冒泡排序算法 简介&#xff1a; 排序算法目前是我们最常用的算法之一&#xff0c;据研究表明&#xff0c;目前排序占用计算机CPU的时…

Linux环境下gdb调试方法与演示

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Linux专栏】&#x1f388; 本专栏旨在分享学习Linux的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 演示环境&#xff1…