一次实践:给自己的手机摄像头进行相机标定

news2024/11/17 6:55:35

文章目录

  • 1. 问题引入
  • 2. 准备工作
    • 2.1 标定场
    • 2.2 相机拍摄
  • 3. 基本原理
    • 3.1 成像原理
    • 3.2 畸变校正
  • 4. 标定解算
    • 4.1 代码实现
    • 4.2 详细解析
      • 4.2.1 解算实现
      • 4.2.2 提取点位
    • 4.3 解算结果
  • 5. 问题补充

1. 问题引入

不得不说,现在的计算机视觉技术已经发展到足够成熟的阶段了,还记得笔者刚工作的时候,相机标定还是个很神秘的技术,只有少数专业人员能够做,网上也找不到什么相关的资料。但是现在相机标定已经是一个非常普遍的技术了,也有不少的资料的可以参考,因此笔者突发奇想,既然那些大部头的相机可以标定,那么我们使用的手机摄像头一定也可以标定。因此,笔者就记录一下给自己手机摄像头的具体实践,算是弥补下当年没有学习到该技术的遗憾,毕竟要学习一项技术最好的办法就是亲自实践一下。

2. 准备工作

2.1 标定场

笔者见过不少正规的标定场,有的标定场很大,有很多带有标志物的竖条,还带有载动相机设备的轨道。不过目前比较流行且成本最低的办法就是使用棋盘格标定板了,也就是所谓的张正友标定法。

那么棋盘格标定板哪里来呢?打印到纸上倒是一个办法,不过可能有两个问题,一个是打印后每个格子的尺寸需要换算一下,由像素换成米制单位,这可能不是一个整数;另一个就是得找一面墙来贴上去,要贴的光滑平整还是挺难的。因此笔者没有选择这个办法,最后还是通过网上购物找的标定板。由于是给手机摄像头传感器尺寸都不是太大,标定板也不用选择太大,笔者最终选用的标定板尺寸如下所示:

图1:标定板尺寸

每个格子是5毫米,一共12X9个格子,整体尺寸还是比较小巧的,大概就一个手掌心大小。材质是玻璃基板,成本大概是50元左右。这个尺寸笔者实际体验还是有点偏小的,不过再大成本就上来了,建议有财力的同学可以适当选择大一点。

2.2 相机拍摄

接下来就是用手机摄像头对棋盘格标定板进行拍摄了。理论上进行标定解算只需要6组控制点就可以了,但是因为识别的控制点都是有误差的,需要多组点位来进行求解以提升精度。只拍摄一张照片获得的控制点也不太够,通常还需要获取多张照片上的控制点,避免局部最优的问题,提高解算过程的可靠性。如果可以的话,要使用多个视角、多个不同距离的标定板照片,同时最好保证标定板覆盖整个图像平面的不同区域,这样可以更好地估计畸变和其他参数。

在这里笔者拍摄了6张棋盘格标定板的图片,分别是前、后、左、右、上、下6个不同的位置和视角,如下所示:

图2:拍摄的棋盘格图片

可以看到拍摄的标定板区域都太靠中间了,不过也是没办法,使用的标定板尺寸确实有点偏小。拍摄的时候一旦靠的很近,手机拍照程序就会自动切换成近景拍摄。笔者不太确定切换成近景拍摄之后会不会修改相机的参数,所以都没有靠的很近。但是太远了拍照又有点糊,只能使用目前这样的效果。

现在很多手机拍照的功能会自动修正照片,比如滤镜,广角矫正等等,这些功能都尽量关了或者不使用。另外,拍照过程不要进行调焦,具体来说相机上会有0.6x、1x、2x、3x这样的参数,这代表变焦倍率,使用原始倍率(1x)进行标定即可。自动对焦功能当然也要关闭,保持镜头和焦平面的位置不变。

还有个问题是保持手机不动移动标定板来拍摄照片,还是保持标定板不动移动手机来拍摄照片?应该来说,两者原理上都可以实现,但是标定板不动,相机移动更常见一点,因为实现起来更见简单。笔者就是将棋盘格标定板通过双面胶粘在墙上实现的,也算是组成了一个成本最低的微型标定场了。

