相机标定张正友、opencv和halcon对比(1)

news2024/11/18 11:46:54

本文将从基本标定开始,结合实际工作经验,分析张正友、opencv和halcon三者相机标定的深层原理与不同之处,内容比较多,如果出现错误请指正。

相机光学模型

我们使用的镜头都是由多组镜片组成,它实际上是一种厚透镜模型,但是目前所有的相机标定是基于针孔模型来进行标定的,因此在学习标定之前,首先我们要对相机进行建模,这样能从整体上把握坐标系之间的变换关系。当然鱼眼镜头和沙姆镜头需要基于针孔模型进行二次建模,这里不细说了,有想交流的可以私信我。我们的目标就是把厚透镜模型变为针孔模型进行后续的处理。
厚透镜镜片组可能如下(halcon):
在这里插入图片描述

针孔模型

针孔模型如下图所示,小孔处为投影中心,y为物体,y’为倒立的像,a为物距,c为像距,注意这里像距并不等同于镜片的焦距,但我们一般叫焦距
在这里插入图片描述
针孔模型满足下面的相似三角形关系:
在这里插入图片描述
在使用中,一般我们会在投影中心o前方构造虚拟像平面,把像平面和物平面放到同一侧,这样可以使图像坐标系和相机坐标系递增方向对齐:
在这里插入图片描述
在这里插入图片描述

厚透镜模型

可以将镜头看作是两个球心位于同一直线的折射球面组成,两个球面之间为一种均匀介质,镜头两侧为另一种介质,镜头具有一定厚度,如下图所示:
在这里插入图片描述
注意光是从左往右传播的,镜头前面的距离为负,向上为正,向下为负,比如y为正,y’为负,f为负,f’为正。
参数解释如下:
y 物高
y’ 像高
F 物方焦点,像方平行光线过镜头后汇聚在该点
F’ 像方焦点,物方平行光线过镜头后汇聚在该点
f 物方焦距
f’ 像方焦距,两侧介质一样的话,f等于-f’
P 物方主平面,为过像方水平光线与过F的对应光线的交点
P’ 像方主平面,为过物方水平光线与过F’的对应光线的交点
a 物距,为物到物方主平面距离
a’ 像距
N 为物方主平面与光轴交点
N’ 为像方主平面与光轴交点,入射和出射光线角度相同

这里因为有两个主平面,导致直接基于厚透镜是无法建模的。

厚透镜成像法则:

  1. 镜头前平行于光轴的光线,经过F’;
  2. 经过F的光线,通过镜头后和光轴水平;
  3. 过N点的光线,也会过N’点,并且镜头前和镜头后与光轴的夹角不变。

两个关键的公式:
在这里插入图片描述
在这里插入图片描述
这两个公式非常关键,在做相机镜头选型时一定会用到这个公式去推断视野和成像芯片尺寸对镜头型号的影响。

可推导出如下变化:
 物距变小,像距变大,物距变大,像距变小。也就是说,相机固定不动,焦距不变的情况下,聚焦过程其实为改变像距的过程;
 物距无穷远,所有入射光线为平行光,此时a’=f’,像面位于像方焦点上。
 【放大镜虚像】当物放到F点位置,像面会在无穷远处,如果物放到F以内,光线在成像端发散,a’的正负号会发生变化,像变为物体同一侧的虚像:
在这里插入图片描述

厚透镜转针孔模型(halcon)

那么厚透镜到底怎么转为针孔模型呢?这里基于现有资料,这里以halcon为例进行说明。在说明之前我们必须先了解镜头中的两个概念:出瞳和入瞳。

孔径光阑和出瞳入瞳

镜头中都设计有一个可调节大小的环,来控制入射光线的多少。如下图中的D面即为环,同时镜筒本身也会限制到达像平面的光线总量,这些因素统称为光阑,其中起最大程度限制作用的被称为孔径光阑。需要注意的是,并不是最小尺寸的光阑为孔径光阑,因为光在穿过镜筒时,光阑前后的镜片可能放大或缩小光阑的实际尺寸。
在这里插入图片描述
基于孔径光阑,定义了两个重要的虚拟光阑:入瞳(ENP)和出瞳(EXP)。入瞳决定镜头入口可接收的光线面积,是孔径光阑被其前面的光学系统在物方所成的像,通常为虚像。出瞳是孔径光阑被后面的光学系统在像方所成的像,通常为虚像。
主入射光线经过入瞳ENP中心Q,在主平面交点的反向延长线经过出瞳EXP中心Q’,如下图,这里入射角w和出射角w’也是不一样的:
在这里插入图片描述

