从Pearson相关系数到模板匹配的NCC方法

news2025/1/15 16:30:10

文章目录

  • <center> NCC(Normalized Cross Correlation)
    • 1.**Pearson相关系数**
    • 2.**协方差 covariance**
    • 3. **方差 variance**
    • 4.模板匹配中的NCC方法
    • 5.实现过程
    • 6.测试结果
    • 7.部分核心源码
      • NCC.cpp

NCC(Normalized Cross Correlation)

从Pearson相关系数到模板匹配的NCC方法

1.Pearson相关系数

Pearson相关系数是用来衡量两个变量之间的相关性,由下式给出
p = c o v ( X , Y ) σ ( X ) σ ( Y ) p = \frac{cov(X,Y)}{\sigma(X)\sigma(Y)} p=σ(X)σ(Y)cov(X,Y)
p在数值上在[-1,1]之间

  • 当p=0时,说明两个变量不想关;
  • 当p>0时,两个变量正相关,而且p越大正相关性越强;
  • 当p<0时,两个变量负相关,而且p越小负相关性越强;

上式中 c o v ( X , Y ) cov(X,Y) cov(X,Y)表示的是两个变量 X 、 Y X、Y XY的协方差, σ ( X ) \sigma(X) σ(X)表示的是变量X的标准差差, σ ( Y ) \sigma(Y) σ(Y)表示的是变量Y的标准差$。

2.协方差 covariance

协方差也是用来衡量两个变量之间的相关性的,当两个变量之间的协方差是0时不相关(两个变量相互独立),大于0时正相关,小于0时负相关。例如身高和体重之间的协方差就是一个正数,因为身高和体重是正相关的。
协方差由下式给出:
c o v ( X , Y ) = E [ ( X − E ( X ) ) ( Y − E ( Y ) ) ] cov(X,Y)=E[(X-E(X))(Y-E(Y))] cov(X,Y)=E[(XE(X))(YE(Y))]
其中E()表示变量的数学期望,eg:E(X)表示变量X的数学期望, E [ X ] = Σ μ i x i , μ i 是 x i E[X]=\Sigma \mu_i x_i,\mu_i 是 x_i E[X]=Σμixi,μixi的权重,如果每个样本的权重都相等的话则写为: E [ X ] = Σ x i n E[X]=\frac{\Sigma x_i}{n} E[X]=nΣxi

此外协方差的等价式

c o v ( X , Y ) = E [ ( X − E ( X ) ) ( Y − E ( Y ) ) ] = E [ X Y − X E ( Y ) − Y E ( X ) + E ( X ) E ( Y ) ] = E ( X Y ) − 2 E ( X ) E ( Y ) + E ( X ) E ( Y ) = E ( X Y ) − E ( X ) E ( Y ) \begin{aligned} cov(X,Y) &= E[(X-E(X))(Y-E(Y))]\\ &=E[XY - XE(Y) - YE(X) + E(X)E(Y)]\\ &=E(XY)-2E(X)E(Y) + E(X)E(Y)\\ &=E(XY)-E(X)E(Y) \end{aligned} cov(X,Y)=E[(XE(X))(YE(Y))]=E[XYXE(Y)YE(X)+E(X)E(Y)]=E(XY)2E(X)E(Y)+E(X)E(Y)=E(XY)E(X)E(Y)

协方差示例
有三个人的身高体重数据,X表示身高,Y表示体重

X身高(cm): 100,150,200
Y体重(kg): 50,100,150

则身高和体重的协方差 c o v ( X , Y ) = E ( X Y ) − E ( X ) E ( Y ) 则身高和体重的协方差cov(X,Y)=E(XY)-E(X)E(Y) 则身高和体重的协方差cov(X,Y)=E(XY)E(X)E(Y)
其中:

E ( X ) = 1 3 ( 100 + 150 + 200 ) = 150 E(X)=\frac{1}{3}(100+150+200)=150 E(X)=31(100+150+200)=150,
E ( Y ) = 100 , E ( X Y ) = 1 3 ( 100 ∗ 50 + 150 ∗ 100 + 200 ∗ 150 ) = 50000 3 E(Y)=100,E(XY)=\frac{1}{3}(100*50+150*100+200*150)=\frac{50000}{3} E(Y)=100,E(XY)=31(10050+150100+200150)=350000
c o v ( X , Y ) = E ( X Y ) − E ( X ) E ( Y ) = 50000 3 − 150 ∗ 100 = 5000 3 . cov(X,Y)=E(XY)-E(X)E(Y)=\frac{50000}{3}-150*100=\frac{5000}{3}. cov(X,Y)=E(XY)E(X)E(Y)=350000150100=35000.

