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

本文将从基本标定开始,结合实际工作经验,分析张正友、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 distortioncv::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.rhkb.cn/news/205706.html

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

相关文章

Linux socket编程(8):shutdown和close的区别详解及例子

在Linux中有两种操作可以终止socket间的进程通信&#xff1a;close和shutdown。但这两种函数在使用时有着不同的行为和效果。在网络编程中&#xff0c;正确地选择和使用这些操作至关重要&#xff0c;因为它们直接影响着通信的结束和资源的释放。本文将介绍close和shutdown函数&…

Alignment of HMM, CTC and RNN-T,对齐方式详解——语音信号处理学习(三)(选修二)

参考文献&#xff1a; Speech Recognition (option) - Alignment of HMM, CTC and RNN-T哔哩哔哩bilibili 2020 年 3月 新番 李宏毅 人类语言处理 独家笔记 Alignment - 7 - 知乎 (zhihu.com) 本次省略所有引用论文 目录 一、E2E 模型和 CTC、RNN-T 的区别 E2E 模型的思路 C…

mongodb基本操作命令

mongodb快速搭建及使用 1.mongodb安装1.1 docker安装启动mongodb 2.mongo shell常用命令2.1 插入文档2.1.1 插入单个文档2.1.2 插入多个文档2.1.3 用脚本批量插入 2.2 查询文档2.2.1 排序查询2.2.1 分页查询 前言&#xff1a;本篇默认你是对nongodb的基础概念有了了解&#xff…

正则表达式【C#】

1作用&#xff1a; 1文本匹配&#xff08;验证字符串&#xff09; 2查找字符串 2符号&#xff1a; . ^ $ * - ? ( ) [ ] { } \ | [0-9] 匹配出数字 3语法格式&#xff1a; / 表示模式 / 修饰符 /[0-9]/g 表示模式&#xff1a;是指匹配条件&#xff0c;要写在2个斜…

【LabVIEW学习】3.labview制作安装程序

一。生成exe文件 1.创建可执行文件 &#xff08;1&#xff09;创建项目 注意&#xff1a; 1.创建.exe文件&#xff0c;这个文件在labview环境下才可以运行&#xff0c;如果直接传递给其他电脑&#xff08;没有labview环境&#xff09;&#xff0c;他是不可以运行的。 2.如果已…

Redis-Redis 高级数据结构 HyperLogLog与事务

Redis 高级数据结构 HyperLogLog HyperLogLog(Hyper [ˈhaɪpə(r)] ) 并不是一种新的数据结构 ( 实际类型为字符串类 型) &#xff0c;而是一种基数算法 , 通过 HyperLogLog 可以利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是 IP 、 Email 、 ID 等。 如…

最大熵模型

1. 最大熵原理 学习概率模型时&#xff0c;在所有可能的概率模型(分布)中&#xff0c;熵最大的模型是最好的模型。 假设离散随机变量X的概率分布是P(X)&#xff0c;则其熵为 且满足0<H(P)<logN 当且仅当X的分布是均匀分布时右边的等号成立&#xff0c;即当X服从均匀分布…

48、Flink DataStream API 编程指南(1)- DataStream 入门示例

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

新材料制造ERP用哪个好?企业应当如何挑选适用的

有些新材料存在特殊性&#xff0c;并且在制造过程中对车间、设备、工艺、人员等方面提出更高的要求。还有些新材料加工流程复杂&#xff0c;涉及多种材料的请购、出入库、使用和管理等环节&#xff0c;解决各个业务环节无缝衔接问题是很多制造企业面临的管理难题。 新材料制造…

CSS3样式详解之圆角、阴影及变形

目录 前言一、圆角样式&#xff08;border-radius&#xff09;二、元素阴影&#xff08;box-shadow&#xff09;三、过渡动画样式&#xff08;transition&#xff09;1. transition-property(用于设置属性名称)2. transition-duration&#xff08;设置时间&#xff09;3. trans…