模型转换

针孔模型中只有一个投影中心,但厚透镜模型中有两个,分别是入瞳和出瞳,同时两个角度w和w’也是不一样的,为了两个w角度一致,且物方w角度不变(因为它取决于物方被测物体的尺寸),我们只能将出瞳移动到入瞳位置(Q’移动到Q上),此时w和w’角度一致。同时我们还需要将像平面虚拟的移动到与入瞳中心距离为c的位置,来保证像平面大小不变。c为主距,也就是halcon相机标定时输入的焦距f,注意这里的主距和f’不相同。
在这里插入图片描述
出瞳移动到入瞳,像平面移动到虚拟像平面的示意图:
在这里插入图片描述
此时,厚透镜模型变转换为了由虚拟像平面、投影中心和物平面构成的针孔模型,影响最关键的参数其实是主距c。
移动后满足下面的等式:
在这里插入图片描述

总结

说了这么多到底有什么用呢,对于普通镜头,我们可以了解到标定出的焦距其实是主距。而对于其他镜头,我认为关键是初始值的选取,尤其是沙姆标定中,我们可以基于镜头参数,推导出理论初始值进行标定,然后控制标定的结果在理想的范围内是非常关键的。
注意这里用的是halcon中的模型转换,opencv中的并没有说明它的模型怎么定义的,但我们用halcon的模型去套用应该也是没问题的。

坐标系转换

接下来是喜闻乐见的坐标系转换了,相信大家都从其他地方也看过很多,这里总结一下容易混淆及懵逼的几个点。
首先列一下坐标系图:
在这里插入图片描述

在这里包含了下面几个坐标系:

  • 图像坐标系 O 0 u v O_{0}uv O0uv,就是我们在屏幕看到的图像,它有一个中心点一般在左上角(0,0),单位是像素;
  • 成像坐标系 O 1 u v O_{1}uv O1uv,在CMOS平面内,它的中心点是光轴和CMOS平面交点,是通过像元长度计算出单位为mm或m的坐标系;
  • 相机坐标系 O 1 X c Y c Z c O_{1}X_{c}Y_{c}Z_{c} O1XcYcZc,它的中心即是投影中心,Zc和光轴重合,Xc和Yc和成像坐标系x轴y轴平行,单位也是mm或m;
  • 世界坐标系 O w X w Y w Z w O_{w}X_{w}Y_{w}Z_{w} OwXwYwZw,它的中心即某个标定板确定的中心,单位也是mm或m。
  • 针孔模型中,要求物点、投影中心和像点必须在同一条直线上。

下面开始公式推导,首先假设成像坐标系原点 O 1 O_{1} O1在图像坐标系中的坐标为 ( u 0 , v 0 ) (u0,v0) (u0,v0),像元物理尺寸为 S x , S y S_{x},S_{y} Sx,Sy,镜头焦距(其实是主距)为 f f f,在图像坐标系中取一点 ( u , v ) (u,v) (u,v)

  • 图像坐标系–>成像坐标系
    图像坐标系点 u , v {u,v} u,v,成像坐标系点 ( x , y ) (x,y) (x,y)
    [ u v 1 ] = [ 1 S x 0 u 0 0 1 S y v 0 0 0 1 ] [ x y 1 ] \begin{bmatrix}u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} \frac{1}{S_{x}} & 0 & u_{0}\\ 0 & \frac{1}{S_{y}} & v_{0}\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}x \\ y \\ 1 \end{bmatrix} uv1 = Sx1000Sy10u0v01 xy1 (1)

  • 成像坐标系 – > 相机坐标系【容易理解错】
    注意,这里的变换是透视投影变换,针对的是两个实际点转到相机坐标系中的变换:

一个是成像坐标系中,CMOS表面的物理点 ,转到相机坐标系中即 ( x , y , f ) (x,y,f) (x,y,f)
一个是世界坐标系中,物体表面对应的物理点,在相机坐标系中即 ( X c Y c Z c ) (X_{c}Y_{c}Z_{c}) (XcYcZc)
目标是将前者转到后者,因为成像坐标系中心和相机坐标系中都在光轴上,可以将该投影变换看成相似三角形的转换:

在这里插入图片描述
转换公式如下:
( Z c [ x y 1 ] = [ f 0 0 0 0 f 0 0 0 0 0 1 ] [ X c Y c Z c 1 ] ) ( Z_{c}\begin{bmatrix}x \\ y \\ 1 \end{bmatrix} = \begin{bmatrix} f & 0 & 0 & 0\\ 0 & f & 0 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}X_{c} \\ Y_{c} \\ Z_{c} \\ 1 \end{bmatrix} ) (Zc xy1 = f000f0000001 XcYcZc1 ) (2)
这里的 Z c Z_{c} Zc我们一般称为尺度因子,反正最后会被约掉。

  • 相机坐标系 --> 世界坐标系
    这个变换是说世界坐标中的物理点,从相机坐标转到世界坐标系中,是一个旋转平移的变换:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    综上,整体的变换关系如下:
    在这里插入图片描述
    在这里插入图片描述

这里 M 1 M_{1} M1为内参矩阵, M 2 M_{2} M2为平移旋转矩阵,即我们说的外参, Z c Z_{c} Zc可以计算中自动消除。
而这,正是张正友算法的求解核心原理:利用每组的像素坐标和世界坐标,求出射影变换矩阵 M M M,再分别求出内参和外参的初始值,进行非线性迭代优化。
. [ u v 1 ] = M [ X w Y w Z w 1 ] . .\begin{bmatrix}u \\ v \\ 1 \end{bmatrix} = M \begin{bmatrix}X_{w} \\ Y_{w} \\ Z_{w} \\ 1 \end{bmatrix} . . uv1 =M XwYwZw1 .

镜头畸变对比

镜头畸变包含了径向畸变和切向畸变,径向畸变主要由透镜产生,它的效应主要有两种:枕形和桶形,如图所示。在 CMOS 中心(光学中心)的畸变为 0,随着向边 缘移动,畸变越来越严重。切向畸变来自于透镜安装的整个过程,因为安装时很难保证透镜和成像平面平行。
在这里插入图片描述
具体的公式halcon采用的和张正友是一样的:
在这里插入图片描述
而Opencv最新版本的公式如下:
在这里插入图片描述
可以看到,右边径向畸变系数k,halcon和OpenCV是不一样的,但形式一致,切向是相同的,并且OpenCV还多了 ( s 1 s 2 s 3 s 4 ) (s_{1}s_{2}s_{3}s_{4}) (s1s2s3s4)四个参数。
经过对比验证,最关键的还不是这个,而是左右描述的畸变矫正不一致! 经过查询相关资料,

halcon中的公式等号右边是畸变点,等号左边是未畸变点,而张正友和OpenCV的正好相反。

这个不同点最终的影响不得而知,有谁知道的可以评论一下。
这个不同会导致一个问题,就是解畸变halcon和Opencv的过程是不一样的,halcon解畸变会更加简单,因为等号右边就是畸变的点,可以直接代入求解,但Opencv不是,它解畸变已知的是左边,求的是右边无畸变点,这个二元多次方程到底该怎么解呢?Opencv给出了一个解法。

Opencv解畸变

在 OpenCV 中,解畸变的函数主要包括 cv::undistort 和 cv::undistortPoints,我们这里看一下cv::undistortPoints函数,它里面最关键的是下面这段代码,两个for循环。

