突破Java视觉识别瓶颈:changzengli/yolo-onnx-java高级功能与工业级扩展指南

突破Java视觉识别瓶颈:changzengli/yolo-onnx-java高级功能与工业级扩展指南

【免费下载链接】yolo-onnx-java Java开发视觉智能识别项目 纯java 调用 yolo onnx 模型 AI 视频 识别 支持 yolov5 yolov8 yolov7 yolov9 yolov10,yolov11,paddle ,obb,seg ,detection,包含 预处理 和 后处理 。java 目标检测 目标识别,可集成 rtsp rtmp,车牌识别,人脸识别,跌倒识别,打架识别,车牌识别,人脸识别 等 【免费下载链接】yolo-onnx-java 项目地址: https://gitcode.com/changzengli/yolo-onnx-java

引言:Java开发者的AI视觉困境与解决方案

你是否还在为Java平台缺乏高效的计算机视觉解决方案而苦恼?是否因Python生态的强势而被迫在生产环境中进行多语言混合开发?changzengli/yolo-onnx-java项目为Java开发者带来了福音,彻底改变了这一局面。本文将深入探讨如何充分利用该项目的高级功能,构建工业级的视觉智能应用系统。

读完本文,你将能够:

  • 掌握多模型部署与优化技巧,实现YOLO全系列模型的高效推理
  • 构建实时视频流处理管道,轻松集成RTSP/RTMP协议
  • 开发复杂场景下的智能分析应用,如行为识别、异常检测
  • 优化模型性能,解决Java环境下的性能瓶颈
  • 了解实际项目中的最佳实践与避坑指南

核心功能架构解析

changzengli/yolo-onnx-java项目采用模块化设计,提供了从图像预处理到结果后处理的完整解决方案。项目核心架构如下:

mermaid

多模型支持矩阵

项目支持多种模型和任务类型,满足不同场景需求:

模型类型支持版本主要应用场景输入尺寸典型FPS(CPU)
YOLOv5v3-v6.2通用目标检测640x64015-25
YOLOv7全部实时目标检测640x64020-30
YOLOv8全部检测/分割/姿态640x64025-40
YOLOv9全部高精度检测640x64018-28
YOLOv10全部最新架构640x64022-35
姿态估计YOLOv7-w6-pose行为分析960x9608-15
车牌识别自定义模型交通管理48x16830-50

高级功能实战指南

1. 多模型部署与优化

1.1 模型加载与管理

项目提供了灵活的模型加载机制,可以同时加载多个模型进行联合推理:

// 加载目标检测模型
OrtEnvironment environment = OrtEnvironment.getEnvironment();
OrtSession.SessionOptions sessionOptions = new OrtSession.SessionOptions();
OrtSession detectionSession = environment.createSession("yolov8n.onnx", sessionOptions);

// 加载姿态估计模型
OrtEnvironment poseEnv = OrtEnvironment.getEnvironment();
OrtSession poseSession = poseEnv.createSession("yolov7-w6-pose.onnx", sessionOptions);
1.2 推理引擎优化

针对Java环境特点,可通过以下方式优化推理性能:

// 启用CPU多线程
sessionOptions.setInterOpNumThreads(Runtime.getRuntime().availableProcessors());
sessionOptions.setIntraOpNumThreads(Runtime.getRuntime().availableProcessors() * 2);

// 启用内存复用
sessionOptions.setOptimizationLevel(OrtSession.SessionOptions.OptLevel.ALL_OPT);

// GPU加速配置 (如支持)
sessionOptions.addCUDA(0); // 使用第0个GPU
1.3 模型量化与精度平衡

为进一步提升性能,可对模型进行量化处理:

// 注意:实际量化需在模型导出时完成,此处为加载量化模型示例
OrtSession quantizedSession = environment.createSession("yolov8n-int8.onnx", sessionOptions);

2. 实时视频流处理技术

2.1 视频流处理架构

项目采用生产者-消费者模式处理视频流,有效平衡性能与资源占用:

mermaid

2.2 RTSP/RTMP流集成实现

下面是集成RTSP/RTMP视频流的完整代码示例:

