• 【opencv】教程代码 —TrackingMotion 角点检测


    ebbadc4e7caf29b84fdf9882650b1ce5.png

    • 角点检测

    • 执行角点检测并在可能的角点周围画一个圆

    • 对图像中的角点位置进行检测和细化

    • Shi-Tomasi方法检测图像角点

    1. cornerDetector_Demo.cpp 角点检测

    5ff061abce9e5c679e55087945d609af.png

    ca67abad1284943248525fe1d34aa94b.png

    1. /**
    2. * @function cornerDetector_Demo.cpp
    3. * @brief Demo code for detecting corners using OpenCV built-in functions
    4. * 使用 OpenCV 内置函数进行角点检测的示例代码
    5. * @author OpenCV team
    6. */
    7. #include "opencv2/highgui.hpp" // 包含OpenCV图形界面高级操作的头文件
    8. #include "opencv2/imgproc.hpp" // 包含OpenCV图像处理的头文件
    9. #include // 包含标准输入输出流的头文件
    10. using namespace cv; // 使用cv命名空间
    11. using namespace std; // 使用std命名空间
    12. /// 全局变量定义
    13. Mat src, src_gray; // 原图和转换为灰度图的图像
    14. Mat myHarris_dst, myHarris_copy, Mc; // Harris算法结果、副本和M矩阵
    15. Mat myShiTomasi_dst, myShiTomasi_copy; // Shi-Tomasi算法结果和副本
    16. int myShiTomasi_qualityLevel = 50; // Shi-Tomasi算法质量等级
    17. int myHarris_qualityLevel = 50; // Harris算法质量等级
    18. int max_qualityLevel = 100; // 最大质量等级
    19. double myHarris_minVal, myHarris_maxVal; // Harris算法最小和最大值
    20. double myShiTomasi_minVal, myShiTomasi_maxVal; // Shi-Tomasi算法最小和最大值
    21. RNG rng(12345); // 随机数生成器,用于产生颜色
    22. const char* myHarris_window = "My Harris corner detector"; // Harris检测器窗口名称
    23. const char* myShiTomasi_window = "My Shi Tomasi corner detector"; // Shi-Tomasi检测器窗口名称
    24. /// 函数头定义
    25. void myShiTomasi_function( int, void* ); // Shi-Tomasi算法函数
    26. void myHarris_function( int, void* ); // Harris算法函数
    27. /**
    28. * @function main
    29. */
    30. int main( int argc, char** argv )
    31. {
    32. /// 加载源图像并将其转换为灰度图
    33. CommandLineParser parser( argc, argv, "{@input | building.jpg | input image}" );
    34. src = imread( samples::findFile( parser.get( "@input" ) ) );
    35. if ( src.empty() )
    36. {
    37. cout << "Could not open or find the image!\n" << endl;
    38. cout << "Usage: " << argv[0] << " " << endl;
    39. return -1;
    40. }
    41. cvtColor( src, src_gray, COLOR_BGR2GRAY );
    42. /// 设置一些参数
    43. int blockSize = 3, apertureSize = 3; // 定义Harris矩阵和Shi-Tomasi矩阵的块大小和孔径大小
    44. /// 使用cornerEigenValsAndVecs计算Harris矩阵
    45. cornerEigenValsAndVecs( src_gray, myHarris_dst, blockSize, apertureSize );
    46. /* 计算 Harris 响应函数Mc */
    47. Mc = Mat( src_gray.size(), CV_32FC1 ); // 初始化Mc矩阵,大小与灰度图一致
    48. for( int i = 0; i < src_gray.rows; i++ ) // 遍历图像的每一行
    49. {
    50. for( int j = 0; j < src_gray.cols; j++ ) // 遍历图像的每一列
    51. {
    52. float lambda_1 = myHarris_dst.at(i, j)[0]; // 获取第一个特征值lambda_1
    53. float lambda_2 = myHarris_dst.at(i, j)[1]; // 获取第二个特征值lambda_2
    54. Mc.at<float>(i, j) = lambda_1*lambda_2 - 0.04f * ((lambda_1 + lambda_2) * (lambda_1 + lambda_2)); // 计算Mc中每个像素的Harris响应值
    55. }
    56. }
    57. minMaxLoc( Mc, &myHarris_minVal, &myHarris_maxVal ); // 寻找Mc中的最小值和最大值
    58. /* 创建窗口和滑动条 */
    59. namedWindow( myHarris_window ); // 创建一个名为"My Harris corner detector"的窗口
    60. createTrackbar( "Quality Level:", myHarris_window, &myHarris_qualityLevel, max_qualityLevel, myHarris_function ); // 创建一个滑动条以调整Harris检测器的质量等级
    61. myHarris_function( 0, 0 ); // 调用Harris检测器函数
    62. /// 使用cornerMinEigenVal计算Shi-Tomasi矩阵
    63. cornerMinEigenVal( src_gray, myShiTomasi_dst, blockSize, apertureSize ); // 直接计算灰度图的Shi-Tomasi响应值
    64. minMaxLoc( myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal ); // 寻找Shi-Tomasi响应值矩阵中的最小值和最大值
    65. /* 创建窗口和滑动条 */
    66. namedWindow( myShiTomasi_window ); // 创建一个名为"My Shi Tomasi corner detector"的窗口
    67. createTrackbar( "Quality Level:", myShiTomasi_window, &myShiTomasi_qualityLevel, max_qualityLevel, myShiTomasi_function ); // 创建一个滑动条以调整Shi-Tomasi检测器的质量等级
    68. myShiTomasi_function( 0, 0 ); // 调用Shi-Tomasi检测器函数
    69. waitKey();
    70. return 0;
    71. }
    72. /**
    73. * @function myShiTomasi_function
    74. */
    75. void myShiTomasi_function( int, void* )
    76. {
    77. myShiTomasi_copy = src.clone(); // 克隆原图用于绘制
    78. myShiTomasi_qualityLevel = MAX(myShiTomasi_qualityLevel, 1); // 确保质量等级至少为1
    79. // 遍历图像每个像素
    80. for( int i = 0; i < src_gray.rows; i++ )
    81. {
    82. for( int j = 0; j < src_gray.cols; j++ )
    83. {
    84. // 依据质量等级,判断并绘制角点
    85. if( myShiTomasi_dst.at<float>(i,j) > myShiTomasi_minVal + ( myShiTomasi_maxVal - myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel )
    86. {
    87. circle( myShiTomasi_copy, Point(j,i), 4, Scalar( rng.uniform(0,256), rng.uniform(0,256), rng.uniform(0,256) ), FILLED );
    88. }
    89. }
    90. }
    91. imshow( myShiTomasi_window, myShiTomasi_copy ); // 显示结果
    92. }
    93. /**
    94. * @function myHarris_function
    95. */
    96. void myHarris_function( int, void* )
    97. {
    98. myHarris_copy = src.clone(); // 克隆原图用于绘制
    99. myHarris_qualityLevel = MAX(myHarris_qualityLevel, 1); // 确保质量等级至少为1
    100. // 遍历图像每个像素
    101. for( int i = 0; i < src_gray.rows; i++ )
    102. {
    103. for( int j = 0; j < src_gray.cols; j++ )
    104. {
    105. // 依据质量等级,判断并绘制角点
    106. if( Mc.at<float>(i,j) > myHarris_minVal + ( myHarris_maxVal - myHarris_minVal )*myHarris_qualityLevel/max_qualityLevel )
    107. {
    108. circle( myHarris_copy, Point(j,i), 4, Scalar( rng.uniform(0,256), rng.uniform(0,256), rng.uniform(0,256) ), FILLED );
    109. }
    110. }
    111. }
    112. imshow( myHarris_window, myHarris_copy ); // 显示结果
    113. }

    这段代码是一个用于检测图像中角点的完整示例程序,使用了OpenCV库。它实现了两种角点检测方法:Harris角点检测和Shi-Tomasi角点检测。代码首先读取图像,然后将其转换为灰度图以进行处理。接下来分别计算两种方法的角点响应函数,并创建滑动条以调整检测角点的质量等级。通过滑动条调整后,程序会根据计算出的响应值和用户设定的质量等级绘制出角点。最后显示处理后带有标记角点的图像。

    cornerEigenValsAndVecs(src_gray, myHarris_dst, blockSize, apertureSize);

    f07b19a9684b8be3f52c0026b3023efe.png

    2a9c5e21319cf19fce0e1b338b38fc5c.png

    cornerMinEigenVal(src_gray, myShiTomasi_dst, blockSize, apertureSize);

    c6e367cebbd8d9a507136cec8163a635.png

    1. if( myShiTomasi_dst.at<float>(i,j) > myShiTomasi_minVal + ( myShiTomasi_maxVal - myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel )
    2. {
    3. circle( myShiTomasi_copy, Point(j,i), 4, Scalar( rng.uniform(0,256), rng.uniform(0,256), rng.uniform(0,256) ), FILLED );
    4. }

    b5e4b9dcb92903f9ceb798d3ca12466f.png

    2. cornerHarris_Demo.cpp执行角点检测并在可能的角点周围画一个圆

    e441a9bd0d9c01809b796f15fd04b519.png

    a334493244363a1e4adb3a16816ecc90.png

    该代码是一个使用Harris-Stephens方法进行角点检测的演示程序。主要实现以下功能:

    1. 读取一张图片,并将其转换为灰度图像。

    2. 创建一个窗口和一个滑动条以调整Harris角点检测的阈值。

    3. 使用Harris-Stephens角点检测算法检测图像角点。

    4. 检测到角点后,在图像上绘制圆形以标记这些角点。

    5. 在两个窗口中分别显示原始图像和检测到角点后的图像。

    1. /**
    2. * @function cornerHarris_Demo.cpp
    3. * @brief Demo code for detecting corners using Harris-Stephens method
    4. * @author OpenCV team
    5. */
    6. #include "opencv2/highgui.hpp" // 包含OpenCV图形界面头文件
    7. #include "opencv2/imgproc.hpp" // 包含OpenCV图像处理头文件
    8. #include // 包含标准输入输出流头文件
    9. using namespace cv; // 使用cv命名空间,省去cv::前缀
    10. using namespace std; // 使用std命名空间,省去std::前缀
    11. /// Global variables
    12. Mat src, src_gray; // 声明全局变量src和src_gray,存储原始图像和灰度图像
    13. int thresh = 200; // 声明全局变量thresh,定义Harris角点检测阈值
    14. int max_thresh = 255; // 定义最大阈值
    15. const char* source_window = "Source image"; // 窗口名称常量,原图窗口
    16. const char* corners_window = "Corners detected"; // 窗口名称常量,角点检测结果窗口
    17. /// Function header
    18. void cornerHarris_demo( int, void* ); // 声明函数cornerHarris_demo
    19. /**
    20. * @function main
    21. */
    22. int main( int argc, char** argv )
    23. {
    24. /// Load source image and convert it to gray
    25. CommandLineParser parser( argc, argv, "{@input | building.jpg | input image}" ); // 解析命令行参数
    26. src = imread( samples::findFile( parser.get( "@input" ) ) ); // 读取图像文件
    27. if ( src.empty() )
    28. {
    29. cout << "Could not open or find the image!\n" << endl; // 如果图像为空,输出错误信息
    30. cout << "Usage: " << argv[0] << " " << endl; // 提示使用方法
    31. return -1; // 返回错误代码,终止程序
    32. }
    33. cvtColor( src, src_gray, COLOR_BGR2GRAY ); // 将原图像转换为灰度图像
    34. /// Create a window and a trackbar
    35. namedWindow( source_window ); // 创建一个窗口
    36. createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo ); // 创建一个滑动条
    37. imshow( source_window, src ); // 在窗口中显示原图像
    38. cornerHarris_demo( 0, 0 ); // 调用cornerHarris_demo函数,执行角点检测
    39. waitKey(); // 等待按键事件
    40. return 0; // 正常结束程序
    41. }
    42. /**
    43. * @function cornerHarris_demo
    44. * @brief Executes the corner detection and draw a circle around the possible corners
    45. */
    46. void cornerHarris_demo( int, void* )
    47. {
    48. /// Detector parameters
    49. int blockSize = 2; // 角点检测中块的大小
    50. int apertureSize = 3; // Sobel算子的孔径大小
    51. double k = 0.04; // Harris角点检测方程中的自由参数
    52. /// Detecting corners
    53. Mat dst = Mat::zeros( src.size(), CV_32FC1 ); // 创建一个和原图像同样大小的矩阵,初始值为0
    54. cornerHarris( src_gray, dst, blockSize, apertureSize, k ); // 执行Harris角点检测
    55. /// Normalizing
    56. Mat dst_norm, dst_norm_scaled; // 声明两个Mat类型变量,存储正规化后的图像和转换为8位的图像
    57. normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() ); // 正规化处理
    58. convertScaleAbs( dst_norm, dst_norm_scaled ); // 将正规化后的图像转换为8位
    59. /// Drawing a circle around corners
    60. for( int i = 0; i < dst_norm.rows ; i++ )
    61. {
    62. for( int j = 0; j < dst_norm.cols; j++ )
    63. {
    64. if( (int) dst_norm.at<float>(i,j) > thresh ) // 判断是否为角点
    65. {
    66. circle( dst_norm_scaled, Point(j,i), 5, Scalar(0), 2, 8, 0 ); // 在检测到的角点位置绘制圆圈
    67. }
    68. }
    69. }
    70. /// Showing the result
    71. namedWindow( corners_window ); // 创建一个新窗口以显示结果
    72. imshow( corners_window, dst_norm_scaled ); // 显示结果图像
    73. }

    5eb01b28c31135c108e0bf98cb918c6b.png

    ac63835a084ac081fff4fe8d62f9965b.png

    convertScaleAbs( dst_norm, dst_norm_scaled );

    acdcb8b6905c98eafd45348830f6f7ff.png

    3. cornerSubPix_Demo.cpp对图像中的角点位置进行检测和细化

    81f4d47674946eccf4f50d570cb850f5.jpeg

    91b94cc6c8734096ebb31a1b44769e6f.png

    98cdf91da0a73285c5b19203982a4c8d.png

    1. /**
    2. * @function cornerSubPix_Demo.cpp
    3. * @brief Demo code for refining corner locations
    4. * @author OpenCV team
    5. */
    6. #include "opencv2/highgui.hpp" // 包含OpenCV图形界面高级操作头文件
    7. #include "opencv2/imgproc.hpp" // 包含OpenCV图像处理头文件
    8. #include // 包含标准输入输出流头文件
    9. using namespace cv; // 使用命名空间cv,避免每次调用OpenCV函数时都要加cv::前缀
    10. using namespace std; // 使用命名空间std,避免每次调用标准库函数时都要加std::前缀
    11. /// 全局变量定义区域
    12. Mat src, src_gray; // 定义源图像和灰度图像
    13. int maxCorners = 10; // 最大角点数量初始化为10
    14. int maxTrackbar = 25; // 轨迹条的最大值为25
    15. RNG rng(12345); // 随机数生成器,种子为12345
    16. const char* source_window = "Image"; // 显示窗口的名称
    17. /// 函数头声明
    18. void goodFeaturesToTrack_Demo( int, void* );
    19. /**
    20. * @function main
    21. */
    22. int main( int argc, char** argv )
    23. {
    24. /// 读取源图像并转换成灰度图像
    25. CommandLineParser parser( argc, argv, "{@input | pic3.png | input image}" ); // 解析命令行参数
    26. src = imread( samples::findFile( parser.get( "@input" ) ) ); // 读取图片文件
    27. if( src.empty() ) // 如果读取失败,则输出错误信息并返回-1
    28. {
    29. cout << "Could not open or find the image!\n" << endl;
    30. cout << "Usage: " << argv[0] << " " << endl;
    31. return -1;
    32. }
    33. cvtColor( src, src_gray, COLOR_BGR2GRAY ); // 把源图像转换为灰度图像
    34. /// 创建窗口
    35. namedWindow( source_window );
    36. /// 创建轨迹条以设置角点数量
    37. createTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo );
    38. imshow( source_window, src ); // 显示源图像
    39. goodFeaturesToTrack_Demo( 0, 0 ); // 调用角点检测函数
    40. waitKey(); // 等待键盘事件
    41. return 0;
    42. }
    43. /**
    44. * @function goodFeaturesToTrack_Demo.cpp
    45. * @brief Apply Shi-Tomasi corner detector
    46. */
    47. void goodFeaturesToTrack_Demo( int, void* )
    48. {
    49. /// Shi-Tomasi算法的参数设定
    50. maxCorners = MAX(maxCorners, 1); // 确保角点的数量至少为1
    51. vector corners; // 角点集合
    52. double qualityLevel = 0.01; // 角点检测可接受的最小特征值
    53. double minDistance = 10; // 角点之间的最小距离
    54. int blockSize = 3, gradientSize = 3; // 块大小和梯度大小
    55. bool useHarrisDetector = false; // 是否使用哈里斯角点检测器
    56. double k = 0.04; // 哈里斯角点检测器的自由参数
    57. /// 复制源图像
    58. Mat copy = src.clone();
    59. /// 应用角点检测
    60. goodFeaturesToTrack( src_gray,
    61. corners,
    62. maxCorners,
    63. qualityLevel,
    64. minDistance,
    65. Mat(),
    66. blockSize,
    67. gradientSize,
    68. useHarrisDetector,
    69. k );
    70. /// 绘制检测到的角点
    71. cout << "** Number of corners detected: " << corners.size() << endl;
    72. int radius = 4; // 绘制的圆形角点的半径
    73. for( size_t i = 0; i < corners.size(); i++ ) // 遍历所有检测到的角点
    74. {
    75. // 绘制圆形角点,颜色随机
    76. circle( copy, corners[i], radius, Scalar(rng.uniform(0,255), rng.uniform(0, 256), rng.uniform(0, 256)), FILLED );
    77. }
    78. /// 显示结果
    79. namedWindow( source_window );
    80. imshow( source_window, copy ); // 显示含有角点的图像
    81. /// 设置细化角点所需的参数
    82. Size winSize = Size( 5, 5 ); // 搜索窗口的大小
    83. Size zeroZone = Size( -1, -1 ); // 死区的大小
    84. TermCriteria criteria = TermCriteria( TermCriteria::EPS + TermCriteria::COUNT, 40, 0.001 ); // 终止迭代的条件
    85. /// 计算细化后的角点位置
    86. cornerSubPix( src_gray, corners, winSize, zeroZone, criteria );
    87. /// 输出细化后的角点位置
    88. for( size_t i = 0; i < corners.size(); i++ ) // 遍历细化后的角点集
    89. {
    90. // 打印每个细化后的角点坐标
    91. cout << " -- Refined Corner [" << i << "] (" << corners[i].x << "," << corners[i].y << ")" << endl;
    92. }
    93. }

    该代码是OpenCV的一个演示程序,用于展示如何对图像中的角点位置进行检测和细化。代码首先读取图像并转换成灰度图像,然后创建一个窗口并添加一个轨迹条来设置角点的最大数量。通过Shi-Tomasi角点检测函数goodFeaturesToTrack来检测图像中的角点。之后,利用cornerSubPix函数对已检测到的角点进行位置细化。结果显示了检测到的角点的数量以及细化后的角点的位置。

    95834af35e3a14176eb7919ea7f6136d.png

    cornerSubPix( src_gray, corners, winSize, zeroZone, criteria );

    a97f15a67313e724e5cbb54af7c96398.png

    4. goodFeaturesToTrack_Demo.cpp  Shi-Tomasi方法检测图像角点

    7e6e676f15d44777f8246a85554c5968.png

    971dd842dc56c3c5e0a664cd5940673f.png

    1. /**
    2. * @function goodFeaturesToTrack_Demo.cpp
    3. * @brief Demo code for detecting corners using Shi-Tomasi method
    4. * @author OpenCV team
    5. */
    6. #include "opencv2/imgcodecs.hpp" // 引入OpenCV图像编解码功能库
    7. #include "opencv2/highgui.hpp" // 引入OpenCV的高级GUI功能库
    8. #include "opencv2/imgproc.hpp" // 引入OpenCV图像处理功能库
    9. #include // 引入输入输出流库
    10. using namespace cv; // 使用OpenCV命名空间
    11. using namespace std; // 使用标准命名空间
    12. /// Global variables
    13. Mat src, src_gray; // 定义原图像及其灰度图像的全局变量
    14. int maxCorners = 23; // 定义检测到的最大角点数量
    15. int maxTrackbar = 100; // 跟踪条的最大值
    16. RNG rng(12345); // 定义随机数生成器,用于画图时颜色的随机
    17. const char* source_window = "Image"; // 定义用于显示图像的窗口名
    18. /// Function header
    19. void goodFeaturesToTrack_Demo( int, void* ); // 声明检测角点的函数原型
    20. /**
    21. * @function main
    22. */
    23. int main( int argc, char** argv )
    24. {
    25. /// Load source image and convert it to gray
    26. CommandLineParser parser( argc, argv, "{@input | pic3.png | input image}" ); // 解析命令行参数
    27. src = imread( samples::findFile( parser.get( "@input" ) ) ); // 读取图片文件
    28. if( src.empty() )
    29. {
    30. cout << "Could not open or find the image!\n" << endl; // 如果图片为空,打印错误信息
    31. cout << "Usage: " << argv[0] << " " << endl;
    32. return -1;
    33. }
    34. cvtColor( src, src_gray, COLOR_BGR2GRAY ); // 将原图像转换为灰度图像
    35. /// Create Window
    36. namedWindow( source_window ); // 创建一个窗口
    37. /// Create Trackbar to set the number of corners
    38. createTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo ); // 创建一个跟踪条以调整角点的最大数量
    39. imshow( source_window, src ); // 显示源图像
    40. goodFeaturesToTrack_Demo( 0, 0 ); // 调用goodFeaturesToTrack_Demo函数
    41. waitKey(); // 等待按键事件
    42. return 0;
    43. }
    44. /**
    45. * @function goodFeaturesToTrack_Demo.cpp
    46. * @brief Apply Shi-Tomasi corner detector
    47. */
    48. void goodFeaturesToTrack_Demo( int, void* )
    49. {
    50. /// Parameters for Shi-Tomasi algorithm
    51. maxCorners = MAX(maxCorners, 1); // 确保角点数至少为1
    52. vector corners; // 定义角点集合
    53. double qualityLevel = 0.01; // 定义角点检测的质量水平
    54. double minDistance = 10; // 角点之间的最小距离
    55. int blockSize = 3, gradientSize = 3; // 定义块大小和梯度大小
    56. bool useHarrisDetector = false; // 是否使用Harris角点检测器
    57. double k = 0.04; // Harris检测器的自由参数
    58. /// Copy the source image
    59. Mat copy = src.clone(); // 复制源图像
    60. /// Apply corner detection
    61. goodFeaturesToTrack( src_gray, // 输入图像
    62. corners, // 输出角点集合
    63. maxCorners, // 角点的最大数量
    64. qualityLevel, // 角点检测的质量水平
    65. minDistance, // 角点之间的最小距离
    66. Mat(), // 蒙版,为空代表不使用
    67. blockSize, // 块大小
    68. gradientSize, // 梯度大小
    69. useHarrisDetector, // 是否使用Harris检测器
    70. k ); // Harris检测器的参数
    71. /// Draw corners detected
    72. cout << "** Number of corners detected: " << corners.size() << endl; // 打印检测到的角点数量
    73. int radius = 4; // 角点绘制的圆半径
    74. for( size_t i = 0; i < corners.size(); i++ )
    75. {
    76. circle( copy, corners[i], radius, Scalar(rng.uniform(0,255), rng.uniform(0, 256), rng.uniform(0, 256)), FILLED ); // 在图像上绘制检测到的角点
    77. }
    78. /// Show what you got
    79. namedWindow( source_window ); // 创建窗口
    80. imshow( source_window, copy ); // 显示含有角点的图像
    81. }

    此代码是使用C++语言和OpenCV库编写的角点检测示例程序。它可以加载一个图像文件,将其转换为灰度图,然后使用Shi-Tomasi角点检测方法检测图像中的角点。程序通过一个可调的跟踪条允许用户设置最大角点数,并在图像中显示检测到的角点数量。检测到的角点会以彩色圆圈标出并展示在一个新窗口中。这个示例程序适用于那些想要学习如何使用OpenCV进行基本角点检测的开发者。

  • 相关阅读:
    Redis数据结构详解
    PyCharm配置Jupyter
    北京ib国际学校大盘点
    【Mybatis源码】XPathParser解析器
    Spring Security 如何实现身份认证和授权?
    文心一言 VS 讯飞星火 VS chatgpt (245)-- 算法导论18.1 3题
    pytest学习和使用7-fixture参数scope作用域(范围)执行顺序
    Sealos 是企业节省成本的终极武器
    Python文件操作(04):常见功能
    6.wifi开发【智能家居:下】,正式开发:智能开关灯,智能采集温湿度,智能调彩灯
  • 原文地址:https://blog.csdn.net/cxyhjl/article/details/137364050