其实笔者也试过将标定板放在桌面上来拍摄,不过在室内拍摄很容易在照片上有影子,还是固定在墙上比较好一点。而且最好放采光比较好的墙面上,在白天日照充足的时候进行拍摄,以便获得最好的拍摄效果。

3. 基本原理

3.1 成像原理

相机标定虽然解算的是内参,但是其实连外参也解算了,因为相机标定解算使用的相机成像原理,这个过程中内参和外参会一起参与解算。在不考虑畸变的情况下,相机的成像原理可用下式(1)来表示:

s [ u v 1 ] = K [ R ∣ t ] [ X w Y w Z w 1 ] (1) s \begin{bmatrix} u\\ v\\ 1\\ \end{bmatrix} = K \begin{bmatrix} R|t\\ \end{bmatrix} \begin{bmatrix} X_w\\ Y_w\\ Z_w\\ 1\\ \end{bmatrix} \tag{1} s uv1 =K[Rt] XwYwZw1 (1)

在这个式子中:

  • [ X w Y w Z w ] T {\begin{bmatrix}X_w & Y_w & Z_w\\\end{bmatrix}}^T [XwYwZw]T表示世界空间中的三维点,也称为物方点。
  • [ u v ] T {\begin{bmatrix}u & v\\\end{bmatrix}}^T [uv]T表示图像平面上的像素坐标,也称为像点。
  • [ R ∣ t ] \begin{bmatrix}R|t\\\end{bmatrix} [Rt]是相机的外参矩阵。具体来说,就是旋转变换和平移变换的组合, R R R就是3X3的旋转矩阵, t t t则是一个3列维向量。由于旋转变换可以用欧拉角来表示,因而也可以表示成3维向量。3个旋转量,3个平移量,这就是相机的6个外参的由来。
  • K K K是相机的内参矩阵,通常表示为下式(2):
    K = [ f x 0 c x 0 f y c y 0 0 1 ] (2) K = \begin{bmatrix} f_x & 0 & c_x\\ 0 & f_y & c_y\\ 0 & 0 & 1\\ \end{bmatrix} \tag{2} K= fx000fy0cxcy1 (2)
    • f x f_x fx f y f_y fy分别是水平方向和垂直方向的焦距,单位为像素。
    • c x c_x cx c y c_y cy是像主点(即成像平面的光轴交点)坐标,单位为像素。
  • s s s是比例因子,这个参数是为了实现齐次坐标的转换,将其次三维坐标需要转为二维坐标。

以笔者的见识来说,上述相机成像原理其实与其他学科的一些知识有类似的地方:

  1. 计算机图形学。图形渲染中的几何变换,包含模型(model)变换、视图(view)变换和投影(projection)变换 ,合起来就是通常所说的MVP矩阵。模型变换包括旋转变换和平移变换,视图变换又是模型变换的逆变换,对应的就是式(1)的外参矩阵 [ R ∣ t ] \begin{bmatrix}R|t\\\end{bmatrix} [Rt]。不过投影矩阵有所不同,式(1)的内参矩阵 K K K是将点从相机坐标系转换为图像坐标系,图形渲染中的投影矩阵则是将点从将点从相机坐标系转换为裁剪坐标系。

  2. 摄影测量学。在摄影测量学中,这一套成像原理的公式被总结为共线方程,除了表示的形式不同,最显著的不同是内参只有三个:焦距和像主点二维坐标。这个公式个人认为并不太直观,但是比较容易进行平差计算。

如果有以上两者经验的读者,可以对照着进行理解,虽然它们看起来有点差异,但是笔者确定它们的原理都是一样的,都是基于空间的几何变换,只不过是应对于不同情况有不同的描述。

3.2 畸变校正

以上成像原理没有考虑到畸变的影响。为什么会产生畸变呢?很简单,相机镜头不是完美的平面光学系统,光线在传输时发生复杂的弯曲,这会导致图像中的直线在图像边缘发生扭曲。常见的畸变有径向畸变和切向畸变。