// 视频流处理示例 (CameraDetectionWarnDemo.java 核心代码)
public class CameraDetectionWarnDemo {
    public static void main(String[] args) throws OrtException {
        // 加载OpenCV本地库
        nu.pattern.OpenCV.loadLocally();
        
        // 根据操作系统加载FFmpeg支持库
        String OS = System.getProperty("os.name").toLowerCase();
        if (OS.contains("win")) {
            System.load(ClassLoader.getSystemResource("lib/opencv_videoio_ffmpeg470_64.dll").getPath());
        }
        
        // 初始化模型
        String modelPath = "src/main/resources/model/yolov7-tiny.onnx";
        OrtEnvironment environment = OrtEnvironment.getEnvironment();
        OrtSession.SessionOptions sessionOptions = new OrtSession.SessionOptions();
        OrtSession session = environment.createSession(modelPath, sessionOptions);
        
        // 打开视频流 - 支持RTSP/RTMP/摄像头/本地文件
        VideoCapture video = new VideoCapture();
        boolean opened = video.open("rtsp://192.168.1.100:554/stream1"); // RTSP示例
        
        // 备用方案:打开本地摄像头
        if (!opened) {
            video.open(0); // 尝试本地摄像头
        }
        
        // 备用方案:打开本地视频文件
        if (!video.isOpened()) {
            video.open("video/car3.mp4"); // 最后尝试本地视频
        }
        
        // 检查视频流是否成功打开
        if (!video.isOpened()) {
            System.err.println("无法打开视频源,请检查连接或文件路径");
            return;
        }
        
        // 跳帧检测配置 - 平衡性能与实时性
        int detectSkip = 3; // 每3帧检测一次
        int detectSkipIndex = 0;
        
        // 主循环
        Mat frame = new Mat();
        while (video.read(frame)) {
            detectSkipIndex++;
            if (detectSkipIndex % detectSkip != 0) {
                continue; // 跳帧处理
            }
            
            // 帧处理与推理
            Mat processedFrame = preprocess(frame);
            List<Detection> results = infer(session, processedFrame);
            
            // 结果可视化
            drawResults(frame, results);
            
            // 业务逻辑处理
            processBusinessLogic(results);
            
            // 显示结果
            HighGui.imshow("实时监控", frame);
            
            // 按键退出
            if (HighGui.waitKey(1) == 27) { // ESC键
                break;
            }
        }
        
        // 资源释放
        video.release();
        HighGui.destroyAllWindows();
    }
    
    // 其他方法实现...
}
2.3 跳帧策略与性能平衡

在资源有限的情况下,合理的跳帧策略可以显著提升系统整体性能:

// 智能跳帧实现
int detectSkip = 4; // 初始跳帧间隔
int detectSkipIndex = 1;
float[][] outputData = null; // 缓存推理结果

while (video.read(img)) {
    if ((detectSkipIndex % detectSkip == 0) || outputData == null) {
        // 执行推理并缓存结果
        image = img.clone();
        image = letterbox.letterbox(image);
        // ...预处理和推理代码...
        outputData = (float[][]) output.get(0).getValue();
        detectSkipIndex = 1;
    } else {
        detectSkipIndex++;
    }
    
    // 使用缓存的推理结果进行后处理
    // ...
}

3. 高级应用场景实战

3.1 行为分析系统:跌倒与异常行为检测

基于姿态估计技术,我们可以构建行为分析系统,实现跌倒检测等功能:

// PoseEstimation.java核心代码分析
public class PoseEstimation {
    public static void main(String[] args) throws OrtException {
        // 加载模型
        String modelPath = "src/main/resources/model/yolov7-w6-pose.onnx";
        OrtEnvironment environment = OrtEnvironment.getEnvironment();
        OrtSession session = environment.createSession(modelPath, new OrtSession.SessionOptions());
        
        // 读取图像
        Mat img = Imgcodecs.imread("images/pose.jpg");
        Mat image = img.clone();
        
        // 预处理
        Letterbox letterbox = new Letterbox();
        letterbox.setNewShape(new Size(960, 960));
        letterbox.setStride(64);
        image = letterbox.letterbox(image);
        
        // 准备输入数据
        float[] pixels = preprocessImage(image);
        
        // 推理
        OnnxTensor tensor = OnnxTensor.createTensor(environment, FloatBuffer.wrap(pixels), 
                                                  new long[]{1, 3, 960, 960});
        Map<String, OnnxTensor> inputs = new HashMap<>();
        inputs.put(session.getInputInfo().keySet().iterator().next(), tensor);
        OrtSession.Result output = session.run(inputs);
        
        // 处理结果
        float[][] outputData = ((float[][]) output.get(0).getValue());
        List<PEResult> results = new ArrayList<>();
        for (float[] datum : outputData) {
            PEResult result = new PEResult(datum);
            if (result.getScore() > PEConfig.personScoreThreshold) {
                results.add(result);
            }
        }
        
        // NMS后处理
        results = nms(results, PEConfig.IoUThreshold);
        
        // 姿态分析与行为判断
        for (PEResult result : results) {
            List<KeyPoint> keyPoints = result.getKeyPointList();
            boolean isFalling = detectFall(keyPoints); // 跌倒检测逻辑
            if (isFalling) {
                System.out.println("检测到跌倒行为!");
                // 触发告警逻辑
            }
        }
    }
    
    // 跌倒检测核心算法
    private static boolean detectFall(List<KeyPoint> keyPoints) {
        // 获取关键节点
        KeyPoint nose = keyPoints.get(0); // 鼻子
        KeyPoint leftHip = keyPoints.get(11); // 左髋
        KeyPoint rightHip = keyPoints.get(12); // 右髋
        KeyPoint leftAnkle = keyPoints.get(15); // 左脚踝
        KeyPoint rightAnkle = keyPoints.get(16); // 右脚踝
        
        // 检查关键点可见性
        if (nose.getScore() < 0.5 || leftHip.getScore() < 0.5 || rightHip.getScore() < 0.5 ||
            leftAnkle.getScore() < 0.5 || rightAnkle.getScore() < 0.5) {
            return false; // 关键点分数不足,无法判断
        }
        
        // 计算身体宽高比 - 跌倒时宽高比增大
        float hipY = Math.max(leftHip.getY(), rightHip.getY());
        float ankleY = Math.max(leftAnkle.getY(), rightAnkle.getY());
        float height = ankleY - nose.getY();
        float width = Math.abs(leftHip.getX() - rightHip.getX()) * 2;
        
        return width / height > 0.8; // 宽高比阈值,根据实际情况调整
    }
}
3.2 车牌识别系统:从检测到识别的完整流程

项目提供了端到端的车牌识别解决方案,流程如下:

mermaid

实现代码示例:

// PlateDetection.java核心代码分析
public class PlateDetection {
    public static void main(String[] args) throws OrtException {
        // 1. 加载车牌检测模型
        String detectModelPath = "src/main/resources/model/plate_detect.onnx";
        OrtSession detectSession = createSession(detectModelPath);
        
        // 2. 加载车牌识别模型
        String recModelPath = "src/main/resources/model/plate_rec_color.onnx";
        OrtSession recSession = createSession(recModelPath);
        
        // 3. 处理图像目录
        String imagePath = "carimg";
        Map<String, String> imageFiles = getImagePathMap(imagePath);
        
        for (String filePath : imageFiles.values()) {
            // 4. 读取图像
            Mat img = Imgcodecs.imread(filePath);
            
            // 5. 车牌检测
            List<CarDetection> detections = detectPlates(detectSession, img);
            
            // 6. 车牌识别
            for (CarDetection detection : detections) {
                // 裁剪车牌区域
                Mat plateRegion = cropPlateRegion(img, detection.getBbox());
                
                // 识别车牌号码和颜色
                String plateNo = recognizePlate(recSession, plateRegion);
                String plateColor = recognizePlateColor(recSession, plateRegion);
                
                // 设置结果
                detection.setPlateNo(plateNo);
                detection.setPlateColor(plateColor);
                
                System.out.println("车牌识别结果: " + plateColor + "-" + plateNo);
                
                // 7. 结果可视化
                drawPlateResult(img, detection);
            }
            
            // 显示结果
            HighGui.imshow("车牌识别结果", img);
            HighGui.waitKey();
        }
    }
    