//遍历每个点
for( int i = 0; i < n; i++ )
    {
        double x, y, x0 = 0, y0 = 0, u, v;
        u = x; v = y;
        x = (x - cx)*ifx;
        y = (y - cy)*ify;

        if( _distCoeffs ) {
            // compensate tilt distortion
            cv::Vec3d vecUntilt = invMatTilt * cv::Vec3d(x, y, 1);
            double invProj = vecUntilt(2) ? 1./vecUntilt(2) : 1;
            x0 = x = invProj * vecUntilt(0);
            y0 = y = invProj * vecUntilt(1);

            double error = std::numeric_limits<double>::max();
            // compensate distortion iteratively

			//核心:迭代计算畸变点
            for( int j = 0; ; j++ )
            {
                if ((criteria.type & cv::TermCriteria::COUNT) && j >= criteria.maxCount)
                    break;
                if ((criteria.type & cv::TermCriteria::EPS) && error < criteria.epsilon)
                    break;
                double r2 = x*x + y*y;
                //下面这个是公式中的倒数
                double icdist = (1 + ((k[7]*r2 + k[6])*r2 + k[5])*r2)/(1 + ((k[4]*r2 + k[1])*r2 + k[0])*r2);
                if (icdist < 0)  // test: undistortPoints.regression_14583
                {
                    x = (u - cx)*ifx;
                    y = (v - cy)*ify;
                    break;
                }
                double deltaX = 2*k[2]*x*y + k[3]*(r2 + 2*x*x)+ k[8]*r2+k[9]*r2*r2;
                double deltaY = k[2]*(r2 + 2*y*y) + 2*k[3]*x*y+ k[10]*r2+k[11]*r2*r2;
                x = (x0 - deltaX)*icdist;
                y = (y0 - deltaY)*icdist;

				//解出来后再反向带回去,比较一下误差大小
                if(criteria.type & cv::TermCriteria::EPS)
                {
                    double r4, r6, a1, a2, a3, cdist, icdist2;
                    double xd, yd, xd0, yd0;
                    cv::Vec3d vecTilt;

                    r2 = x*x + y*y;
                    r4 = r2*r2;
                    r6 = r4*r2;
                    a1 = 2*x*y;
                    a2 = r2 + 2*x*x;
                    a3 = r2 + 2*y*y;
                    cdist = 1 + k[0]*r2 + k[1]*r4 + k[4]*r6;
                    icdist2 = 1./(1 + k[5]*r2 + k[6]*r4 + k[7]*r6);
                    xd0 = x*cdist*icdist2 + k[2]*a1 + k[3]*a2 + k[8]*r2+k[9]*r4;
                    yd0 = y*cdist*icdist2 + k[2]*a3 + k[3]*a1 + k[10]*r2+k[11]*r4;

                    vecTilt = matTilt*cv::Vec3d(xd0, yd0, 1);
                    invProj = vecTilt(2) ? 1./vecTilt(2) : 1;
                    xd = invProj * vecTilt(0);
                    yd = invProj * vecTilt(1);

                    double x_proj = xd*fx + cx;
                    double y_proj = yd*fy + cy;

                    error = sqrt( pow(x_proj - u, 2) + pow(y_proj - v, 2) );
                }
            }
        }

关于这个公式,右边是无畸变的,现在已知的是左侧带畸变的 x ′ ′ x^{''} x′′,右边无畸变的 x ′ x^{'} x看上去是不好求的。
在这里插入图片描述
opencv使用的是不动点迭代求解非线性方程的根(参考https://blog.csdn.net/weixin_43956164/article/details/124197614),先在最里面的for中,将已知的带畸变的强行代入公式右边,注意设第一个 x ′ x^{'} x是未知的,这样就变成了:
( x ′ ′ − 2 p 1 x ′ ′ y ′ ′ − p 2 ( r 2 + 2 x ′ 2 ) − s 1 r 2 − s 2 r 4 1 + k 1 r 2 + . . . 1 + k 4 r 2 + . . . = x ′ ) (\frac{x^{''} - 2p_{1}x^{''}y^{''}-p_{2}(r^{2}+2x^{'2}) - s_{1}r^{2} - s_{2}r^{4}}{\frac{1+k_{1}r^{2}+...}{1+k_{4}r^{2}+...}}=x^{'} ) (1+k4r2+...1+k1r2+...x′′2p1x′′y′′p2(r2+2x2)s1r2s2r4=x)
求出来的结果,再按 x ′ x^{'} x y ′ y^{'} y代入公式右侧,重新得到畸变的 x ′ ′ x^{''} x′′ y ′ ′ y^{''} y′′,然后和输入的已知进行误差求解,满足误差范围则停止。

初始值设定对比

初始值的设定是很关键的,尤其在复杂的相机模型中比如沙姆模型。这里列一下opencv和张正友标定在初始值设置时的不同:

  • 张正友
    整个过程参考链接:https://zhuanlan.zhihu.com/p/94244568?ivk_sa=1024320u
    核心就是下面三个步骤:

1)、求解内参矩阵与外参矩阵的积;
2)、求解内参矩阵;
3)、求解外参矩阵;
4)、标定畸变系数。

  • opencv
    opencv可以通过传入标记CALIB_USE_INTRINSIC_GUESS来手动控制内参和畸变的初始参数,如果不设置该标记,那么opencv会通过cvInitIntrinsicParams2D计算内参中的焦距(其中的中心位置在该函数中强行设置为了图像中心!),然后根据内参调用cvFindExtrinsicCameraParams2来计算外参,这里全局一个内参矩阵,每个图像对应一个外参,具体的方法参考的张正友但又有不同。可以参考下面两个链接,讲的很详细:
    https://blog.csdn.net/weixin_43956164/article/details/127408933
    https://blog.csdn.net/weixin_43956164/article/details/126771627

  • 总结
    张正友内参是计算得出的,opencv可以传入初始内参,也可以进行估算,两个不同点在于:
    a.opencv把中心点强行设为了图像坐标系中心,而zhang是放到内参中统一估算的;
    b.opencv由于强行让内参的中心点设置为了已知量,所以化简的出了一个ax=b的矩阵,动用cvSolve去解得方程,而zhang更通用,中心点也是求出的,得出一个ax=0的矩阵方程,可以动用svd分解a矩阵,得到UWV,则V矩阵的最后一列即为ax=0的解。

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

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

相关文章

企业微信应用文本消息

应用支持推送文本、图片、视频、文件、图文等类型&#xff0c;本篇主要实现发送应用文本消息。 获取企业凭证 发送应用消息首先需要获取调用凭证access_token&#xff0c;此处的凭证为企业凭证&#xff0c;可通过企业授权安装时返回的授权信息中获取access_token&#xff1b;之…

nexus 制品库管理

目录 一、nexus 介绍 二、nexus 支持的仓库 三、nexus 部署 四、nexus 数据备份 五、创建一个内网yum源 六、创建一个代理yum仓库 七、jenkins 使用 nexus插件 7.1 jenkins 安装插件 7.2 配置 maven 工程 7.3 查看构建和上传 一、nexus 介绍 Nexus 是一个强大的仓库管…

【重点文章】将Java程序打包成exe文件,无Java环境也可以运行(解决各种疑难杂症)

文章目录 一、将Java程序打成jar包二、将Jar打成exe三、加壳改造成安装包 编译器为IDEA 一、将Java程序打成jar包 2. 3. 你打的包一般会出现在根目录下面的out文件夹下面  当然你也可以用maven的package功能打包&#xff0c;效果是一样的   二、将Jar打成exe 使用工具e…

AD4209 双路LED、集成充电一体 可做双色温芯片调节 适用于台灯、手电筒

AD4209 是一款双路输出的可调色温的 台灯控制芯片&#xff0c;集成了锂电池充电管理模块、 LED 功能控制模块和保护模块&#xff0c;关机待机电流仅 3uA。 AD4209 为双路输出控制&#xff0c;每一路最大输出 电 流 为 1.2A 开 关 模 式 &#xff1a;CH1→CH2→CH1CH2→OFF。…

Qt MVC示例 simpletreemodel 树模型

Qt MVC示例 simpletreemodel 树模型 从文本中读取树模型数据&#xff0c;缩进代表子项 TreeItem 表示一行字符串数据 treeitem.h #ifndef TREEITEM_H #define TREEITEM_H#include <QList> #include <QVariant>//! [0] class TreeItem { public:explicit Tree…

EasyRecovery2024免费强大的电脑文件恢复软件

文件的保存一直是我们对电子化数据较为关注的一个环节&#xff0c;毕竟这是一份文件或数据的根本所在。但是在计算机操作中难免会出现有文件丢失或文件误删的现象&#xff0c;给我们的日常和工作带来不必要的困扰。 今天小编就要和大家分享一款功能超级强大的文件恢复软件&…

DCGAN 使用指南:将卷积神经网络和对抗网络结合,适用于生成小尺寸的图像

DCGAN 使用指南&#xff1a;将卷积神经网络和对抗网络结合 网络结构细节设计 论文地址&#xff1a;https://arxiv.org/abs/1511.06434 项目代码&#xff1a;https://github.com/tensorlayer/DCGAN.git DCGAN 适用于生成小尺寸的图像&#xff0c;并且具有简单易用的优势 Styl…

使用 Webshell 访问 SQL Server 主机并利用 SSRS

本文将指导您使用RDS SQL Server实例的主机账号登录和管理SQL Server Reporting Services&#xff08;SSRS&#xff09;数据库。 背景信息 RDS SQL Server提供Webshell功能&#xff0c;用户可以通过Web界面登录RDS SQL Server实例的操作系统。通过Webshell&#xff0c;用户可…

中国毫米波雷达产业分析3——毫米波雷达市场分析(1~3)

一、总体市场 &#xff08;一&#xff09;总规模 近几年&#xff0c;得益于汽车智能化的高速发展与雷达芯片制作工艺的进步&#xff0c;国内毫米波雷达整体市场增速较快。根据初步测算&#xff0c;2022年中国毫米波雷达市场总规模达到86亿元&#xff0c;实现同比增长24.6%。 图…

加密挖矿、AI发展刺激算力需求激增!去中心化算力时代已来临!

2009年1月3日&#xff0c;中本聪在芬兰赫尔辛基的一个小型服务器上挖出了比特币的创世区块&#xff0c;并获得了50BTC的出块奖励。自加密货币诞生第一天起&#xff0c;算力一直在行业扮演非常重要的角色。行业对算力的真实需求&#xff0c;也极大推动了芯片厂商的发展&#xff…

安装vmware_esxi 超详细

安装vmware_esxi 超详细 </h2><div id"cnblogs_post_body" class"blogpost-body blogpost-body-html">esxi安装手册 1、esxi介绍 ESXI原生架构模式的虚拟化技术&#xff0c;是不需要宿主操作系统的&#xff0c;它自己本身就是操作系统。因此…

Maven 进阶学习指南---setting详解

前言 当我们在开发项目时&#xff0c;有时需要用到外部依赖组件&#xff0c;例如当我们需要 Json 序列化的时候需要用到 FastJson 组件&#xff0c;我们可以通过下载对应 jar 包加载到项目中。但当一个大的项目同时需要依赖各种各样的外部服务&#xff0c;就存在着配置繁琐、依…

Ubuntu22.04 server版本关闭DHCP,手动设置ip

在Ubuntu 22.04 中&#xff0c;网络配置已迁移到 Netplan&#xff0c;因此可以使用 Netplan 配置文件来手动设置 IP 地址并关闭 DHCP。 以下是在 Ubuntu 22.04 上手动设置 IP 地址并禁用 DHCP 的步骤&#xff1a; 打开终端&#xff0c;使用 root 权限或 sudo 执行以下命令&…

004:Direct 2D离屏渲染(Qt中实现)

简介&#xff1a; 用QT开发图像显示的小程序&#xff0c;需要一些标注工具&#xff0c;由于用的是opengl渲染&#xff0c;所以就在内存中进行绘制&#xff0c;然后纹理贴图贴出去&#xff0c;发现Qt绘制的效果太差&#xff0c;且速度一般&#xff0c;于是就想着用direct2d来绘制…

48、Flink DataStream API 编程指南(3)- 完整版

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

【element-plus使用】el-select自定义样式、下拉框选项过长等问题解决

1、自定义样式 <template><el-select v-model"value" style"width: 150px"><el-option label"选项一" value"option1"></el-option><el-option label"选项二" value"option2"><…

C++ 抽象类和接口 详解

目录 0 引言1 抽象类2 接口2.1 Java与C接口的区别 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;C专栏&#x1f4a5; 标题&#xff1a;C 抽象类和接口 详解❣️ 寄语&#xff1a;书到用时方恨少&#xff0c;事非经过不知难&#xff01;&#x1f…

springboot整合easy-es实现数据的增删改查

背景 目前公司的一个老项目&#xff0c;查询贼慢&#xff0c;需要想办法提升一下速度&#xff0c;于是就想到了ES&#xff0c;现在尝试一下将ES整合到项目中来提升检索效率。 ES是基于倒排索引实现的&#xff0c;倒排索引中一个表相当于一个索引&#xff0c;表中的每条记录都…

yolov1网络结构说明

文章目录 一. 网络结构二. 网络说明1. 网络的输入2. 网络的输出(1) 5 5表示:每个网格使用两个先验框进行预测。(2) “5”表示&#xff1a;每个先验框包含的预测信息的数量。(3) 20表示&#xff1a;20个分类预测值(4) 每个网格能预测几个目标&#xff1f; 一. 网络结构 论文下…

海外储能认证标准

北美认证 UL9540 代表一个封装完整的储能系统功能安全认证&#xff0c;关注机械测试&#xff0c;电器测试和环境测试 UL9540A 关注消防本身&#xff0c;UL9540A测试主要从电池储能系统安装参数&#xff0c;安装通风要求&#xff0c;消防设施&#xff0c;消防策略和应对措施…