3. 方差 variance

在考察单个变量的分布特征时有方差(variance)的概念,方差是一个大于等于0的实数,方差为0表示变量分布完全集中在一个点上,方差越大变量的分布越分散。方差由下式给出: v a r ( X ) = E [ ( X − E ( X ) ) 2 ] var(X)=E[(X-E(X))^2] var(X)=E[(XE(X))2] 观察可以看到方差是协方差的一个特例,即cov(X,X)=var(X).$

4.模板匹配中的NCC方法

模板匹配就是给定一个目标图和一个搜索图,采用一定的搜索策略去找到一个和目标相近的区域,在刚性模板匹配中,一般都是采用滑窗的方法来搜索,在比较两个图的相似度时有很多种方法,最简单的就是两个图像直接相减,NCC(Normalized Cross Correlation)就是计算两张图的pearson相关性,值越大说明两个图像越相像。

记 T m × n 为目标图 ( t a r g e t ) 记T_{m\times n}为目标图(target) Tm×n为目标图(target), S M × N S_{M\times N} SM×N为源搜索图(source), S x , y S_{x,y} Sx,y为S中以点 ( x , y ) (x,y) (x,y)为左上角的和T大小相同的子图, R ( M − m + 1 ) × ( N − n + 1 ) R_{(M-m+1)\times (N-n+1)} R(Mm+1)×(Nn+1)为匹配的结果图,则 R ( x , y ) = c o v ( S x , y , T ) σ ( S x , y ) σ ( T ) R(x,y)=\frac{cov(S_{x,y},T)}{\sigma(S_{x,y})\sigma(T)} R(x,y)=σ(Sx,y)σ(T)cov(Sx,y,T)

其中 c o v ( S x , y , T ) = E ( S x , y T ) − E ( S x , y ) E ( T ) = Σ i = 1 m Σ j = 1 n S x , y ( i , j ) T ( i , j ) m n − S x , y ˉ T ˉ \begin{aligned} cov(S_{x,y},T) &=E(S_{x,y}T)-E(S_{x,y})E(T)\\ &=\frac{\Sigma_{i=1}^{m}\Sigma_{j=1}^{n}S_{x,y}(i,j)T(i,j)}{mn} - \bar{S_{x,y}}\bar{T} \end{aligned} cov(Sx,y,T)=E(Sx,yT)E(Sx,y)E(T)=mnΣi=1mΣj=1nSx,y(i,j)T(i,j)Sx,yˉTˉ

S x , y ˉ = Σ i = 1 m Σ j = 1 n S x , y ( i , j ) m n \bar{S_{x,y}}=\frac{\Sigma_{i=1}^{m}\Sigma_{j=1}^{n}S_{x,y}(i,j)}{mn} Sx,yˉ=mnΣi=1mΣj=1nSx,y(i,j)

T ˉ = Σ i = 1 m Σ j = 1 n T ( i , j ) m n \bar{T} = \frac{\Sigma_{i=1}^{m}\Sigma_{j=1}^{n}T(i,j)}{mn} Tˉ=mnΣi=1mΣj=1nT(i,j)

σ ( S x , y ) = v a r ( S x , y ) = Σ i = 1 m Σ j = 1 n ( S x , y ( i , j ) − S x , y ˉ ) 2 m n \sigma(S_{x,y})=\sqrt{var(S_{x,y})}=\sqrt{\frac{\Sigma_{i=1}^{m}\Sigma_{j=1}^{n}{(S_{x,y}(i,j)-\bar{S_{x,y}}})^2}{mn}} σ(Sx,y)=var(Sx,y) =mnΣi=1mΣj=1n(Sx,y(i,j)Sx,yˉ)2

σ ( T ) = v a r ( S x , y ) = Σ i = 1 m Σ j = 1 n ( T ( i , j ) − T ˉ ) 2 m n \sigma(T)=\sqrt{var(S_{x,y})}=\sqrt{\frac{\Sigma_{i=1}^{m}\Sigma_{j=1}^{n}{(T(i,j)-\bar{T}})^2}{mn}} σ(T)=var(Sx,y) =mnΣi=1mΣj=1n(T(i,j)Tˉ)2