畸变校正看起来很玄乎,其实说穿了也非常简单,我们只需要理解一点,畸变校采用的有理函数的模型。所谓有理函数的模型,就是将校正前的位置x与校正后的位置y使用一个高阶多项式(形如 y = a x 3 + b x 2 + c x + d y=ax^3+bx^2+cx+d y=ax3+bx2+cx+d)来进行表示,没有什么物理上的原理,就是纯采用数学方式进行拟合,最后得到了每个高阶项的系数(a,b,c,d)。

鉴于畸变校正会增加对标定解算的复杂度,这里就不进行进一步论述了。对于初学者来说,理解成像原理的公式(1)更为关键一点。

4. 标定解算

4.1 代码实现

使用上述介绍的基本原理就可以进行标定解算了,不过解算方法比较复杂,我们还是结合具体的实现来解释,代码如下所示,这里主要使用了OpenCV库:

#include <filesystem>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>

#ifdef _WIN32
#include <Windows.h>
#endif

using namespace cv;
using namespace std;

int main() {
#ifdef _WIN32
  SetConsoleOutputCP(65001);
#endif

  vector<std::filesystem::path> imgPaths = {
      "C:/Work/CalibrateCamera/Data/front.jpg",
      "C:/Work/CalibrateCamera/Data/left.jpg",
      "C:/Work/CalibrateCamera/Data/right.jpg",
      "C:/Work/CalibrateCamera/Data/up.jpg",
      "C:/Work/CalibrateCamera/Data/down.jpg",
      "C:/Work/CalibrateCamera/Data/back.jpg"};
  size_t imageNum = imgPaths.size();

  // 定义棋盘格尺寸 (内角点数)
  int boardWidth = 11;  // 列数
  int boardHeight = 8;  // 行数
  cv::Size boardSize(boardWidth, boardHeight);

  double cellSize = 0.005;

  Size imageSize(3072, 4096);  // 图像尺寸

  // 准备标定所需的物方点和像方点
  vector<vector<Point3f>> objectPoints(imageNum);  // 多张图像的3D物方点
  vector<vector<Point2f>> imagePoints(imageNum);   // 多张图像的2D像方点

  for (size_t ii = 0; ii < imageNum; ++ii) {
    // 加载棋盘格图像
    cv::Mat image = cv::imread(imgPaths[ii].string().c_str());
    if (image.empty()) {
      std::cerr << "Error: Could not load image!" << std::endl;
      return -1;
    }

    // 存储角点坐标
    std::vector<cv::Point2f> corners;

    // 转换图像为灰度
    cv::Mat grayImage;
    cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);

    // 寻找棋盘格角点
    // cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE
    bool found = cv::findChessboardCorners(grayImage, boardSize, corners,
                                           cv::CALIB_CB_FAST_CHECK);

    // 如果找到角点,进行进一步处理
    if (found) {
      std::cout << "Chessboard corners found!" << std::endl;

      // 增加角点的精度
      cv::cornerSubPix(
          grayImage, corners, cv::Size(11, 11), cv::Size(-1, -1),
          cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::MAX_ITER,
                           30, 0.001));

      // 绘制角点
      std::string cornerImgPath = imgPaths[ii].parent_path().generic_string() +
                                  "/corner/" + imgPaths[ii].stem().string() +
                                  "_corner" + imgPaths[ii].extension().string();
      cv::drawChessboardCorners(image, boardSize, corners, found);
      cv::imwrite(cornerImgPath.c_str(), image);

      cout << corners.size() << endl;
      imagePoints[ii].resize(corners.size());

      for (size_t ci = 0; ci < corners.size(); ++ci) {
        imagePoints[ii][ci] = corners[ci];
      }

      objectPoints[ii].resize(corners.size());
      for (int hi = 0; hi < boardHeight; ++hi) {
        for (int wi = 0; wi < boardWidth; ++wi) {
          int ci = hi * boardWidth + wi;
          objectPoints[ii][ci].x = cellSize * wi;
          objectPoints[ii][ci].y = cellSize * hi;
          objectPoints[ii][ci].z = 0;
        }
      }
    } else {
      std::cerr << "Chessboard corners not found!" << std::endl;
    }
  }

  // 内参矩阵和畸变系数
  Mat cameraMatrix = Mat::eye(3, 3, CV_64F);  // 初始化为单位矩阵
  Mat distCoeffs = Mat::zeros(8, 1, CV_64F);  // 初始化为零

  // 外参的旋转和位移向量
  vector<Mat> rvecs, tvecs;

  // 执行标定
  double reprojectionError =
      calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix,
                      distCoeffs, rvecs, tvecs);

  cout << u8"重投影误差:" << reprojectionError << endl;
  cout << u8"内参矩阵:" << cameraMatrix << endl;
  cout << u8"畸变系数:" << distCoeffs << endl;

  return 0;
}