    // 车牌检测实现
    private static List<CarDetection> detectPlates(OrtSession session, Mat img) throws OrtException {
        // 预处理
        Letterbox letterbox = new Letterbox();
        Mat processedImg = letterbox.letterbox(img);
        
        // 准备输入
        float[] inputData = preprocessImage(processedImg);
        OnnxTensor tensor = OnnxTensor.createTensor(OrtEnvironment.getEnvironment(), 
            FloatBuffer.wrap(inputData), new long[]{1, 3, 640, 640});
        
        // 推理
        Map<String, OnnxTensor> inputs = new HashMap<>();
        inputs.put(session.getInputInfo().keySet().iterator().next(), tensor);
        OrtSession.Result output = session.run(inputs);
        
        // 后处理
        float[][] outputData = ((float[][][]) output.get(0).getValue())[0];
        return postprocessDetections(outputData, letterbox);
    }
    
    // 车牌识别实现
    private static String recognizePlate(OrtSession session, Mat plateImg) throws OrtException {
        // 预处理车牌图像
        Letterbox letterbox = new Letterbox(168, 48);
        Mat processedPlate = letterbox.letterbox(plateImg);
        
        // 准备输入
        float[] inputData = preprocessPlate(processedPlate);
        OnnxTensor tensor = OnnxTensor.createTensor(OrtEnvironment.getEnvironment(), 
            FloatBuffer.wrap(inputData), new long[]{1, 3, 48, 168});
        
        // 推理
        Map<String, OnnxTensor> inputs = new HashMap<>();
        inputs.put(session.getInputInfo().keySet().iterator().next(), tensor);
        OrtSession.Result output = session.run(inputs);
        
        // 解码结果
        float[][][] result = (float[][][]) output.get(0).getValue();
        return decodePlate(maxScoreIndex(result[0]));
    }
}
3.3 多模型融合:构建复杂场景分析系统

在实际应用中,常常需要多个模型协同工作,构建完整的解决方案:

// 多模型融合示例 - 智能监控系统
public class SmartSurveillanceSystem {
    private OrtSession objectDetectionSession;
    private OrtSession poseEstimationSession;
    private OrtSession plateDetectionSession;
    
    public SmartSurveillanceSystem() throws OrtException {
        // 初始化所有模型
        objectDetectionSession = loadModel("yolov8n.onnx");
        poseEstimationSession = loadModel("yolov7-w6-pose.onnx");
        plateDetectionSession = loadModel("plate_detect.onnx");
    }
    
    public void processFrame(Mat frame) throws OrtException {
        // 1. 目标检测 - 检测场景中的所有目标
        List<Detection> objects = detectObjects(objectDetectionSession, frame);
        
        // 2. 针对不同目标应用特定模型
        for (Detection obj : objects) {
            if ("person".equals(obj.getLabel())) {
                // 对人员进行姿态分析
                List<KeyPoint> keypoints = estimatePose(poseEstimationSession, frame, obj.getBbox());
                
                // 行为分析
                if (isFalling(keypoints)) {
                    triggerAlarm("人员跌倒警报", obj.getBbox());
                } else if (isFighting(keypoints)) {
                    triggerAlarm("打架行为警报", obj.getBbox());
                }
            } else if ("car".equals(obj.getLabel())) {
                // 对车辆进行车牌识别
                String plateInfo = recognizePlate(plateDetectionSession, frame, obj.getBbox());
                obj.setExtraInfo("plate", plateInfo);
            }
        }
        
        // 3. 结果可视化
        drawResults(frame, objects);
    }
    
    // 其他方法实现...
}

性能优化与部署最佳实践

1. Java环境性能调优

Java环境下的性能优化需要综合考虑JVM配置、内存管理和线程模型:

// JVM优化参数示例
java -Xmx4g -Xms4g -XX:+UseG1GC -XX:MaxGCPauseMillis=20 \
     -XX:+UseParallelGC -XX:ParallelGCThreads=4 \
     -jar your-application.jar

2. 内存管理最佳实践

在处理大量图像数据时,合理的内存管理至关重要:

// 高效内存管理示例
public class MemoryEfficientProcessor {
    private Mat reusableMat = new Mat(); // 可重用的Mat对象
    
    public Mat processImage(Mat input) {
        // 避免频繁创建新对象
        if (reusableMat.size() != input.size()) {
            reusableMat.release(); // 释放旧内存
            reusableMat = new Mat(input.size(), input.type());
        }
        
        // 处理图像
        Imgproc.cvtColor(input, reusableMat, Imgproc.COLOR_BGR2RGB);
        
        // 返回处理结果的拷贝,原对象可继续重用
        Mat result = reusableMat.clone();
        return result;
    }
    