上面的式子展开看起来感觉很复杂,以往看到的也都是这样完全展开又组合在一起的式子,就像opencv官网的解释,很完整但是让人很费解,具体为什么是这样搞不清楚(也可能是我菜吧),但是看上面R(x,y)的式子意义是很明确的,就是计算两个图之间的Pearson相关系数。按照公式就可以直接开工写代码了。

5.实现过程

观察式子: R ( x , y ) = c o v ( S x , y , T ) σ ( S x , y ) σ ( T ) R(x,y)=\frac{cov(S_{x,y},T)}{\sigma(S_{x,y})\sigma(T)} R(x,y)=σ(Sx,y)σ(T)cov(Sx,y,T)

可以发现 σ ( T ) \sigma(T) σ(T)是固定的,模板给定之后值就确定了,只需要计算一次。 σ ( S x , y )和 c o v ( S x , y , T ) \sigma(S_{x,y})和cov(S_{x,y},T) σ(Sx,y)和cov(Sx,y,T)的计算过程中一直要用到 S x , y ˉ \bar{S_{x,y}} Sx,yˉ,如果直接去计算这个平均值将会有很多计算是浪费掉的,可以用积分图来加速这个过程

几个核心的步骤

  • 计算两个图的协方差
  • 计算图的灰度均值
  • 计算图的标准差

在实现上第一版先只打算跑通整个NCC的计算流程,后续如果有机会的话可以再考虑做几个优化版本。目前很明确想到的有下面这几个:

  • 积分图加速均值的计算
  • 计算协方差时用到卷积用FFT加速
  • 金字塔加速
  • 指令集优化
  • 多线程

6.测试结果

  • source
    在这里插入图片描述

  • target

在这里插入图片描述

  • result

在这里插入图片描述

可以看到在目标处得到最大值,也就是正确匹配到了目标图。

7.部分核心源码

source image size w,h = (1095,680)
target image size w,h = (89,91)
my NCC run 10 times, use 12359.000000 ms       
opencv NCC run 10 times, use 14.000000 ms

opencv的速度是该版本的882.78倍。

NCC.cpp