4.2 详细解析

4.2.1 解算实现

代码实现的步骤很简单,就是通过函数findChessboardCorners提取棋盘格图片的角点,将其传入calibrateCamera函数中,就得到了最终的解算成果,也就是内参矩阵。这其中的关键就在于calibrateCamera这个函数,我们可以看一下它的函数原型:

CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,
                                     InputArrayOfArrays imagePoints, Size imageSize,
                                     InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
                                     OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
                                     int flags = 0, TermCriteria criteria = TermCriteria(
                                        TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) );

其参数详解如下:

  • objectPoints:3D空间中的物方点坐标集合,也就是公式(1)中的 [ X w Y w Z w ] T {\begin{bmatrix}X_w & Y_w & Z_w\\\end{bmatrix}}^T [XwYwZw]T。由于是多张图片的多组点的集合,所以它的类型实际是std::vector<std::vector<cv::Point3f>>
  • imagePoints:图像中的像素坐标集合,对应公式(1)中的 [ u v ] T {\begin{bmatrix}u & v\\\end{bmatrix}}^T [uv]T,类型同样应该也是双重数组std::vector<std::vector<cv::Point2f>>
  • imageSize:输入图像的尺寸(宽度和高度),单位为像素。
  • cameraMatrix:输出的摄像机内参矩阵,也就是公式(1)中的 K K K,为3X3矩阵。
  • distCoeffs:输出的摄像机的畸变系数,通常为1X5或1X8的向量,包含径向和切向畸变系数。
  • rvecs:输出的旋转向量集合,可以转换成公式(1)中的 R R R。每个旋转向量对应一个图像,所以类型是std::vector<cv::Mat>
  • tvecs:输出的平移向量集合,对应公式(1)中的 t t t。每个平移向量对应一个图像,类型也是std::vector<cv::Mat>
  • 返回值:标定的重投影误差,用于衡量标定结果的精确度。误差越小,标定结果越准确。

通过对calibrateCamera函数的解析,相信读者就很容易明白为什么笔者要先讲公式(1)的成像原理。这个解算参数的输入输出都是根据公式(1)来的,不过另一个问题来了,输入的物方点和像方点是怎么来的呢?

4.2.2 提取点位

答案很简单,就是棋盘格上的角点。棋盘格由黑白相间的格子组成,所以它的角点是很容易提取的;另外一方面,棋盘格也是规整的,只要每个格子的尺寸都是一样,就很容易知道物方坐标。理论上,只要对图像提取角点,然后剔除掉非棋盘的角点就可以作为相机标定的像点了。不过,OpenCV提供了更进一步的接口findChessboardCorners,直接输入棋盘格的内角点个数,就可以自动检测出像点。如下图所示在一张图片上笔者提取的像点:

图3: 提取棋盘格的角点作为像点

正如上图所示,findChessboardCorners提取的是内角点,例如12X9的棋盘格,提取的内角点是11X8个,并且结果是按照从左到右,从上往下进行排序的。为什么要这么排序呢?因为很容易帮我们算出物方点。在相机标定这个应用中,相机的外参是不重要的,因此我们可以就以棋盘格标定板的左上角作为世界坐标系的原点,第1个点的坐标是(0,0,0),第2个点的坐标是(0.005,0,0),第3个点坐标是(0.010,0,0)…第12个点坐标是(0,0.005,0),第13个点坐标是(0.005,0.005,0)…就这么依次类推得到所有角点对应的世界空间坐标系坐标。