unity UI特效遮罩

using System.Collections; using System.Collections.Generic; using UnityEngine;/**UI特效遮罩 1.需要将ScrollRect 的遮罩Mask 换为 2D Mask2.将特效的Render里面的 Masking 设置为*/ public class UIParticleMaskControll : MonoBehaviour {// Start is called before …

Spring Cloud Stream如何屏蔽不同MQ带来的差异性?

引言 在当前的微服务架构下&#xff0c;使用消息队列&#xff08;MQ&#xff09;技术是实现服务解耦和削峰填谷的重要策略。为了保证系统的灵活性和可替换性&#xff0c;我们需要避免对单一开源技术的依赖。 市面上有多种消息队列技术&#xff0c;如 Kafka、RocketMQ、Rabbit…

uniapp2023年微信小程序头像+昵称分别获取

1、DOM <view class"m-user"><view class"user-info"><!--头像 GO--><button class"avatar avatar-wrapper" open-type"chooseAvatar" chooseavatar"onChooseAvatar"slot"right"><im…

智能手表上的音频(四):语音通话

上篇讲了智能手表上音频文件播放。本篇开始讲语音通话。同音频播放一样有两种case&#xff1a;内置codec和BT。先看这两种case下audio data path&#xff0c;分别如下图&#xff1a; 内置codec下的语音通话audio data path 蓝牙下的语音通话audio data path 从上面两张图可以看…

数字化时代的政务服务:构建便捷高效的线上政务大厅

引言&#xff1a; 随着数字化时代的来临&#xff0c;如何通过线上政务大厅搭建一个便捷高效的服务平台&#xff0c;以更好地满足公众需求值得探究。线上政务大厅是政务服务的新方式&#xff0c;但搭建线上政务大厅并不是一件容易的事情&#xff0c;需要精心的规划和设计。 一…

linux 应用开发笔记---【I/O文件/基础篇 】

文章笔记来自于【速学Linux】手把手教你学嵌入式Linux C应用编程_哔哩哔哩_bilibili 一&#xff0c;什么是linux应用程序 1.运行在linux操作系统用户空间的程序 2.内核程序运行在内核空间&#xff0c;应用程序运行在用户空间 在终端执行的命令ls,ps。。。。。。都是运行在用…

vue3实现元素拖拽移动功能

效果图 实现拖拽移动 首先我们给需要实现功能的元素加一个draggable"true"让元素能够被拖拽 先来认识两个搭配draggable属性一起使用的事件——ondragstart和ondragend&#xff0c;它们的定义分别为&#xff1a; ①. ondragstart 事件在用户开始拖动元素或选择的文…

BUUCTF [GXYCTF2019]BabyUpload 1详解(.htaccess配置文件特性)

题目环境&#xff1a;查看题目源码 SetHandler application/x-httpd-php 通过源码可以看出这道文件上传题目主要还是考察.htaccess配置文件的特性 倘若不先上传.htaccess配置文件&#xff0c;那么后台服务器就无法解析php代码 这个是需要注意的 .htaccess配置文件特性 概述来说…

python爬虫AES案例:某招聘网站

声明&#xff1a; 该文章为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;违者后果自负&#xff0c;由此产生的一切后果均与作者无关 一、找出需要加密的参数 js运行 atob(‘aHR0cHM6Ly93d3cua2Fuemh1bi5jb20vc2VhcmNoLz9xdWVyeT1weXRob24mdHlwZT0w’) 拿到网址…

基于Java web的多功能游戏大厅系统的开发与实现

摘 要 目前&#xff0c;国内游戏市场上的网络游戏有许多种类&#xff0c;游戏在玩法上也越来越雷同&#xff0c;形式越来越单调。这种游戏性系统给玩家带来的成就感虽然是无穷的&#xff0c;但是也有随之而来的疲惫感&#xff0c;尤其是需要花费大量的时间和精力&#xff0c;这…