namespace mycv
{


/**
 * @brief 模板匹配,归一化交叉相关算法。衡量模板和待匹配图像的相似性时
 * 用(Pearson)相关系数来度量。
 * r=cov(X,Y)/(sigma(X) * sigma(Y))
 * 其中cov(X,Y): 表示两个变量的协方差
 * cov(X,Y) = E[(X-E(x)) * (Y-E(Y))] = E(XY) - E(x)E(Y)
 * sigma(X): 表示X变量的标准差
 * sigma(Y): 表示Y变量的标准差
 * 
 * @param source : 搜索图CV_8UC1格式
 * @param target :模板图CV_8UC1格式
 * @param result : 匹配结果的map图
 * @return int : 程序运行的状态码
 */
int NormalizedCrossCorrelation(
    const cv::Mat &source,
    const cv::Mat &target,
    cv::Mat &result
    )
    {
        if(source.empty() || target.empty())
        {
            MYCV_ERROR(kImageEmpty,"NCC empty input image");
            return kImageEmpty;
        }
        int H = source.rows;
        int W = source.cols;
        int t_h = target.rows;
        int t_w = target.cols;
        if(t_h > H || t_w > W)
        {
            MYCV_ERROR(kBadSize,"NCC source image size should larger than targe image");
            return kBadSize;
        }

        //r = cov(X,Y)/(sigma(X) * sigma(Y))
        //sigma(X) = sqrt(var(X))
        int r_h = H - t_h + 1; //结果图的高度
        int r_w = W - t_w + 1;
        double target_mean = calculateMean(target);
        double target_var = calculateVariance(target,target_mean);
        double target_std_var = std::sqrt(target_var);
        result = cv::Mat::zeros(cv::Size(r_w,r_h),CV_32FC1);
        for(int row = 0; row < r_h ; row++)
        {
            float * p = result.ptr<float>(row);
            for(int col = 0; col < r_w; col++)
            {
                cv::Rect ROI(col,row,t_w,t_h);//source上和目标图匹配的子图
                cv::Mat temp = source(ROI);
                double temp_mean = calculateMean(temp);
                double cov = calculateCovariance(temp,target,temp_mean,target_mean);
                double temp_var = calculateVariance(temp,temp_mean);
                double temp_std_var = std::sqrt(temp_var);
                p[col] = cov / ((temp_std_var + 0.0000001) * (target_std_var + 0.0000001));
            }
        }


        return kSuccess;
    }


/**
 * @brief 计算图像上ROI区域内的均值
 * 
 * @param input  : 输入的图像CV_8UC1
 * @param ROI  : 输入的ROI区域
 * @param mean  : 返回的区域均值
 * @return int 
 */
int calculateRegionMean(const cv::Mat &input,const cv::Rect &ROI,double &mean)
{
    if(input.empty())
    {
        MYCV_ERROR(kImageEmpty,"input empty");
        return kImageEmpty;
    }
    if(1 != input.channels())
    {
        MYCV_ERROR(kBadDepth,"Now only sopurt for one channel image");
        return kBadDepth;
    }
    int h = input.rows;
    int w = input.cols;
    
    if((ROI.x+ROI.width > w ) || (ROI.y+ROI.height > h)
    || ROI.width <= 0 || ROI.height <= 0 )
    {
        MYCV_ERROR(kBadSize,"ROI is too big");
        return kBadSize;
    }
    int tpx = ROI.x;
    int tpy = ROI.y;
    int btx = ROI.x + ROI.width;
    int bty = ROI.y + ROI.height;
    double sum = 0;
    for(int row = tpy; row < bty; row++)
    {
        const uchar *p = input.ptr<uchar>(row);
        for (int col = tpx ; col < btx ; col++)
        {
            sum += p[col];
        }
    }
    int pixels_num = ROI.height * ROI.width;
    mean = sum / pixels_num;
    return kSuccess;
}

/**
 * @brief 计算两个输入图的协方差,两个输入图的尺寸需要一致,在计算目标图和原图子块的协方差时,
 * 目标图(模板图)是固定的,均值只需要计算一次,所以如果传入图像均值的话就不在计算均值,均值默认为-1
 * cov(X,Y): 表示两个变量的协方差
 * cov(X,Y) = E[ (X-E(x)) * (Y-E(Y)) ] = E(XY) - E(x)E(Y)
 * 
 * @param A  : 输入图A CV_8UC1
 * @param B  : 输入图B CV_8UC1
 * @param mean_a  : A的像素均值
 * @param mean_b  : B的像素均值
 * @return double : 两个图像的协方差
 */
double calculateCovariance(const cv::Mat &A, const cv::Mat &B,double mean_a,double mean_b)
{
    if(A.empty() || B.empty())
    {
        MYCV_ERROR(kImageEmpty,"input image is empty");
        return kImageEmpty;
    }
    if (A.cols != B.cols || A.rows != B.rows)
    {
        MYCV_ERROR(kBadSize,"mat A B should be in same size");
        return kBadSize;
    }
    
    //E(XY)
    double sum = 0;
    for (int row = 0; row < A.rows; row++)
    {
        const uchar *pa = A.ptr<uchar>(row);
        const uchar *pb = B.ptr<uchar>(row);
        for (int  col = 0; col < A.cols; col++)
        {
            sum += (double)pa[col] * (double)pb[col];
        }
        
    }

    double mean_AB = sum / ((double)A.rows * (double)A.cols);

    if (-1 == mean_a)
    {
        mean_a = calculateMean(A);
    }
    if (-1 == mean_b)
    {
        mean_b = calculateMean(B);
    }
    
    //cov(X,Y) = E[ (X-E(x)) * (Y-E(Y)) ] = E(XY) - E(x)E(Y)
    double cov_AB = mean_AB - (mean_a * mean_b);
    
    return cov_AB;
}

/**
 * @brief 计算输入图像的方差,如果已知mean就不再计算mean
 * 
 * @param image  : 输入图CV_8UC1
 * @param mean  : 图像的灰度均值,默认值为-1,不输入时会计算mean
 * @return double :图像的方差
 */
double calculateVariance(const cv::Mat &image,double mean)
{
    if (image.empty())  
    {
        MYCV_ERROR(kImageEmpty,"empty image");
        return -1;//正常的方差不会小于0
    }
    if (-1 == mean)
    {
        mean = calculateMean(image);
    }

    double sum = 0 ;
    for (int  row = 0; row < image.cols; row++)
    {
        const uchar * p = image.ptr<uchar>(row);
        for (int col = 0; col < image.cols; col++)
        {
            sum += (p[col] - mean) * (p[col] - mean);
        }
        
    }

    double var = sum / ((double)image.cols * (double)image.rows);
    
    return var;    
}



/**
 * @brief 计算输入图的灰度均值
 * 
 * @param image  : 输入图CV_8UC1
 * @return double : 输入图像的灰度均值
 */
double calculateMean(const cv::Mat &image)
{
     if (image.empty())  
    {
        MYCV_ERROR(kImageEmpty,"empty image");
        return -1;
    }

    double sum = 0 ;
    for (int  row = 0; row < image.cols; row++)
    {
        const uchar * p = image.ptr<uchar>(row);
        for (int col = 0; col < image.cols; col++)
        {
            sum += p[col];
        }
        
    }

    double mean = sum / ((double)image.cols * (double)image.rows);
    return mean;
}




} //end namespace mycv

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

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