另外一点要提醒读者的是,findChessboardCorners这里我配置的是参数是cv::CALIB_CB_FAST_CHECK,是一种快速算法,cv::CALIB_CB_ADAPTIVE_THRESH和cv::CALIB_CB_NORMALIZE_IMAGE会对图像作预处理,能够增加提取棋盘格角点的稳健性。但是我实际使用发现程序卡住了,不知道是效率很低还是OpenCV的问题,就没有使用这两个选项。

4.3 解算结果

最终,笔者的结算结果如下所示:

重投影误差:0.166339
内参矩阵:[2885.695162446343, 0, 1535.720945173723;
 0, 2885.371543143629, 2053.122840953737;
 0, 0, 1]
畸变系数:[0.181362004467736;
 -3.970106972775221;
 0.0005157812878172198;
 0.0004644406171824815;
 23.559069196518]

解算的结果重投影误差是0.166339,表示每个物体点在重新投影到图像上时与实际检测到的角点位置的误差为0.166339像素。通常来说,这样的误差已经算是非常小,表明标定结果较为精确。

不过笔者还考虑一个问题,误差为0.166339像素,那么具体是多少米呢?以前做测绘软件的时候,平差的结果也是以像素为单位,总会有客户对我发起灵魂拷问:那具体是多少米呢?这次笔者也关注了一下这个问题,个人认为在相机标定这样的应用场景,确实无法直接使用物理单位表示精度,因为这个算法的结果就在于重投影到图像上的像素差为量度,这一点与相机外参的定向的误差量度有所不同。

对照内参矩阵,可得解算的焦距是 f x = 2885.695 f_x=2885.695 fx=2885.695 f y = 2885.372 f_y=2885.372 fy=2885.372,单位也是像素。那么这个焦距换算成物理单位是多少米呢?根据笔者查找的资料显示,焦距在像素和毫米之间的转换公式如下所示:
焦距(毫米) = 焦距(像素) × 传感器尺寸(毫米) 图像分辨率(像素) 焦距(毫米)= \frac{焦距(像素)×传感器尺寸(毫米)}{图像分辨率(像素)} 焦距(毫米)=图像分辨率(像素)焦距(像素)×传感器尺寸(毫米)

也就是说与相机传感器尺寸有关,不过关于传感器尺寸的描述有点蛋疼,比如网上显示我手机摄像头的传感器是1/1.49英寸,这通常表示传感器的对角线长度。可以根据对角线长度加上宽高比(例如4:3还是16:9)算出相机传感器的物理尺寸,进而知道具体物理单位的焦距值大小。不过传感器的对角线长度标称值和真实物理尺寸之间,会因为行业惯例和历史标准有所差异,所以算出来的也不一定正确,最好还是联系官方来确定。不过,标定出像素单位的焦距已经足够后续满足后续的使用场景了,笔者这里也就是寻根究底一下。

5. 问题补充

最后,补充一些没搞定或者暂时没理解的问题吧:

  1. 关于成像原理列出的公式(1)的内参矩阵部分,其实笔者也没弄清楚为什么将焦距分成X方向上的 f x f_x fx和y方向上的 f y f_y fy,有些资料上的内参矩阵并不是这么列的,《摄影测量学》教材上列出的共线方程更是只有一个焦距值 f f f
  2. 笔者记得似乎有个操作“相机重标定”,可以将使用固定焦距 f f f,调整像主点到图像中心,以及消除畸变的重投影,可以简化后续的空间计算,使得计算更为便捷。时间关系就留待后续研究了。
  3. 本文笔者并没有具体解释解算的算法原理,因为这不是一两句话就能说清楚的,在测绘学中有个过程有个专门的名词叫做平差;或者叫做状态估计、最大似然估计、非线性优化等等,至少我们需要知道最小二乘法原理才能继续论述这个,就留待后续的文章中进行讨论吧。

列出一些文章以供参考:

  1. 相机标定:从入门到实战
  2. 相机系列——相机标定简述
  3. 相机标定之张正友标定法数学原理详解
  4. 计算机视觉----相机标定

本文源代码和数据地址

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

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