    // 资源释放
    public void release() {
        reusableMat.release();
    }
}

3. 多线程处理框架

使用Java并发框架优化多模型推理性能:

// 多线程推理示例
public class MultiThreadedInferenceEngine {
    private ExecutorService executor;
    private List<OrtSession> sessionPool; // 模型会话池
    
    public MultiThreadedInferenceEngine(String modelPath, int threadCount) throws OrtException {
        // 创建线程池
        executor = Executors.newFixedThreadPool(threadCount);
        
        // 创建模型会话池
        sessionPool = new ArrayList<>();
        OrtSession.SessionOptions options = new OrtSession.SessionOptions();
        options.setIntraOpNumThreads(1); // 每个会话使用1个线程
        
        for (int i = 0; i < threadCount; i++) {
            sessionPool.add(OrtEnvironment.getEnvironment().createSession(modelPath, options));
        }
    }
    
    // 异步推理
    public Future<List<Detection>> inferAsync(Mat image) {
        return executor.submit(() -> {
            // 获取会话 (简单轮询策略)
            OrtSession session = sessionPool.get((int)(Thread.currentThread().getId() % sessionPool.size()));
            
            // 执行推理
            return performInference(session, image);
        });
    }
    
    // 关闭资源
    public void shutdown() {
        executor.shutdown();
        sessionPool.forEach(session -> {
            try {
                session.close();
            } catch (OrtException e) {
                e.printStackTrace();
            }
        });
    }
    
    // 实际推理实现
    private List<Detection> performInference(OrtSession session, Mat image) throws OrtException {
        // 推理逻辑实现...
    }
}

4. 跨平台部署指南

4.1 Windows部署
  1. 安装OpenCV并配置环境变量
  2. 将OpenCV的dll文件复制到项目lib目录
  3. 确保JRE版本与OpenCV版本匹配
4.2 Linux部署
# Ubuntu依赖安装
sudo apt-get update
sudo apt-get install -y libopencv-dev openjdk-11-jdk

# 运行应用
java -Djava.library.path=/usr/local/lib -jar your-application.jar
4.3 Docker容器化
FROM openjdk:11-jre-slim

# 安装依赖
RUN apt-get update && apt-get install -y libopencv-dev libgtk2.0-0

# 设置工作目录
WORKDIR /app