相关文章

HTML5 本地存储

文章目录HTML5 本地存储Cookie的缺点localStorage简介简单使用sessionStorage简介简单使用indexedDB简介HTML5 本地存储 Cookie的缺点 在HTML4.01中&#xff0c;想要在浏览器端存储用户的某些数据时&#xff0c;我们一般只能使用Cookie来实现。 但是Cookie存在一些问题&…

如何进行企业设备管理?

如何进行企业设备管理&#xff1f; 点进这篇文章&#xff0c;让企业设备管理不再 难 难 难 &#xff01; 对于许多公司来说&#xff0c;特别是制造业&#xff0c;生产设备已成为企业生产线中最重要最核心的部分&#xff0c;因此设备管理是企业管理基础的重要组成部分。而在当…

mysql-基础-约束多表关系多表查询事务

文章目录mysql基础1&#xff0c;约束1.1 概念1.2 分类1.3 非空约束1.4 唯一约束1.5 主键约束1.6 默认约束1.7 约束练习1.8 外键约束1.8.1 概述1.8.2 语法1.8.3 练习2&#xff0c;数据库设计2.1 数据库设计简介2.2 表关系(一对多)2.3 表关系(多对多)2.4 表关系(一对一)2.5 数据库…

刘鹏的2022年度总结