相关文章

Python画笔案例-067 绘制配乐七角星

1、绘制橙子 通过 python 的turtle 库绘制 配乐七角星,如下图: 2、实现代码 绘制 配乐七角星 ,以下为实现代码: """配乐七角星.py本程序需要coloradd模块支持,安装方法:pip install coloradd""" import turtle from coloradd import color…

制造企业如何提升项目管理效率?惠科股份选择奥博思PowerProject项目管理系统

全球知名的显示方案综合服务商 - 惠科股份有限公司与北京奥博思达成合作&#xff0c;基于奥博思 PowerProject 搭建企业级项目管理平台。满足惠科多产品多业务领域的项目全周期管理。助力企业在技术研发、产品创新等方面继续取得行业领先优势。 同时&#xff0c;PowerProject …

如何进行u盘拷贝文件管控?5个方法一文详情告诉你!

小李&#xff1a;老王&#xff0c;最近我们部门经常提到数据安全的问题&#xff0c;特别是U盘拷贝文件带来的风险。 你有什么好办法可以管控一下吗&#xff1f; 老王&#xff1a;小李啊&#xff0c;你问对人了。 U盘拷贝文件管控确实是个头疼的问题&#xff0c;但我们可以从…

C++入门day5-面向对象编程(终)

C入门day4-面向对象编程&#xff08;下&#xff09;-CSDN博客 本节是我们面向对象内容的最终篇章&#xff0c;不是说我们的C就学到这里。如果有一些面向对象的基础知识没有讲到&#xff0c;后面会发布在知识点补充专栏&#xff0c;全都是干货满满的。 https://blog.csdn.net/u…

【中级通信工程师】终端与业务(九):市场细分与选择

【零基础3天通关中级通信工程师】 终端与业务(九)&#xff1a;市场细分与选择 本文是中级通信工程师考试《终端与业务》科目第九章《市场细分与选择》的复习资料和真题汇总。本章的核心内容涵盖了市场细分的概念与方法、目标市场选择策略以及市场定位的原则和步骤。通过本节的…

​fl studio21.2.3.4004中文版永久2024最新下载安装图文详细使用教程​

随着数字音乐制作的快速发展&#xff0c;越来越多的音乐制作软件涌现出来&#xff0c;而FL Studio无疑是其中的佼佼者。作为一款功能强大、易于上手的音乐制作软件&#xff0c;FL Studio V21中文版在继承了前代版本优秀基因的基础上&#xff0c;进一步提升了用户体验&#xff0…

用于MRI重建的具有全局感受野的傅里叶卷积块|文献速递--基于多模态-半监督深度学习的病理学诊断与病灶分割

Title 题目 Fourier Convolution Block with global receptive field for MRI reconstruction 用于MRI重建的具有全局感受野的傅里叶卷积块 01 文献速递介绍 从欠采样的磁共振成像&#xff08;MRI&#xff09;信号中重建图像可以显著减少扫描时间并改善临床实践。然而&…

rk3588S 调试USB摄像头

