解决:如何在opencv中得到与matlab立体标定一样的矫正图?(python版opencv)
目的:采用一样的标定参数,matlab中和opencv中的立体矫正图像是一样的吗?不一样的话怎么让它们一样?
结论:不一样。后文为解决方案。
原因:注意matlab的标定结果在matlab中的用法和在opencv中的用法不一样,主要原因是matlab的rectifyStereoImages函数和opencv的cv2.stereoRectify函数的计算结果不一样导致的。照这个思路,把matlab的rectifyStereoImages的结果导入opencv、而不用opencv的cv2.stereoRectify就可以了。
不想看对比细节可直接看3. 好像发现了一些线索
软件版本:Matlab2024a + OpenCV4.9.0
问题的提出
在matlab的stereo camera calibrator中对棋盘格标定后,可以点击“Show Rectified”一键得到矫正图
但是把matlab的参数导入到opencv中后,怎么得到和matlab一样的结果呢?
1. 用标定后的参数在matlab中直接显示立体矫正后的左右目图像
在matlab的stereo camera calibrator中对棋盘格标定后,有两种结果,一种直接在stereoParams中查看,另一种用函数转换成opencv的格式,这里两种都展示:
1.1 在stereoParams中直接查看
% stereoParams.CameraParameters1.intrinsics中查看左相机
K =[5701.4907,0,1387.8609;0,5705.7330,1050.1707;0,0,1]
RadialDistortion = [-0.0621,0.2954,2.6695]
TangentialDistortion =[0.0010,-0.0004]
%写成[k1, k2, p1, p2, k3]格式
distCoeffs = [-0.0621,0.2954,0.0010,-0.0004,2.6695]
% stereoParams.CameraParameters2.intrinsics中查看右相机
K =[5596.4954,0,1062.2055;0,5620.0099,1016.7026;0,0,1]
RadialDistortion = [-0.0358,-0.0958,9.2830]
TangentialDistortion =[0.0001,0.0034]
%写成[k1, k2, p1, p2, k3]格式
distCoeffs = [-0.0358,-0.0958,0.0001,0.0034,9.2830]
% 以及旋转矩阵、平移矩阵(这两个是完全一样的)
stereoParams.PoseCamera2.R =[0.9500,-0.0045,0.3121;0.0035,1.0000,0.0038;-0.3121,-0.0025,0.9500]
stereoParams.PoseCamera2.Translation =[ -35.0696 -0.0101 5.1674]
1.2 在matlab中转换成opencv格式
函数:stereoParametersToOpenCV
[intrinsicMatrix1,distortionCoefficients1,...intrinsicMatrix2,distortionCoefficients2,...rotationOfCamera2,translationOfCamera2] ...= stereoParametersToOpenCV(stereoParams)
% 输出
intrinsicMatrix1 =[5701.4907,0,1386.8609;0,5705.7330,1049.1707;0,0,1]
distortionCoefficients1 = [-0.0621 0.2954 0.0010 -0.0004 2.6695]
intrinsicMatrix2 =[5596.4954,0,1061.2055;0,5620.0099,1015.7026;0,0,1]
distortionCoefficients2 =[-0.0358 -0.0958 0.0001 0.0034 9.2830]
rotationOfCamera2 =[0.9500 -0.0045 0.31210.0035 1.0000 0.0038-0.3121 -0.0025 0.9500]
translationOfCamera2 =[ -35.0696 -0.0101 5.1674]
1.3 两种方法的差异
只有内参矩阵的主点坐标不一样,畸变参数、旋转矩阵、平移向量都是一样的~
差值为1,原因是主点-1了,如下:cx = intrinsics.PrincipalPoint(1) - 1;
%在函数function [intrinsicMatrix, distortionCoefficients] = cameraIntrinsicsToOpenCV(intrinsics)中
function distortionCoefficients = getOCVDistortionCoefficients(intrinsics) % Distortion Coefficients in OpenCV [k1 k2 p1 p2 k3]distortionCoefficients = zeros(1,5);if length(intrinsics.RadialDistortion) == 3distortionCoefficients([1,2,5]) = intrinsics.RadialDistortion;elsedistortionCoefficients([1,2]) = intrinsics.RadialDistortion;enddistortionCoefficients([3,4]) = intrinsics.TangentialDistortion;
endfunction intrinsicMatrix = getOCVIntrinsicMatrix(intrinsics)% Focal length.fx = intrinsics.FocalLength(1);fy = intrinsics.FocalLength(2);% Principal point.cx = intrinsics.PrincipalPoint(1) - 1;cy = intrinsics.PrincipalPoint(2) - 1; % Construct OpenCV's intrinsic matrix.intrinsicMatrix = [fx 0 cx;0 fy cy;0 0 1];
end
1.4 在matlab中用stereoParams映射矫正后的图像
close all; clc;I1 = imread('D:\StereoRectify\Calibration\left\0001.jpg');%读取左右图片
I2 = imread('D:\StereoRectify\Calibration\right\0001.jpg');[J1, J2] = rectifyStereoImages(I1, I2, stereoParams);figure; subplot(2,1,1); imshow(J1);
subplot(2,1,2); imshow(J2);
这里J1,J2的图像尺寸都是4026×2128。
如果在opencv里面矫正后的图像尺寸也是这个值,说明两个方法取得一样的效果;反之,就有问题!
当然,这个验证方法过于简单粗暴,实际上把两种方法的图像做减法也能对比的~~
但是把matlab的参数导入到opencv中后,怎么得到和matlab一样的结果呢?
2. 把matlab标定的参数导入python的opencv,然后计算立体矫正后的左右目图像
这段可以不看~~怎么解释validPixROI
这个参数呢?
网上有这么说的:
validPixROI1:一个最多地包含有效像素的长方形。(左目图像)
validPixROI2:一个最多地包含有效像素的长方形。(右目图像)
这个参数的第一个值是有效图像最左侧非零点的横坐标;
后面三个参数我无法解释,对着图像来看上/下/左/右/横/纵坐标都不是-_-|||。
opencv官方文档也没写,我自己写一个计算图像的非零区域的代码吧!
跳到这里:这里是正文~~
2.1 代码:
import camera_config
import cv2
import matplotlib.pyplot as plt
from PIL import Image
import numpy as npsize = camera_config.size # (8000, 3000) # 图像尺寸
left_camera_matrix = camera_config.left_camera_matrix
left_distortion = camera_config.left_distortion
right_camera_matrix = camera_config.right_camera_matrix
right_distortion = camera_config.right_distortion
R = camera_config.R
T = camera_config.T# 进行立体更正
R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(left_camera_matrix, left_distortion, right_camera_matrix, right_distortion, size, R, T)
# 输出参数:
print('***** R1 *****\n',R1) # R1:矫正旋转矩阵。将第一个相机坐标系下未矫正的点变换到第一个相机矫正坐标系下,即 R_{左矫正坐标系}{左未矫正坐标系}
print('***** P1 *****\n',P1) # P1:3x4左相机投影矩阵。将左矫正坐标系下的点投影到左矫正坐标系图像平面坐标系。
print('***** R2 *****\n',R2) # R2:矫正旋转矩阵。将第二个相机坐标系下未矫正的点变换到第二个相机矫正坐标系下,即 R_{右矫正坐标系}{右未矫正坐标系}
print('***** P2 *****\n',P2) # P2:3x4右相机投影矩阵。将左矫正坐标系下的点投影到右矫正坐标系图像平面坐标系。
print('***** Q *****\n',Q) # Q:4x4的视差深度映射矩阵。
# 计算更正map
left_map1, left_map2 = cv2.initUndistortRectifyMap(left_camera_matrix, left_distortion, R1, P1, size, cv2.CV_16SC2)
right_map1, right_map2 = cv2.initUndistortRectifyMap(right_camera_matrix, right_distortion, R2, P2, size, cv2.CV_16SC2)
img_l = np.array(Image.open(r'Calibration/left/0001.jpg'))
img_r = np.array(Image.open(r'Calibration/right/0001.jpg'))
# 根据更正map对图片进行重构
img1_rectified = cv2.remap(img_l, left_map1, left_map2, cv2.INTER_LINEAR)
img2_rectified = cv2.remap(img_r, right_map1, right_map2, cv2.INTER_LINEAR)
# 转成灰度图,求非零图像区域,然后求图像区域的上/下/左/右/横/纵坐标
img1_rectified_gray = cv2.cvtColor(img1_rectified, cv2.COLOR_RGB2GRAY)
img2_rectified_gray = cv2.cvtColor(img2_rectified, cv2.COLOR_RGB2GRAY)
idxNonZero=cv2.findNonZero(img1_rectified_gray).squeeze(1)
l1, r1, t1, b1 = np.min(idxNonZero[:,0]), np.max(idxNonZero[:,0]), np.min(idxNonZero[:,1]), np.max(idxNonZero[:,1])
idxNonZero=cv2.findNonZero(img2_rectified_gray).squeeze(1)
l2, r2, t2, b2 = np.min(idxNonZero[:,0]), np.max(idxNonZero[:,0]), np.min(idxNonZero[:,1]), np.max(idxNonZero[:,1])
plt.figure(1)
plt.subplot(211)
plt.imshow(img1_rectified)
plt.subplot(212)
plt.imshow(img2_rectified)
plt.figure(2)
plt.subplot(211)
plt.imshow(img1_rectified[min(t1,t2):max(b1,b2), l2:r1])
plt.subplot(212)
plt.imshow(img2_rectified[min(t1,t2):max(b1,b2), l2:r1])
# 裁剪后的图像尺寸
print(f'image size: {r1-l2}x{max(b1,b2)-min(t1,t2)}')plt.show()
结果:
***** R1 *****[[ 0.9853897 -0.00381456 0.1702721 ][ 0.00352377 0.99999177 0.00200993][-0.17027837 -0.00138056 0.98539503]]
***** P1 *****[[5662.8715 0. 4312.4698143 0. ][ 0. 5662.8715 1261.70807171 0. ][ 0. 0. 1. 0. ]]
***** R2 *****[[ 0.98931806 0.00028444 -0.14577278][-0.00053314 0.99999847 -0.00166697][ 0.14577209 0.00172688 0.98931669]]
***** P2 *****[[ 5662.8715 0. 4312.4698143 -200738.92039502][ 0. 5662.8715 1261.70807171 0. ][ 0. 0. 1. 0. ]]
***** Q *****[[ 1. 0. 0. -4312.4698143 ][ 0. 1. 0. -1261.70807171][ 0. 0. 0. 5662.8715 ][ 0. 0. 0.02821013 -0. ]]
image size: 4074x2152
2.2 参数解释
参见opencv官方文档中函数stereoRectify()的解释
P1, P2的含义及其用法
P1:3x4左相机投影矩阵。将左矫正坐标系下的三维点投影到左矫正坐标系图像平面坐标系的像素点
P 1 = [ f 0 c x 1 0 0 f c y 0 0 0 1 0 ] {P1 = }\left[ {\begin{array}{cc} f&0&{{c_{x1}}}&0\\ 0&f&{{c_y}}&0\\ 0&0&1&0 \end{array}} \right] P1= f000f0cx1cy1000
P2:3x4右相机投影矩阵。将左矫正坐标系下的三维点投影到右矫正坐标系图像平面坐标系的像素点。 T x T_x Tx是两个相机之间的水平偏移值。我这里算了一下,实际上就是matlab标定的平移向量[ -35.0696 -0.0101 5.1674] 的长度=35.4483的负数,用P2的两个参数 T x ⋅ f {T_x} \cdot f Tx⋅f=-200738.92039502; f f f=5662.8715; -200738.92039502/5662.8715 = -35.4483 可以验证。
P 2 = [ f 0 c x 2 T x ⋅ f 0 f c y 0 0 0 1 0 ] {P2 = }\left[ {\begin{array}{cc} f&0&{{c_{x2}}}&{{T_x} \cdot f}\\ 0&f&{{c_y}}&0\\ 0&0&1&0 \end{array}} \right] P2= f000f0cx2cy1Tx⋅f00
对于三维物理空间点 ( X , Y , Z ) (X, Y, Z) (X,Y,Z),都可用P1和P2,计算该点对应的图像像素坐标 ( x , y ) (x, y) (x,y),( w w w是尺度因子)
w [ x y 1 ] = P [ X Y Z 1 ] w\left[ {\begin{array}{cc} x\\ y\\ 1 \end{array}} \right] = P\left[ {\begin{array}{cc} X\\ Y\\ Z\\ 1 \end{array}} \right] w xy1 =P XYZ1
Q的含义及其用法
Q:4x4的视差深度映射矩阵。
Q = [ 1 0 0 − c x 1 0 1 0 − c y 0 0 0 f 0 0 − 1 T x c x 1 − c x 2 T x ] {Q = }\left[ {\begin{array}{cc} 1&0&0&{ - {c_{x1}}}\\ 0&1&0&{ - c{}_y}\\ 0&0&0&f\\ 0&0&{ - \frac{1}{{{T_x}}}}&{\frac{{{c_{x1}} - {c_{x2}}}}{{{T_x}}}} \end{array}} \right] Q= 10000100000−Tx1−cx1−cyfTxcx1−cx2
为什么把Q叫视差深度映射矩阵呢?因为采用下式,Q能够将单通道视差图转换为表示 3D 表面的 3 通道图(就是x,y,z坐标值)。对于每个像素坐标 ( x , y ) (x, y) (x,y)及其视差 d = d i s p a r i t y ( x , y ) d=disparity(x,y) d=disparity(x,y) ,都能计算三维物理空间中的一个点 ( X , Y , Z ) (X, Y, Z) (X,Y,Z):
[ X Y Z W ] = Q [ x y d i s p a r i t y ( x , y ) 1 ] \left[ {\begin{array}{c} X\\ Y\\ Z\\ W \end{array}} \right] = Q\left[ {\begin{array}{c} x\\ y\\ disparity(x,y)\\ 1 \end{array}} \right] XYZW =Q xydisparity(x,y)1
上式中的W好像没有什么实际意义。。。
2.3 图像结果
Figure1是8000×3000尺寸的图像
Figure2是裁掉周围黑框的图像
- opencv的image size: 4074x2152为什么和matlab的图像尺寸4026×2128不一样啊?!
我裂开!!!
哪位小伙伴知道为什么?欢迎讨论!!!
直观的对比opencv和matlab的结果
3. 好像发现了一些线索 ~_~
matlab自带的rectifyStereoImages(I1, I2, stereoParams)
的可选输出重投影矩阵reprojectionMatrix
,和opencv的Q矩阵是同样的含义,但是,结果却不一样!!!
[J1, J2, reprojectionMatrix, camMatrix1, camMatrix2, R1, R2] = rectifyStereoImages(I1, I2, stereoParams);
reprojectionMatrix = [1 0 0 -1943.86090 1 0 -1066.43670 0 0 5596.49540 0 0.0282 0]
% Notes
% -----
% - reprojectionMatrix is represented as a 4-by-4 matrix:
% [1 0 0 -cx
% 0 1 0 -cy
% 0 0 0 f
% 0 0 1/b 0],
% where f and [cx, cy] are the focal length and principal point of
% rectified camera 1, respectively. b is the baseline of the virtual
% rectified stereo camera.
camMatrix1 =[5596.4954 0 1943.8609 -198385.9933;0 5596.4954 1066.4367 0;0 0 1 0]
camMatrix2 =[1 0 0 0;0 1 0 0;0 0 1 0]
% R1、R2和前面的一样
R1 =[0.9854 -0.0038 0.17030.0035 1.0000 0.0020-0.1703 -0.0014 0.9854]
R2 =[0.9893 0.0003 -0.1458-0.0005 1.0000 -0.00170.1458 0.0017 0.9893]
% - Use camMatrix1 and camMatrix2 to project 3-D world points in the
% rectified camera 1's coordinate system into the image plane of J1 and
% J2, respectively. R1 and R2 bring 3-D points in the unrectified camera's
% coordinate system to points in the rectified camera's coordinate system
% for camera 1 and camera 2, respectively.
在python中对前面的2.1 代码作出如下修改就可以了:
# 原来的
# 进行立体更正
R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(left_camera_matrix, left_distortion, right_camera_matrix, right_distortion,size, R, T)# 把上面这句删除,改成matlab的rectifyStereoImages输出值
Q = reprojectionMatrix
P1 = camMatrix1
P2 = camMatrix2
R1 = R1
R2 = R2
这样opencv输出的image size: 4025x2111,和matlab的图像尺寸4026×2128相当接近了!!!直观对比如下 ↓↓
但是,左图是可以的,右图是黑色的,怎么办啊??!!
尝试:按照前面P2的定义,对P2重新赋值
P2 = P1
P2[0,3] = np.linalg.norm(T)*P1[0,0]
# 输出P2
***** P2 *****[[ 5596.495 0. 1943.861 198385.9892][ 0. 5596.495 1066.437 0. ][ 0. 0. 1. 0. ]]image size: 4025x2127
OK啦!!!opencv输出的image size: 4025x2127和matlab的图像尺寸4026×2128横纵坐标都差个1,让我看看应该把1加在哪!
直观对比如下 ↓↓
两张图像做减法,不太行,可能是插值方法不一样?还是坐标错了?
还是提取棋盘格角点坐标对比吧!
相关文章:

解决:如何在opencv中得到与matlab立体标定一样的矫正图?(python版opencv)
目的:采用一样的标定参数,matlab中和opencv中的立体矫正图像是一样的吗?不一样的话怎么让它们一样? 结论:不一样。后文为解决方案。 原因:注意matlab的标定结果在matlab中的用法和在opencv中的用法不一样&a…...
gin入门教程(4):路由与处理器
路由与处理器 在 Gin 框架中,路由和处理器是核心组成部分,负责将 HTTP 请求映射到相应的处理逻辑。 1. 定义路由 在 cmd/main.go 中,您可以定义不同的路由,例如: r.GET("/ping", func(c *gin.Context) {…...
【python+Redis】hash修改
文章目录 前请详解一、关于Update1. 语法2. 代码示例 二、完整代码 前请详解 Redis库数据 keyvalue1{“id”: 1, “name”: “xxx”, “age”: “18”, “sex”: “\u7537”}2{“id”: 2, “name”: “xxx”, “age”: “18”, “sex”: “\u5973”}3{“id”: 3, “name”: “…...

MAVlink协议 部分通用消息集解析
文章目录 MAVLink是一种非常轻量级的消息传输协议, 用于地面控制终端(地面站)与无人机之间 (以及机载无人机组件之间) 进行通信, 为一种设计用于资源受限系统及带宽受限链路的二进制遥测协议。 HEARTBEAT 检测信号消息显示系统或组件存在并正…...
c++实现跳表
原理 跳表(Skip List) 是一种随机化数据结构,用于高效查找、插入和删除,尤其适用于有序数据集合。相比链表,跳表通过多层索引结构加速查找,期望时间复杂度接近 O(logn)。跳表的主要思想是: …...

新探索研究生英语读写教程pdf答案(基础级)
《新探索研究生英语读写教程》的设计和编写充分考虑国内研究生人才培养目标和研究生公共英语的教学需求, 教学内容符合研究生认知水平, 学术特征突出;教学设计紧密围绕学术阅读、学术写作和学术研究能力培养;教学资源立体多元&…...

管道与共享内存
一,命名管道 管道的限制就是他只能在有血缘关系(父子进程)的进程中,允许互相访问,这是有局限性的,所以我们想在毫无关系的进程中允许他们相互访问,这就是命名管道的定义。 总结:命名…...
ES 自定义排序方式
es默认score是根据query的相关度进行打分的,具体打分机制可以参见:官方文档。如果召回时既希望有相关性又能根据其他信息进行排序。 例如小红书搜索的时候,可能既希望有召回相关度又能根据热度信息(如果喜欢、收藏等等参数去进行召…...
在vue中,编写一个li标签同时使用v-for和v-if,谁的优先级更高
在 Vue 中,v-if 和 v-for 是两个常用的指令,但它们的优先级不同。当二者一起使用时,v-for 的优先级高于 v-if。这意味着,v-for 会先执行,即使列表中的某些元素不满足 v-if 条件,它们仍会被遍历和渲染。 由…...
Java 后端开发面试题及其答案
以下是一些常见的 Java 后端开发面试题及其答案,涵盖了 Java 基础、面向对象、并发、多线程、框架等多个方面: 1. Java 中的基本数据类型有哪些? 答案: Java 中的基本数据类型有 8 种: int:32 位整数lon…...

C++,STL 045(24.10.24)
内容 1.对set容器的大小进行操作。 2.set容器的交换操作。 运行代码 #include <iostream> #include <set>using namespace std;void printSet(set<int> &s) {for (set<int>::iterator it s.begin(); it ! s.end(); it){cout << *it <…...

二叉树习题其五【力扣】【算法学习day.12】
前言 书接上篇文章二叉树习题其四,这篇文章我们将基础拓展 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一…...

【数据库】Mysql的锁类型
Mysql中的锁机制主要是为了保证数据的一致性和完整性,在并发的情况下起着至关重要的作用。其中锁的类型主要是分为以下几种: 按照粒度分类 全局锁:对于整个数据库实例进行枷锁,加锁后整个实例就处于只读的状态。局锁通常用于需要…...

自媒体短视频制作素材下载网站推荐,让创作更简单
随着自媒体行业的火爆,视频质量要求也越来越高。想要找到无版权的高清视频素材并不容易,但别担心!今天为大家整理了5个国内外高质量的素材网站,让你轻松获取自媒体短视频素材,快收藏起来吧! 蛙学网 蛙学网是…...

Altium Designer 入门基础教程(五)
本文章继续接着《Altium Designer 入门基础教程(四)》的内容往下介绍: 七、AD画板的整个流程步骤 I.集成库的制作 AD元件库有2种:1、原理图元件库SCH.LIB 2、印刷电路板(PCB)元件库 PCB.LIB 印刷电路…...
Java题集练习3
Java题集练习3 1 什么时候用instanceof instanceOf关键字主要用于判断一个对象是否为某个类的子类或是接口的实例,通常用于类型转换和运行时类型判断的场景,比如继承和多态中。比如,创建一个Animal类及其子类Cat和Cat子类Hat,可…...

【部署篇】Haproxy-01安装部署(源码方式安装)
一、HAProxy概述 HAProxy是一款免费、快速且可靠的代理软件,提供高可用性、负载均衡,支持TCP和HTTP应用代理,HAProxy凭借其卓越的性能和灵活性,成为众多知名网站和系统的首选代理软件。 核心特点: 高性能…...

开拓鸿蒙测试新境界,龙测科技引领自动化测试未来
在当今科技舞台上,鸿蒙 OS 以非凡先进性强势登场,打破传统操作系统格局,为软件测试领域带来全新机遇与艰巨挑战。 一、鸿蒙 OS 的辉煌崛起 (一)壮丽发展历程与卓越市场地位 鸿蒙 OS 的发展如波澜壮阔的史诗。2023 年…...

Java项目-基于springboot框架的自习室预订系统项目实战(附源码+文档)
作者:计算机学长阿伟 开发技术:SpringBoot、SSM、Vue、MySQL、ElementUI等,“文末源码”。 开发运行环境 开发语言:Java数据库:MySQL技术:SpringBoot、Vue、Mybaits Plus、ELementUI工具:IDEA/…...

调整数组奇偶数顺序
今天给大家分享一道题目,要求我们输入一个数组,将全部奇数放在偶数前面(无需比较大小),下面是我写的代码 这个方法比使用三个数组进行数据传输要节省不少程序运行时间,缺点是使用了较多的while循环…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...