[ 这是 2022 博客之星 的竞选帖子&#xff0c; 请你在这里增加其他内容。接下来分享这一年的收获&#xff0c;感悟&#xff0c;以及 对CSDN 产品的反馈和 2023 年的希望。 ] 目录 1. 学习收获 1.1 心路历程 1.2 基本收支 2. 未来展望 2.1 UR3机械臂ROS 2.2 论文 2.3 开…

电线电缆行业mes解决方案,打造全新信息化车间

电线电缆行业虽然只是一个配套行业&#xff0c;却占据着中国电工行业1/4的产值。它产品种类众多&#xff0c;应用范围十分广泛&#xff0c;涉及到电力、建筑、通信&#xff0c;制造等行业&#xff0c;与国民经济的各个部门都密切相关。电线电续还被称为国民经济的“动脉”与“神…

STM32理论 —— 看门狗

文章目录1. 简述2. 独立看门狗 IWDG2.1 IWDG 相关寄存器2.1.1 键值寄存器IWDG_KR2.1.2 预分频寄存器IWDG_PR与重装载寄存器IWDG_RLR2.2 核心代码1. 简述 STM32 内部自带了 2 个看门狗&#xff1a;独立看门狗&#xff08;IWDG&#xff09;和窗口看门狗&#xff08;WWDG&#xff…

5. 最长回文子串

题目描述 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s “babad” 输出&#xff1a;“bab” 解释&#xff1a;“aba” 同样是符合题意的答案。 示…

Redis集群系列四 —— 哨兵集群搭建

准备实例和配置 搭建一个三节点的 Sentinel 集群&#xff0c;来监管之前的 Redis 主从集群&#xff0c;如图&#xff1a; 参考上述配置&#xff0c;分别复制 redis 下的 sentinel.conf 文件&#xff0c;如图&#xff1a; 文件中除端口外&#xff0c;其它配置都是一样的。 启动…

路由与交换期末复习整理

一、前言 本文是对前期在校内学习路由与交换课程时对相关知识点的整理&#xff0c;供期末复习参考。 二、选择题知识点 1. 启动配置保存的位置 NVRAM 2. 路由器的功能 网络连接功能、&#xff08;数据处理&#xff09;和设备管理功能。 3. 打开路由器接口的命令 int加接口…

骨骼与绑定

文章目录Blender里的三种绑定.主从绑定.进行物体绑定.进行顶点绑定.解除绑定.保持变换.无反向.进行晶格绑定.约束.变换约束.复制位置.复制旋转.复制缩放.限定距离.限定位置&#xff0c;限定旋转&#xff0c;限定缩放.维持体积.变换.追踪约束.钳制到.阻尼追踪.锁定追踪.拉伸到.标…

【Go基础】初识Go语言

文章目录1. 开发环境搭建2. 第一个Go程序3. Go命令介绍1. 开发环境搭建 在 https://studygolang.com/dl 上下载需要的Go稳定版本&#xff0c;这里我选择的是17.5的版本对于Windows和macOS用户&#xff0c;直接双击即可安装&#xff0c;留意一下安装路径&#xff1b;对于Linux用…

loop为true, slidesPerView为多个的时候,swiper精准获取激活的索引

效果图如下&#xff1a; 重点代码如下&#xff1a; <script>var swiper new Swiper(.swiper-container, {slidesPerView: 3, //显示几个slidespaceBetween: 30, //slide之间的间距centeredSlides: true,loop: true, //开启循环滚动initialSlide: 0, //默认就是0p…

多目标跟踪

目录 多目标跟踪定义&#xff1a; 多目标跟踪分类 多目标跟踪难点分析 多目标跟踪数据集 多目标跟踪评价指标 多目标跟踪定义&#xff1a; 多目标跟踪旨在将视频序列中感兴趣的目标检测出来&#xff0c;并赋予每个目标单独的编号&#xff0c;在整个序列中形成目标的轨迹。 …

BindingException异常的产生原因及解决过程详解

一. 问题背景 今天我在讲完MyBatis后&#xff0c;学生在进行代码练习时遇到了下面这样的一个异常&#xff0c;先上图&#xff1a; 二. 问题分析 1.原因分析 首先我们看到&#xff0c;这里抛出的异常是org.apache.ibatis.binding.BindingException&#xff0c;接着再看异常的…

如何提高外贸客户回复率

业务员接到的每一笔订单都是客户对他的信任&#xff0c;所以合作的前提是信任。如何让客户信任我们或者快速信任我们&#xff0c;尤为关键。 如何提高客户的回复率&#xff0c;米贸搜整理如下: 1.及时回复: 无论是客户发来的询盘还是网上咨询&#xff0c;都要尽快回复客户&am…

Uber应用分享 | 使用 Parquet Page Index 加速 Presto 查询

当前&#xff0c;数据量呈快速增长态势&#xff0c;给诸如 Presto 等查询引擎带来了挑战。Presto 作为一种流行的交互式查询引擎&#xff0c;具有可扩展、高性能并可与 Hadoop 进行平滑集成的特性。随着数据量的增长&#xff0c;Presto 需要读取更大的数据块并将其加载到内存中…

CREAL:为什么光场+HOE是AR眼镜未来

利用光场显示技术&#xff0c;CREAL曾展示出可自然变焦的3D显示效果。为了验证该技术在AR和VR场景的应用&#xff0c;该公司分别打造了两款头显原型。头显对于VR来讲比较常见&#xff0c;但对于AR来讲&#xff0c;眼镜形态才是未来的发展方向。因此&#xff0c;为了缩减AR硬件的…

Unity_IL2CPP常见问题分析

Unity 打包il2cpp模式时的常见问题分析 Unity 编辑器模式下是采用.net 虚拟机解释执行.net 代码&#xff0c;发布的时候有两种模式&#xff0c;一种是mono虚拟机模式&#xff0c;一种是il2cpp模式。由于iOS AppStore规定不允许使用虚拟机&#xff0c;所以发布到iOS,Unity采用了…

推出Linux操作系统Inspur KOS,浪潮信息意欲何为?

2020年底&#xff0c;CentOS突然宣布CentOS7、8等系列版本停止维护的时间表&#xff0c;业界为之震动。 一直以来&#xff0c;Linux都是服务器操作系统市场的顶流支柱。CentOS发行版生命周期的突然变动&#xff0c; 不仅促使很多行业用户思考&#xff1a;“CentOS停止维护之后…

第三十三章 数论——组合数详解(2)

一、组合数——卢卡斯定理 1、问题 这道题中&#xff0c;a,ba,ba,b的范围都是很大的&#xff0c;我们就无法直接用到之前所讲解的预处理阶乘的方法。 如果大家没有看过作者写的组合数&#xff08;1&#xff09;的话&#xff0c;建议大家先去看一下&#xff0c;今天所讲的问题…