问题: 客户的 usb 摄像头 接上 板卡上的 USB2.0 的接口是可以的,但是 接上 typec 接口上的 OTGUSB的时候 ,就会出现,无法识别USB的问题。 情况的说明: 先来看一下硬件。 这里的 typec 接口实际上 只用到了 otg USB的 两根线, 也就是 把TYPEC 当做 USB2.0 来用了。(通…

Cannot read properties of undefined (reading ‘upgrade‘)

前端开发工具&#xff1a;VSCODE 报错信息&#xff1a; INFO Starting development server...10% building 2/2 modules 0 active ERROR TypeError: Cannot read properties of undefined (reading upgrade)TypeError: Cannot read properties of undefined (reading upgrade…

vxe-table制作高亮刷新功能

start 记录一下 vxe-table 实现表格新增数据背景闪烁功能。 1. 效果 2. demo代码 <template><div id"app"><div click"tomato">点我新增数据 lazy_tomato</div><vxe-grid refxTable :height"height" :columns&quo…

原文翻译:Make Skeleton-based Action Recognition Model Smaller, Faster and Better

全网没找到一个完整的翻译&#xff0c;用chatgpt翻译如下&#xff0c;可能有的地方不够准确&#xff0c;推荐结合原文对照着看更。 摘要 尽管基于骨架的动作识别在近年来取得了巨大的成功&#xff0c;但大多数现有方法可能面临模型规模庞大和执行速度缓慢的问题。为了解决这个…

Apifox 9月更新|「动态值」全新升级、跨团队引用接口和测试场景、测试报告交互优化

Apifox 新版本上线啦&#xff01;&#xff01;&#xff01; 看看本次版本更新主要涵盖的重点内容&#xff0c;有没有你所关注的功能特性&#xff1a; 「动态值」全新升级 更强大、更灵活的数据模拟能力 支持智能代码补全动态值 测试报告交互优化 支持跨团队引用接口和测试场…

LLM大模型学习:开源大模型技术路线及趋势

MLNLP社区是国内外知名的机器学习与自然语言处理社区&#xff0c;受众覆盖国内外NLP硕博生、高校老师以及企业研究人员。 社区的愿景是促进国内外自然语言处理&#xff0c;机器学习学术界、产业界和广大爱好者之间的交流和进步&#xff0c;特别是初学者同学们的进步。 转载自…

数电基础(组合逻辑电路+Proteus)

1.组合逻辑电路 1.1组合逻辑电路的分析 1.1.1组合逻辑电路的定义 组合逻辑电路的定义 &#xff08;1&#xff09;对于一个逻辑电路&#xff0c;其输出状态在任何时刻只取决于同一时刻的输入状态&#xff0c;而与电路的原来状态无关&#xff0c;这种电路被定义为组合逻辑电路…

MySQL 之索引详解

想象一下&#xff0c;你正在图书馆寻找一本关于 MySQL 索引的书。图书馆里有成千上万本书&#xff0c;但没有目录。你只能一排一排、一本一本地找&#xff0c;直到找到你想要的书。这将会花费大量的时间&#xff01;数据库索引就像图书馆的目录一样&#xff0c;可以帮助数据库系…

什么是智享AI直播(三代)?一文带你全面解析!

什么是智享AI直播&#xff08;三代&#xff09;&#xff1f;一文带你全面解析&#xff01; 在当今这个数字化飞速发展的时代&#xff0c;技术的每一次革新都深刻地改变着我们的生活与工作方式。随着人工智能&#xff08;AI&#xff09;技术的不断成熟与普及&#xff0c;智享AI…

【mysql】千万级数据MySQL索引优化实例

【mysql】千万级数据MySQL索引优化实例 【一】场景描述【二】生成数千万条记录【三】原始sql分析【四】第一次优化&#xff1a;常规索引【五】第二次优化&#xff1a;覆盖索引【六】第三次优化&#xff1a;减少数据量【七】第四次优化&#xff1a;小表驱动大表【八】第五次优化…

蓝桥杯模块二:数码管的静态、动态实现

模块二训练 1.静态显示 一、数码管电路图 二、电路分析 1.数码管电路分析 端口分公共端和段码&#xff0c;先用公共端控制一个数码管&#xff0c;再用段码实现显示数字。共阳数码管公共端输入高电平&#xff0c;段码输入低电平实现点亮 2.锁存器 Y7控制段码&#xff0c;Y6控…

机器学习学习笔记-20240927

文章目录 一些简单的指令数据操作广播机制 标量&#xff0c;向量&#xff0c;矩阵的相互求导1. 标量对标量的求导2. 标量对向量的求导3. 向量对标量的求导4. 向量对向量的求导5. 矩阵对标量的求导6. 矩阵对向量的求导 链式求导法则YYDS求出损失函数偏导为0时的最优解w*1. 损失函…

卷轴模式商城APP开发指南

卷轴模式商城APP的开发是一项融合了技术创新、用户体验优化与商业策略实施的综合性工程。本文将从程序员的角度出发&#xff0c;详细介绍该类型应用的开发流程&#xff0c;涵盖从需求分析到后期维护的各个环节。 一、需求分析 首先&#xff0c;明确APP的核心功能需求&#xff…