opencv各种滤波器的用法

本文通过使用Python的OpenCV库,展示了多种图像滤波技术,包括平均滤波、高斯滤波、中值滤波及双边滤波,并通过实例对比了不同滤波方法的效果。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('test2.jpg')
kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(img,-1,kernel)#

blur = cv2.GaussianBlur(img,(5,5),0)#

median = cv2.medianBlur(img,5)

#9 邻域直径,两个 75 分别是空间高斯函数标准差,灰度值相似性高斯函数标准差
bila = cv2.bilateralFilter(img,9,75,75)

plt.subplot(231),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(232),plt.imshow(dst),plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.subplot(233),plt.imshow(blur),plt.title('gauss')
plt.xticks([]), plt.yticks([])
plt.subplot(234),plt.imshow(median),plt.title('medium')
plt.xticks([]), plt.yticks([])
plt.subplot(235),plt.imshow(bila),plt.title('bila')
plt.xticks([]), plt.yticks([])

plt.show()
<think># 使用OpenCV卡尔曼滤波器和Madgwick算法融合的IMU姿态估计 本文将介绍如何将OpenCV的卡尔曼滤波器与Madgwick姿态估计算法融合,以提高IMU(惯性测量单元)的姿态估计精度。这种融合方法结合了卡尔曼滤波器的噪声抑制能力和Madgwick算法在姿态融合方面的优势。 ## 融合方案设计 1. **系统架构**: - Madgwick滤波器作为前置处理器,提供姿态四元数初始估计 - 卡尔曼滤波器用于进一步优化姿态估计并估计陀螺仪偏置 2. **数据流**: IMU数据 → Madgwick滤波器 → 四元数输出 → 卡尔曼滤波器观测值 → 卡尔曼滤波优化输出 ## 完整代码实现 ```cpp #include <opencv2/opencv.hpp> #include <cmath> #include <iostream> #include <chrono> // Madgwick滤波器实现 class MadgwickFilter { public: MadgwickFilter(float beta = 0.1f) : beta_(beta) { q_[0] = 1.0f; q_[1] = 0.0f; q_[2] = 0.0f; q_[3] = 0.0f; } void update(float gx, float gy, float gz, float ax, float ay, float az, float dt) { // 归一化加速度计数据 float norm = sqrt(ax*ax + ay*ay + az*az); if (norm > 0) { ax /= norm; ay /= norm; az /= norm; } // 计算预测重力方向 float vx = 2.0f*(q_[1]*q_[3] - q_[0]*q_[2]); float vy = 2.0f*(q_[0]*q_[1] + q_[2]*q_[3]); float vz = q_[0]*q_[0] - q_[1]*q_[1] - q_[2]*q_[2] + q_[3]*q_[3]; // 计算误差 float ex = (ay*vz - az*vy); float ey = (az*vx - ax*vz); float ez = (ax*vy - ay*vx); // 梯度下降修正 float qDot1 = 0.5f*(-q_[1]*gx - q_[2]*gy - q_[3]*gz) - beta_*ex; float qDot2 = 0.5f*(q_[0]*gx + q_[2]*gz - q_[3]*gy) - beta_*ey; float qDot3 = 0.5f*(q_[0]*gy - q_[1]*gz + q_[3]*gx) - beta_*ez; float qDot4 = 0.5f*(q_[0]*gz + q_[1]*gy - q_[2]*gx); // 积分 q_[0] += qDot1 * dt; q_[1] += qDot2 * dt; q_[2] += qDot3 * dt; q_[3] += qDot4 * dt; // 归一化四元数 norm = sqrt(q_[0]*q_[0] + q_[1]*q_[1] + q_[2]*q_[2] + q_[3]*q_[3]); if (norm > 0) { q_[0] /= norm; q_[1] /= norm; q_[2] /= norm; q_[3] /= norm; } } const float* quaternion() const { return q_; } private: float q_[4]; // [w, x, y, z] float beta_; // 滤波器增益 }; // 卡尔曼-马格维克融合滤波器 class KalmanMadgwickFusion { public: KalmanMadgwickFusion() { // 创建卡尔曼滤波器 // 状态: [qw, qx, qy, qz, bgx, bgy, bgz] (7维) // 测量: [qw, qx, qy, qz] (4维) kf_ = cv::KalmanFilter(7, 4, 0); // 状态转移矩阵 (A) kf_.transitionMatrix = (cv::Mat_<float>(7, 7) << 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); // 测量矩阵 (H) kf_.measurementMatrix = (cv::Mat_<float>(4, 7) << 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0); // 过程噪声协方差 (Q) cv::setIdentity(kf_.processNoiseCov, cv::Scalar::all(1e-4)); // 测量噪声协方差 (R) cv::setIdentity(kf_.measurementNoiseCov, cv::Scalar::all(1e-2)); // 初始状态协方差 (P) cv::setIdentity(kf_.errorCovPost, cv::Scalar::all(0.1)); // 初始状态 kf_.statePost = (cv::Mat_<float>(7, 1) << 1, 0, 0, 0, 0, 0, 0); // 初始化时间记录 last_time_ = std::chrono::steady_clock::now(); } // 更新滤波器 void update(float gx, float gy, float gz, float ax, float ay, float az) { // 计算时间差 auto now = std::chrono::steady_clock::now(); float dt = std::chrono::duration<float>(now - last_time_).count(); last_time_ = now; // 更新Madgwick滤波器 madgwick_.update(gx, gy, gz, ax, ay, az, dt); // 预测步骤 predict(dt); // 更新步骤 updateKalman(); } // 获取当前姿态(欧拉角) void getOrientation(float& roll, float& pitch, float& yaw) { // 获取卡尔曼滤波后的四元数 const float* q = kf_.statePost.ptr<float>(); // 转换为欧拉角 roll = atan2(2*(q[0]*q[1] + q[2]*q[3]), 1 - 2*(q[1]*q[1] + q[2]*q[2])); pitch = asin(2*(q[0]*q[2] - q[3]*q[1])); yaw = atan2(2*(q[0]*q[3] + q[1]*q[2]), 1 - 2*(q[2]*q[2] + q[3]*q[3])); // 弧度转角度 roll *= 57.2958f; pitch *= 57.2958f; yaw *= 57.2958f; } private: // 卡尔曼预测步骤 void predict(float dt) { // 更新状态转移矩阵中的时间相关部分 updateTransitionMatrix(dt); // 执行卡尔曼预测 kf_.predict(); } // 更新状态转移矩阵 void updateTransitionMatrix(float dt) { // 获取当前状态 float* state = kf_.statePost.ptr<float>(); float qw = state[0], qx = state[1], qy = state[2], qz = state[3]; float bgx = state[4], bgy = state[5], bgz = state[6]; // 计算角速度(补偿偏置) float wx = gx_ - bgx; float wy = gy_ - bgy; float wz = gz_ - bgz; // 更新状态转移矩阵 kf_.transitionMatrix = (cv::Mat_<float>(7, 7) << 1, -wx*dt/2, -wy*dt/2, -wz*dt/2, -qx*dt/2, -qy*dt/2, -qz*dt/2, wx*dt/2, 1, wz*dt/2, -wy*dt/2, qw*dt/2, -qz*dt/2, qy*dt/2, wy*dt/2, -wz*dt/2, 1, wx*dt/2, qz*dt/2, qw*dt/2, -qx*dt/2, wz*dt/2, wy*dt/2, -wx*dt/2, 1, -qy*dt/2, qx*dt/2, qw*dt/2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); } // 卡尔曼更新步骤 void updateKalman() { // 获取Madgwick滤波器的输出 const float* madgwick_q = madgwick_.quaternion(); // 创建测量向量 cv::Mat measurement(4, 1, CV_32F); measurement.at<float>(0) = madgwick_q[0]; measurement.at<float>(1) = madgwick_q[1]; measurement.at<float>(2) = madgwick_q[2]; measurement.at<float>(3) = madgwick_q[3]; // 执行卡尔曼更新 kf_.correct(measurement); } // 成员变量 cv::KalmanFilter kf_; // OpenCV卡尔曼滤波器 MadgwickFilter madgwick_; // Madgwick滤波器 std::chrono::steady_clock::time_point last_time_; float gx_, gy_, gz_; // 当前陀螺仪读数 }; // 示例主函数 int main() { // 创建融合滤波器 KalmanMadgwickFusion filter; // 模拟IMU数据流 for (int i = 0; i < 1000; ++i) { // 模拟陀螺仪数据(单位: rad/s) float gx = 0.1f * sin(i * 0.05f); float gy = 0.05f * cos(i * 0.03f); float gz = 0.02f * sin(i * 0.02f); // 模拟加速度计数据(单位: m/s²) float ax = 0.05f * ((rand() % 100) / 100.0f - 0.5f); float ay = 0.05f * ((rand() % 100) / 100.0f - 0.5f); float az = 9.8f + 0.05f * ((rand() % 100) / 100.0f - 0.5f); // 更新滤波器 filter.update(gx, gy, gz, ax, ay, az); // 获取姿态 float roll, pitch, yaw; filter.getOrientation(roll, pitch, yaw); // 输出姿态信息 if (i % 100 == 0) { std::cout << "Step " << i << ": Roll=" << roll << ", Pitch=" << pitch << ", Yaw=" << yaw << std::endl; } } return 0; } ``` ## 关键实现细节 ### 1. 状态转移矩阵设计 状态转移矩阵根据四元数微分方程设计: ``` dq/dt = 0.5 * ω * q ``` 其中ω是角速度四元数。在离散时间下,状态转移可表示为: ``` q_{k+1} = (I + 0.5 * Ω * Δt) * q_k ``` 这里Ω是角速度的斜对称矩阵。 ### 2. 偏置估计 卡尔曼滤波器状态中包含了陀螺仪偏置项(bgx, bgy, bgz),这些偏置项被建模为随机游走过程。 ### 3. 融合策略 - **Madgwick滤波器**:提供快速、稳定的姿态估计,作为卡尔曼滤波器的观测值 - **卡尔曼滤波器**:对姿态进行平滑处理并估计陀螺仪偏置 ### 4. 时间同步 使用`std::chrono`精确计算时间间隔,确保状态转移矩阵的准确性。 ## 性能优化技巧 1. **矩阵运算优化**:OpenCV的矩阵运算已经高度优化,应避免不必要的矩阵复制 2. **四元数归一化**:在卡尔曼滤波器更新后,应添加四元数归一化步骤 3. **噪声参数调整**:根据实际IMU噪声特性调整Q和R矩阵 4. **偏置初始化**:在静止状态下初始化陀螺仪偏置 §§相关问题§§: 1. 在卡尔曼滤波器中如何有效处理四元数的非线性和归一化约束? 2. Madgwick算法中的beta参数如何影响姿态估计的收敛速度和稳定性? 3. 为什么在IMU姿态估计中需要同时使用加速度计和陀螺仪数据? 4. 如何扩展卡尔曼滤波器以同时估计位置和姿态(如无人机导航)? </think> # 使用OpenCV卡尔曼滤波器与Madgwick融合的IMU姿态估计 我将设计一个完整的融合系统,结合OpenCV的卡尔曼滤波器和Madgwick算法,用于提高IMU姿态估计的精度和稳定性。 ## 完整实现方案 ```cpp #include <opencv2/opencv.hpp> #include <cmath> #include <iostream> #include <chrono> #include <random> // Madgwick滤波器实现 class MadgwickFilter { public: MadgwickFilter(float beta = 0.1f) : beta_(beta) { q_[0] = 1.0f; q_[1] = 0.0f; q_[2] = 0.0f; q_[3] = 0.0f; } void update(float gx, float gy, float gz, float ax, float ay, float az, float dt) { // 归一化加速度计数据 float norm = sqrt(ax*ax + ay*ay + az*az); if (norm > 0) { ax /= norm; ay /= norm; az /= norm; } // 计算预测重力方向 float vx = 2.0f*(q_[1]*q_[3] - q_[0]*q_[2]); float vy = 2.0f*(q_[0]*q_[1] + q_[2]*q_[3]); float vz = q_[0]*q_[0] - q_[1]*q_[1] - q_[2]*q_[2] + q_[3]*q_[3]; // 计算误差 float ex = (ay*vz - az*vy); float ey = (az*vx - ax*vz); float ez = (ax*vy - ay*vx); // 梯度下降修正 float qDot1 = 0.5f*(-q_[1]*gx - q_[2]*gy - q_[3]*gz) - beta_*ex; float qDot2 = 0.5f*(q_[0]*gx + q_[2]*gz - q_[3]*gy) - beta_*ey; float qDot3 = 0.5f*(q_[0]*gy - q_[1]*gz + q_[3]*gx) - beta_*ez; float qDot4 = 0.5f*(q_[0]*gz + q_[1]*gy - q_[2]*gx); // 积分 q_[0] += qDot1 * dt; q_[1] += qDot2 * dt; q_[2] += qDot3 * dt; q_[3] += qDot4 * dt; // 归一化四元数 norm = sqrt(q_[0]*q_[0] + q_[1]*q_[1] + q_[2]*q_[2] + q_[3]*q_[3]); if (norm > 0) { q_[0] /= norm; q_[1] /= norm; q_[2] /= norm; q_[3] /= norm; } } const float* quaternion() const { return q_; } void setQuaternion(const float q[4]) { for(int i=0; i<4; i++) q_[i] = q[i]; } private: float q_[4]; // [w, x, y, z] float beta_; // 滤波器增益 }; // 卡尔曼-马格维克融合滤波器 class KalmanMadgwickFusion { public: KalmanMadgwickFusion() { // 创建卡尔曼滤波器 // 状态: [qw, qx, qy, qz, bgx, bgy, bgz] (7维) kf_ = cv::KalmanFilter(7, 4, 0); // 初始化状态转移矩阵 (A) kf_.transitionMatrix = (cv::Mat_<float>(7, 7) << 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); // 初始化测量矩阵 (H) kf_.measurementMatrix = (cv::Mat_<float>(4, 7) << 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0); // 过程噪声协方差 (Q) setIdentity(kf_.processNoiseCov, cv::Scalar::all(1e-5)); // 测量噪声协方差 (R) setIdentity(kf_.measurementNoiseCov, cv::Scalar::all(1e-3)); // 初始状态协方差 (P) setIdentity(kf_.errorCovPost, cv::Scalar::all(0.1)); // 初始状态 kf_.statePost = (cv::Mat_<float>(7, 1) << 1, 0, 0, 0, 0, 0, 0); // 初始化时间记录 last_time_ = std::chrono::steady_clock::now(); } // 更新滤波器 void update(float gx, float gy, float gz, float ax, float ay, float az) { // 计算时间差 auto now = std::chrono::steady_clock::now(); float dt = std::chrono::duration<float>(now - last_time_).count(); last_time_ = now; // 保存当前陀螺仪读数(用于状态转移矩阵) gx_ = gx; gy_ = gy; gz_ = gz; // 更新Madgwick滤波器 madgwick_.update(gx, gy, gz, ax, ay, az, dt); // 预测步骤 predict(dt); // 更新步骤 updateKalman(); } // 获取当前姿态(欧拉角) void getOrientation(float& roll, float& pitch, float& yaw) { // 获取卡尔曼滤波后的四元数 const float* q = kf_.statePost.ptr<float>(); // 转换为欧拉角 roll = atan2(2*(q[0]*q[1] + q[2]*q[3]), 1 - 2*(q[1]*q[1] + q[2]*q[2])); pitch = asin(2*(q[0]*q[2] - q[3]*q[1])); yaw = atan2(2*(q[0]*q[3] + q[1]*q[2]), 1 - 2*(q[2]*q[2] + q[3]*q[3])); // 弧度转角度 roll *= 57.2958f; pitch *= 57.2958f; yaw *= 57.2958f; } // 获取当前四元数 const float* getQuaternion() const { return kf_.statePost.ptr<float>(); } // 获取估计的陀螺仪偏置 void getGyroBias(float& bx, float& by, float& bz) { const float* state = kf_.statePost.ptr<float>(); bx = state[4]; by = state[5]; bz = state[6]; } private: // 卡尔曼预测步骤 void predict(float dt) { // 更新状态转移矩阵 updateTransitionMatrix(dt); // 执行卡尔曼预测 kf_.predict(); // 确保四元数归一化 normalizeQuaternion(kf_.statePost); } // 更新状态转移矩阵 void updateTransitionMatrix(float dt) { // 获取当前状态 float* state = kf_.statePost.ptr<float>(); float qw = state[0], qx = state[1], qy = state[2], qz = state[3]; float bgx = state[4], bgy = state[5], bgz = state[6]; // 计算角速度(补偿偏置) float wx = gx_ - bgx; float wy = gy_ - bgy; float wz = gz_ - bgz; // 更新状态转移矩阵 kf_.transitionMatrix = (cv::Mat_<float>(7, 7) << 1, -wx*dt/2, -wy*dt/2, -wz*dt/2, -qx*dt/2, -qy*dt/2, -qz*dt/2, wx*dt/2, 1, wz*dt/2, -wy*dt/2, qw*dt/2, -qz*dt/2, qy*dt/2, wy*dt/2, -wz*dt/2, 1, wx*dt/2, qz*dt/2, qw*dt/2, -qx*dt/2, wz*dt/2, wy*dt/2, -wx*dt/2, 1, -qy*dt/2, qx*dt/2, qw*dt/2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); } // 卡尔曼更新步骤 void updateKalman() { // 获取Madgwick滤波器的输出 const float* madgwick_q = madgwick_.quaternion(); // 创建测量向量 cv::Mat measurement(4, 1, CV_32F); measurement.at<float>(0) = madgwick_q[0]; measurement.at<float>(1) = madgwick_q[1]; measurement.at<float>(2) = madgwick_q[2]; measurement.at<float>(3) = madgwick_q[3]; // 执行卡尔曼更新 kf_.correct(measurement); // 更新Madgwick滤波器状态(反馈机制) const float* kalman_q = kf_.statePost.ptr<float>(); madgwick_.setQuaternion(kalman_q); } // 四元数归一化 void normalizeQuaternion(cv::Mat& state) { float* q = state.ptr<float>(); float norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); if (norm > 0) { q[0] /= norm; q[1] /= norm; q[2] /= norm; q[3] /= norm; } } // 成员变量 cv::KalmanFilter kf_; // OpenCV卡尔曼滤波器 MadgwickFilter madgwick_; // Madgwick滤波器 std::chrono::steady_clock::time_point last_time_; float gx_, gy_, gz_; // 当前陀螺仪读数 }; // 生成模拟IMU数据 void generateIMUData(float& gx, float& gy, float& gz, float& ax, float& ay, float& az, int step, float true_roll = 0.0f, float true_pitch = 0.0f, float true_yaw = 0.0f) { static std::default_random_engine generator; static std::normal_distribution<float> noise(0.0f, 0.1f); // 真实角速度 (随时间变化) gx = 0.1f * sin(step * 0.05f) + noise(generator); gy = 0.05f * cos(step * 0.03f) + noise(generator); gz = 0.02f * sin(step * 0.02f) + noise(generator); // 加速度计数据 (重力 + 噪声 + 运动加速度) ax = noise(generator); ay = noise(generator); az = 9.81f + noise(generator); // 根据姿态调整加速度计数据 float roll = true_roll * 0.0174533f; // 角度转弧度 float pitch = true_pitch * 0.0174533f; // 旋转加速度向量 ax += sin(pitch) * 9.81f; ay -= sin(roll) * cos(pitch) * 9.81f; az -= cos(roll) * cos(pitch) * 9.81f; } // 示例主函数 int main() { // 创建融合滤波器 KalmanMadgwickFusion filter; // 模拟参数 float true_roll = 0.0f, true_pitch = 0.0f, true_yaw = 0.0f; // 模拟IMU数据流 for (int i = 0; i < 1000; ++i) { // 更新真实姿态(模拟运动) true_roll = 10.0f * sin(i * 0.01f); true_pitch = 5.0f * cos(i * 0.015f); true_yaw = 2.0f * sin(i * 0.02f); // 生成IMU数据 float gx, gy, gz, ax, ay, az; generateIMUData(gx, gy, gz, ax, ay, az, i, true_roll, true_pitch, true_yaw); // 更新滤波器 filter.update(gx, gy, gz, ax, ay, az); // 获取姿态 float roll, pitch, yaw; filter.getOrientation(roll, pitch, yaw); // 获取陀螺仪偏置估计 float bgx, bgy, bgz; filter.getGyroBias(bgx, bgy, bgz); // 输出姿态信息(每100步) if (i % 100 == 0) { std::cout << "Step " << i << ":\n"; std::cout << " True: Roll=" << true_roll << "°, Pitch=" << true_pitch << "°, Yaw=" << true_yaw << "°\n"; std::cout << " Estimated: Roll=" << roll << "°, Pitch=" << pitch << "°, Yaw=" << yaw << "°\n"; std::cout << " Gyro Bias: bx=" << bgx << ", by=" << bgy << ", bz=" << bgz << "\n"; std::cout << "=======================================\n"; } } return 0; } ``` ## 系统设计详解 ### 1. 融合架构 **双滤波器结构**: - **Madgwick滤波器**:作为前端的姿态估计器,快速融合加速度计和陀螺仪数据 - **卡尔曼滤波器**:作为后端优化器,平滑Madgwick的输出并估计陀螺仪偏置 **数据流向**: ``` IMU数据 → Madgwick滤波器 → 四元数 → 卡尔曼观测值 → 卡尔曼滤波 → 优化后的姿态 (陀螺仪偏置反馈)↖_______________________________↙ ``` ### 2. 卡尔曼滤波器设计 **状态向量**: ```cpp [qw, qx, qy, qz, bgx, bgy, bgz]^T ``` - `qw, qx, qy, qz`:姿态四元数 - `bgx, bgy, bgz`:陀螺仪偏置 **状态转移矩阵**: ```cpp kf_.transitionMatrix = (cv::Mat_<float>(7, 7) << 1, -wx*dt/2, -wy*dt/2, -wz*dt/2, -qx*dt/2, -qy*dt/2, -qz*dt/2, wx*dt/2, 1, wz*dt/2, -wy*dt/2, qw*dt/2, -qz*dt/2, qy*dt/2, wy*dt/2, -wz*dt/2, 1, wx*dt/2, qz*dt/2, qw*dt/2, -qx*dt/2, wz*dt/2, wy*dt/2, -wx*dt/2, 1, -qy*dt/2, qx*dt/2, qw*dt/2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); ``` 该矩阵基于四元数微分方程推导,同时包含了对陀螺仪偏置的建模。 ### 3. 关键创新点 1. **动态状态转移矩阵**: - 每次
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值