# 复制应用
COPY target/*.jar app.jar

# 运行应用
ENTRYPOINT ["java", "-Djava.library.path=/usr/lib/x86_64-linux-gnu", "-jar", "app.jar"]

常见问题与解决方案

1. 模型加载失败

问题OrtException: Failed to load model

解决方案

  • 检查模型路径是否正确
  • 验证ONNX模型版本是否兼容
  • 确保有足够的内存加载模型
  • 检查依赖库版本是否匹配

2. 视频流无法打开

问题无法打开视频流,请检查连接

解决方案

  • 使用VLC等工具验证视频流URL是否有效
  • 检查FFmpeg库是否正确加载
  • 确认网络连接和权限
  • 对于RTSP流,尝试降低分辨率或更改编码格式

3. 推理速度慢

问题:处理速度无法满足实时要求

解决方案

  • 启用跳帧处理
  • 降低输入分辨率
  • 使用更小的模型(如nano或tiny版本)
  • 优化线程配置
  • 考虑使用GPU加速

4. 中文显示乱码

问题:结果可视化时中文标签显示乱码

解决方案

// 使用支持中文的字体
Graphics2D g2d = bufferedImage.createGraphics();
Font font = new Font("SimHei", Font.PLAIN, 20); // 使用黑体
g2d.setFont(font);
g2d.setColor(Color.RED);
g2d.drawString("中文标签", x, y);
g2d.dispose();

未来扩展与进阶方向

1. 自定义模型集成

项目支持集成自定义的ONNX模型,只需实现统一的接口:

// 自定义模型集成示例
public class CustomModelDetector implements Detector {
    private OrtSession session;
    private Preprocessor preprocessor;
    private Postprocessor postprocessor;
    
    public CustomModelDetector(String modelPath) throws OrtException {
        // 初始化模型
        OrtEnvironment environment = OrtEnvironment.getEnvironment();
        session = environment.createSession(modelPath, new OrtSession.SessionOptions());
        
        // 初始化预处理和后处理
        preprocessor = new CustomPreprocessor();
        postprocessor = new CustomPostprocessor();
    }
    
    @Override
    public List<Detection> detect(Mat image) throws OrtException {
        // 预处理
        float[] input = preprocessor.process(image);
        
        // 推理
        OnnxTensor tensor = OnnxTensor.createTensor(OrtEnvironment.getEnvironment(), 
            FloatBuffer.wrap(input), getInputShape());
        Map<String, OnnxTensor> inputs = new HashMap<>();
        inputs.put(session.getInputInfo().keySet().iterator().next(), tensor);
        
        OrtSession.Result output = session.run(inputs);
        
        // 后处理
        return postprocessor.process(output);
    }
    
    // 其他方法实现...
}

2. 分布式推理系统

对于大规模部署,可以构建分布式推理系统:

mermaid

3. 模型动态更新机制

实现模型的热更新,无需重启系统即可更新检测模型:

// 模型热更新示例
public class HotSwappableDetector {
    private volatile Detector currentDetector;
    private String modelPath;
    
    public HotSwappableDetector(String initialModelPath) throws OrtException {
        this.modelPath = initialModelPath;
        this.currentDetector = new YoloDetector(initialModelPath);
    }
    
    public List<Detection> detect(Mat image) throws OrtException {
        return currentDetector.detect(image); // 使用volatile保证线程安全
    }
    
    public void updateModel(String newModelPath) throws OrtException {
        // 创建新的检测器实例
        Detector newDetector = new YoloDetector(newModelPath);
        
        // 原子替换当前检测器
        this.currentDetector = newDetector;
        
        // 可选:异步释放旧模型资源
        new Thread(() -> {
            try {
                Thread.sleep(5000); // 等待旧模型使用完毕
                // 释放旧模型资源
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
        
        this.modelPath = newModelPath;
    }
}

结语:Java视觉智能的未来

changzengli/yolo-onnx-java项目为Java开发者打开了计算机视觉的大门,使Java在AI视觉领域不再是配角。通过本文介绍的高级功能和扩展技巧,你可以构建从简单目标检测到复杂行为分析的全系列视觉智能应用。

随着项目的不断发展,Java平台上的计算机视觉应用将变得越来越强大和普及。无论是工业质检、智能监控、交通管理还是医疗影像,Java开发者都可以凭借该项目快速构建高性能的视觉智能系统。

最后,我们鼓励开发者积极参与项目贡献,共同推动Java视觉智能生态的发展。无论是提交bug修复、添加新功能,还是分享应用案例,都将帮助这个项目变得更加完善。

附录:资源与学习路径

官方资源

  • 项目仓库:https://gitcode.com/changzengli/yolo-onnx-java

学习路径

  1. 基础阶段:掌握项目基本用法和目标检测功能
  2. 进阶阶段:实现视频流处理和多模型集成
  3. 高级阶段:性能优化和复杂场景应用开发
  4. 专家阶段:自定义模型集成和分布式系统构建

推荐学习资源

  • ONNX官方文档:了解模型格式和规范
  • OpenCV Java教程:掌握图像处理基础
  • YOLO系列论文:深入理解目标检测原理
  • Java并发编程实战:优化多线程处理

常见应用场景代码模板

  • 实时视频监控系统
  • 车牌识别与违章检测
  • 安全生产行为分析
  • 智能零售客流统计
  • 工业质检缺陷检测

【免费下载链接】yolo-onnx-java Java开发视觉智能识别项目 纯java 调用 yolo onnx 模型 AI 视频 识别 支持 yolov5 yolov8 yolov7 yolov9 yolov10,yolov11,paddle ,obb,seg ,detection,包含 预处理 和 后处理 。java 目标检测 目标识别,可集成 rtsp rtmp,车牌识别,人脸识别,跌倒识别,打架识别,车牌识别,人脸识别 等 【免费下载链接】yolo-onnx-java 项目地址: https://gitcode.com/changzengli/yolo-onnx-java

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值