修改版-------Caffe转NCNN并移植Android配置记录

深度学习模型移植pytorch->onnx->ncnn->android 深度学习模型移植pytorch->onnx->ncnn->androidpytorch->onnxonnx->ncnnncnn->android 最近做项目需要在手机上跑深度学习的模型,踩了不少坑,做个记录。这里以mobilenetv3为例子。 pytorch->onnx 1.环境配置 pytorch 1.0 之后自带onnx输出,所以是个很好的选择,顺便... 阅读详情

实验目的:

将caffe模型转成ncnn可以实现在移动端运行深度学习模型,主要使用:
https://github.com/Tencent/ncnn
实验环境:
1、系统环境

    Mac OS Mojave系统
    编译好的caffe源码(可以参考我之前的博客:https://blog.youkuaiyun.com/sinat_28731575/article/details/78958348)

2、软件

    Android Studio 3.2
    Genymotion虚拟机
    (参考:http://www.open-open.com/lib/view/open1466430392743.html)

实验过程
1、实验准备

1、将 https://github.com/Tencent/ncnn clone到本地后解压,可以看到下面的组织结构:

其中

    examples是简单的在安卓上使用NCNN的例子,有一个根据这个例子编译好的Android Studio工程: https://github.com/dangbo/ncnn-mobile
    tools是后面需要用到的一些工具代码,包含了将各种网络转换到NCNN的代码

2、编译好的caffe源码用于后面转换模型使用
2、编译NCNN

(1)参照:https://github.com/Tencent/ncnn/wiki/how-to-build
中选择一个需要的环境编译,因为我需要在Android上面使用,所以选择了“Build for Android”:
这里首先需要安装NDK来编译Android项目,配置NDK环境有以下两种方式:

    使用Android Studio来直接安装:
   
    在偏好设置中进行如上图所示的配置,就可以配置NDK编译环境以及相关工具,安装好后NDK存放在上面的sdk目录下的ndk-bundle文件夹中

    自己到网站上面下载的方式:
    下载网址为:http://developer.android.com/ndk/downloads/index.html
    选择合适的版本下载(因为上面的第一种方法虽然简单,但是默认下载最新的NDK,在编译的时候可能会出现后面我会讲到的一些问题,所以这种方式可以根据实际需要选择合适的版本)
    解压上面下载的NDK压缩包
    使用下面的命令配置环境变量:

vim ~/.bash_profile

# 在.bash_profile文件的最后添加上(路径根据自己的进行修改):
export PATH=$PATH:/Users/camlin_z/Data/Project/AndroidStudioProjects/android-ndk-r10e
# 或者想把环境变量添加成Android Studio配置的NDK的话:
export ANDROID_SDK="/Users/camlin_z/Library/Android/sdk"
export ANDROID_NDK="/Users/camlin_z/Library/Android/sdk/ndk-bundle"
export PATH="$PATH:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools:$ANDROID_NDK"

source ~/.bash_profile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

或者想要替换Android Studio中的NDK环境为自己下的版本的话将上面下载的NDK压缩包重命名为ndk-bundle后放到sdk目录下即可

(2)编译libncnn.a
根据上面ncnn的github下的教程有:

$ cd <ncnn-root-dir>
$ mkdir -p build-android-armv7
$ cd build-android-armv7
$ cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
    -DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON \
    -DANDROID_PLATFORM=android-14 ..
$ make -j4
$ make install

    1
    2
    3
    4
    5
    6
    7
    8

即可“build armv7 library”,之后便会在build-android-armv7/install/lib目录下生成libncnn.a,这样ncnn的编译工作就完成了
3、使用NCNN将caffemodel转换成NCNN中需要的格式

参照上面ncnn的github下第二个教程:
https://github.com/Tencent/ncnn/wiki/how-to-use-ncnn-with-alexnet
首先是下载模型以及权重文件:

train.prototxt
deploy.prototxt
snapshot_10000.caffemodel

    1
    2
    3

然后使用之前编译好的caffe中build/tools文件夹下的upgrade_net_proto_text和upgrade_net_proto_binary两个文件分别处理模型以及权重文件:

upgrade_net_proto_text [old prototxt] [new prototxt]
upgrade_net_proto_binary [old caffemodel] [new caffemodel]

    1
    2

同时要更改数据层的batchsize大小为1:

layer {
  name: "data"
  type: "Input"
  top: "data"
  input_param { shape: { dim: 1 dim: 3 dim: 227 dim: 227 } }
}

    1
    2
    3
    4
    5
    6

经过上面的步骤就准备好了需要转换的模型和权重文件。

接下来进入之前clone的 ncnn工程文件:

cd tools/caffe
mkdir build

cd build
cmake ..
make -j4

    1
    2
    3
    4

就可以在build文件夹中生成caffe2ncnn.cpp对应的可执行文件caffe2ncnn,最后执行:

caffe2ncnn deploy.prototxt bvlc_alexnet.caffemodel alexnet.param alexnet.bin

    1

就可以得到最后转化的权重以及模型文件:alexnet.param alexnet.bin
4、编译jni生成了.so库文件

进入刚刚ncnn工程下的examples中,这是一个用squeeze net作为例子来生成动态链接库的例子,可以看到examples下面有已经按照3中步骤生成好的squeeze net对应的权重和模型文件,

进入的squeezencnn/jni文件夹中,可以看到如下文件架结构:

其中的cpp和h就是我们需要编写的C++文件和头文件,其中包含以下几个部分:

    我们需要的C++功能函数以及对应的头文件
    C++和java之间的jni接口函数,用于两者之间的信息互通

然后在终端使用

ndk-build

    1

命令就可以将上面的文件打包成一个 .so动态链接库供Android调用,可以参考:
https://blog.youkuaiyun.com/CrazyMo_/article/details/52804896 中的讲解,下面我以squeeze net这个例子简单说明一下安卓调用的过程:
首先是Android Studio工程中的结构为:

实际上上图中的工程顺序也就是我们建立我们工程的顺序:

    按照上面3中的步骤转换的模型就放在assets目录下
    然后我们除了MainActivity.java,就可以定义一个自己需要的函数接口类代码,比如这里的SqueezeNcnn.java,里面的内容为:

package com.tencent.squeezencnn;

import android.graphics.Bitmap;
import android.content.Context;

public class SqueezeNcnn
{
    // 我们自己定义的类方法,用于实现我们自己的功能(这里可以看到是java)
    public native boolean Init(byte[] param, byte[] bin, byte[] words);

    public native String Detect(Bitmap bitmap);

    static {
        System.loadLibrary("squeezencnn");
    }
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

然后可以参考:https://blog.youkuaiyun.com/createchance/article/details/53783490
来自动生成jni文件夹下的squeezenet_v1.1.id.h和squeezencnn_jni.cpp,然后在其中进一步编写我们需要实现的功能函数

    接着就是JNI代码了,这个部分实际上包含了实现功能的C/C++代码以及jni接口函数两部分,通过上面的生成,我们得到了squeezenet_v1.1.id.h和squeezencnn_jni.cpp,对应于上面SqueezeNcnn.java中的类方法,squeezencnn_jni.cpp中有对应的JNI接口函数:
   
    (函数具体内容大家可以到ncnn工程中查看,这里为了说明方便隐去内容)
    可以看到jni接口函数是在java类函数的前面加上了

Java_com_tencent_squeezencnn_SqueezeNcnn_

    1

部分,将java的native方法转换成C函数声明的规则是这样的:Java_{package_and_classname}_{function_name}(JNI arguments)。包名中的点换成单下划线。需要说明的是生成函数中的两个参数:
JNIEnv *:这是一个指向JNI运行环境的指针,后面我们会看到,我们通过这个指针访问JNI函数
jobject:这里指代java中的this对象

而对于一些不是接口的功能函数,我们就可以使用C++或者C来编写,而不需要考虑jni

    最后就是将上面的代码编译成libsqueezencnn.so动态库
    这里我们首先需要编写jni目录下的编译配置文件 Android.mk 和 Application.mk ,类似于C++编译中的CMakeLists.txt:

Android. mk :

LOCAL_PATH := $(call my-dir)

# change this folder path to yours
NCNN_INSTALL_PATH := /Users/camlin_z/Data/Project/AndroidStudioProjects/ncnn-master/build-android-armv7/install

include $(CLEAR_VARS)
LOCAL_MODULE := ncnn
# LOCAL_SRC_FILES := $(NCNN_INSTALL_PATH)/$(TARGET_ARCH_ABI)/libncnn.a
LOCAL_SRC_FILES := $(NCNN_INSTALL_PATH)/lib/libncnn.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := squeezencnn
LOCAL_SRC_FILES := squeezencnn_jni.cpp

LOCAL_C_INCLUDES := $(NCNN_INSTALL_PATH)/include

LOCAL_STATIC_LIBRARIES := ncnn

LOCAL_CFLAGS := -O2 -fvisibility=hidden -fomit-frame-pointer -fstrict-aliasing -ffunction-sections -fdata-sections -ffast-math
LOCAL_CPPFLAGS := -O2 -fvisibility=hidden -fvisibility-inlines-hidden -fomit-frame-pointer -fstrict-aliasing -ffunction-sections -fdata-sections -ffast-math
LOCAL_LDFLAGS += -Wl,--gc-sections

LOCAL_CFLAGS += -fopenmp
LOCAL_CPPFLAGS += -fopenmp
LOCAL_LDFLAGS += -fopenmp

LOCAL_LDLIBS := -lz -llog -ljnigraphics

include $(BUILD_SHARED_LIBRARY)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

具体里面的配置方法可以参考:
http://www.cnblogs.com/wainiwann/p/3837936.html

Application. mk:

# APP_STL := stlport_static
APP_STL := gnustl_static
# APP_ABI := armeabi armeabi-v7a

# 注意此处哟啊对应你之前编译ncnn时的版本,比如我之前用的就是armeabi-v7a
# 下面就要指定为armeabi-v7a,不能再有后面的arm64-v8a
APP_ABI := armeabi-v7a #arm64-v8a

APP_PLATFORM := android-14
# NDK_TOOLCHAIN_VERSION := 4.9

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

写好上面的各个配置文件之后就可以在终端进入jni文件夹输入:

ndk-build

    1

命令进行编译生成 libsqueezencnn. so动态链接库,经过了以上的所有步骤得到最后的动态链接库,Android中的函数就可以直接调用来实现对应的功能了
---------------------  
作者:Camlin_Z  
来源:优快云  
原文:https://blog.youkuaiyun.com/sinat_28731575/article/details/83591920  
版权声明:本文为博主原创文章,转载请附上博文链接!

量子计算入门指南:密度算符的核心概念与应用解析 本文深入解析了量子计算中密度算符的核心概念与应用。作为描述量子系统“状态的状态”的关键数学工具,密度算符能有效处理混合态与子系统描述,是理解量子噪声、量子纠错和开放系统演化的基石。文章通过对比纯态与混合态,阐释了密度矩阵的数学定义与物理意义,并结合代码示例演示了其在实际量子计算问题中的强大威力。 阅读详情

相关推荐

从3D相机数据到三维模型:Halcon实战深度图、亮度图与点云转换全流程

本文详细解析了如何利用Halcon将3D相机采集的深度图、亮度图转换为三维点云模型的完整流程。通过实战案例分享,涵盖数据格式处理、点云生成方法(SDK接口与纯Halcon实现)、三维模型可视化优化等关键技术,帮助工程师解决工业检测中的实际难题,提升三维重建精度与效率。

weixin_42525005的博客 397

CFLAGS用法

CFLAGS 表示用于 C 编译器的选项, CXXFLAGS 表示用于 C++ 编译器的选项。 这两个变量实际上涵盖了编译和汇编两个步骤。 CFLAGS: 指定头文件(.h文件)的路径,如:CFLAGS=-I/usr/include -I/path/include。同样地,安装一个包时会在安装路径下建立一个include目录,当安装过程中出现问题时,试着把以前安装的包的include目录加入到该变量中来。 LDFLAGS :gcc 等编译器会用到的一些优化参数,也可以在里面指定库文件的位置。用法:LDFLA

qq_40309341的博客 6071

玩转ubuntu18 --机器视觉方面(yolo算法识别及摄像头和cmake问题解决)

玩转ubuntu18 --机器视觉方面(yolo v3算法识别) 1.YOLO的简介 工作原理 先前的检测系统重新调整分类器或本地化器以执行检测。他们将模型应用于多个位置和比例尺的图像。图像的高分区域被视为检测。 我们使用完全不同的方法。我们将单个神经网络应用于整个图像。该网络将图像划分为区域,并预测每个区域的边界框和概率。这些边界框按预测概率加权。 我们的模型比基于分类器的系统具有几个优势。它在测试时间查看整个图像,因此其预测由图像中的全球上下文提供信息。它还通过单一网络评估进行预测,这与R-CNN等系统

qq_53951823的博客 1556

Cmake参数详细介绍

前言 CMake 是一个高效的C/C++ 代码(包括 JNI 开发)编译工具,而CMake 的使用,作为开发者最关心的就是如何编写 CMakeLists.txt 。今天就以Android studio这个开发工具为例,详细介绍一下如何在Android studio这个开发工具中使用CMake。首先需要了解一下如何在 gradle文件中配置这些参数。 gradle中常用配置参数 首先我们需要在项目的根目录的build.gradle这个文件中添加先关的配置以及CMakeLists.txt 文件的路径。如下所示:

hirezy 1万+

深度学习实战87-高中数学自适应测试系统研究与应用研发,前后台页面设计

大家好,我是微学AI ,今天给大家介绍一下深度学习实战87-高中数学自适应测试系统研究与应用研发,前后台页面设计。高中数学自适应测试系统旨在通过精准评估学生能力,用最少的题目发现其薄弱环节,并提供定制化的学习计划,帮助学生快速提升成绩。同时,系统结合了AI大模型实现自动判卷、生成报告,减轻教师负担,并支持个性化作业布置,使教学更加高效。学生可以清晰了解自身学习状态,教师也能获得精准的学生画像,实现差异化教学。

微学AI的博客 445

公交车调度排班优化算法研究与实现

本文提出的公交车调度排班优化算法基于遗传算法,能够较好地处理公交车调度排班问题,使得车辆数量和运营时间得到平衡,公交车的使用效率得到了优化。在模拟的公交车路线中,使用本文所提出的算法,得到了一组较优的公交车调度排班方案。其中,车辆数量的多少会影响到公交车的行驶速度和等候时间,而运营时间的长短则会直接影响到公交车的使用效率和成本。本文基于遗传算法,通过随机生成种群、选择、交叉、变异等操作,逐步优化种群中个体的适应度,最终得到较优的公交车调度排班方案。以下是本文中所使用的Matlab代码实现,供参考。

PixelLoom的博客 872

包体积优化总结

原文发布于:小木箱成长营关于 So 优化 首先我们来到第一部分内容关于 Native 层优化,关于 Native 层优化有六部分可以和大家说一下,第一部分内容是配置 abiFilters。第二部分内容是避免解压缩原生库.第三部分内容是移除调试符号。第四部分内容是 so 压缩方案.第五部分内容是 so 混淆方案.第六部分内容是包体监控。1.1 配置 abiFilters首先我们聊聊第一部分内容配置 ...

Android技术之家 1425

[EdgeAI] NXP eIQ 机器学习Toolkit (一):准备篇

eIQ™机器学习(ML)软件开发环境支持在恩智浦EdgeVerse™微控制器和微处理器(包括i.MX RT跨界MCU和i.MX系列应用处理器)上使用ML算法。eIQ ML软件包括称为eIQ Toolkit的ML工作流工具以及推理引擎、神经网络编译器和优化库。............

HowieXue 薛永浩的博客 1万+

(四)CMake编译选项

一、cmake、make的本质是编译选项的组织集合 本质上来说,make和cmake都是协助你进行编译的工具,用户完全可以通过g++ gcc按照编译器要求来进行直接编译,只不过make和cmake根据各自认为合适的组织规则方便我们进行编译管理罢了。如增加一个线程库: g++ *.cpp -o -lpthread test 这是g++编译器要求的样子。所有包含头文件、库文件、打包和链接库等操作都通过-选项来完成。 make为了减少和整合编译逻辑,将一些例如打包ar操作封装在一个变量AR中;一些编译器专用的选

Fishfishfishfishcat 4687

apollo-减速带通行

主车在通过减速带时速度不超过3m/s

是菜鸟o的博客 390

YOLOv8自定义训练:车牌识别全流程(从标注到推理,附可视化代码)

车牌检测全流程实践指南 摘要:本文详细介绍了基于YOLOv8的车牌检测完整实现方案。针对车牌检测中的三大难点(小目标、多角度、光照变化),提供了从数据准备到模型部署的全流程解决方案。重点包括:1)数据采集与标注规范;2)针对小目标的YOLOv8模型优化配置;3)K-means锚框聚类方法;4)训练参数调优策略。通过实际验证,该方法可获得95%以上的检测准确率,并附有完整的代码实现和可视化工具,便于开发者快速复现应用。 (字数:149字)

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 851

NCNN移植ARM爬坑日志 一

根据官网的教程转换: 进入$/home/wolf/caffe-master/build/tools upgrade_net_proto_text ../../models/bvlc_alexnet/deploy.prototxt /home/wolf/Downloads/test/ test.prototxt upgrade_net_proto_binary ../../../Downloa

wolf2345的博客 2781

咨询进阶——解读40页公司战略解码方法【附全文阅读】

战略解码是将企业战略转化为可执行计划的关键过程,强调垂直和水平一致性原则。通过KPI指标设计和目标分解,确保战略在各部门和岗位有效落地。解码过程包括战略澄清、目标牵引、绩效分解和承诺签订,输出战略解码图等文件。不同部门根据责任定位(如利润中心、绩效中心)采用差异化考核方式,实现战略有效执行。

cdfunlove的博客 150

Caffe转NCNN并移植Android配置记录

实验目的: 将caffe模型转成ncnn可以实现在移动端运行深度学习模型,主要使用: https://github.com/Tencent/ncnn 实验环境: 1、系统环境 Mac OS Mojave系统 编译好的caffe源码(可以参考我之前的博客:https://blog.csdn.net/sinat_28731575/article/details/78958348) 2、软件 An...

Camlin_Z的博客 2598

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

【Android Studio】【NCNN】YOLOV5安卓部署

利用ncnn将yolov5部署在安卓手机上

笔记 5200

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

[Android|深度学习移植]--基于ncnn的RK3399上的mtcnn人脸检测的实现

参考文章: https://blog.csdn.net/qq_33200967/article/details/82421089 https://blog.csdn.net/u014797226/article/details/79626693 https://blog.csdn.net/yhaolpz/article/details/71375762 1.在RK3399上烧录安卓系统(And...

Willing Tong的博客 4665

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

YOLOv5学习记录(二): 模型转化及Android端部署

YOLOv5学习记录(一): 训练自己的数据模型 YOLOv5学习记录(二): 模型转化-Android端部署 文章目录 系列文章目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文

Xiaoer_Lu的博客 1万+

出现错误/ncnn/src/cpu.cpp:426: undefined reference to `stderr'完美解决方案。

前提情况 1。 android studio 编译器 2。 利用ncnn前向推理框架进行移植caffemodel到android手机端 3。 使用cmake进行编译c++接口 出现问题

AI蜗牛车 6570

《学习&&工作笔记》Che_Hongshu个人笔记1

最近在公司做项目,具体过程,自己笔记本装个双系统win/linux,之后装caffe_ssd,下载Mobilenet,熟练掌握MobilenetSSD的使用,制作VOC数据集,训练model,运用剪枝方式进行剪裁,缩小加速model,最后用腾讯ncnn前向推理框架进行移植MobilenetSSD的model,以下是过程中出现问题解决问题的正确打开方式,和很多有一定参考价值的文章。 2018.10....

AI蜗牛车 1480

PC端NCNN部署

1 NCNN部署 1.在电脑端使用ncnn实现分类(alexnet) s1,安装g++,cmake,protobuf,opencv s2,对源码进行编译 git clone https://github.com/Tencent/ncnn $ cd <ncnn-root-dir> $ mkdir -p build $ cd build $ cmake .. $ make -j4 s3,...

mingo_敏 2408

我的第一个caffe Android程序

在上一篇文章《我的第一个caffe C++程序》中,说明了如何编写一个最简单的caffe C++程序,但我的最终目的是希望在Android app中使用caffe框架。所以接下来我就将模型测试程序testXOR移植到Android中,让Android app也能使用caffe深度学习框架。 caffe框架采用C++语言编写,具有良好的可移植性,不过官方代码并没有Android平台的移植。好在民间...

云水木石 3616

一个简单操作解决protobuf版本问题,复制粘贴你会吧

这个方法虽然简单,但是我们有完美的利用anaconda的解决方案,能够解决服务器上大家版本冲突,你想要几个环境就可以建立几个完全不冲突的环境,算是一本万利,教程在http://www.cnblogs.com/SweetBeens/p/8650460.html,推荐用这种方法。当然docker更好一些,但是老代码是没有docker文件的。 从头说起: 如何看你的需要安装的版本呢,上图: 注意看我

乱七八糟的笔记 3万+

在Android手机上使用腾讯的ncnn实现图像分类

目录 目录 前言 使用Ubuntu编译NCNN库 转换预测模型 开发Android项目 参考资料 前言 使用Ubuntu编译NCNN库 1、首先要下载和解压NDK。 wget https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip unzip android-ndk-r17b-l...

夜雨飘零 1万+

NCNN简单入门及安装

1.在电脑端使用ncnn实现分类(alexnet) s1,安装g++,cmake,protobuf,opencv s2,对源码进行编译 git clone https://github.com/Tencent/ncnn $ cd <ncnn-root-dir> $ mkdir -p build $ cd build $ cmake .. $ make -j4 s3,准备caffe模...

程序员深度学习 5124

ncnn的完整编译过程

1. 下载工程源码: 登录到https://github.com/Tencent/ncnn网址,登录后页面如下图所示: 2. 选择git clone或zip download方式下载源码。 3. 进入到ncnn源码根目录: $ cd <ncnn-root-dir> 4. 创建build文件夹: $ mkdir build 5. 进入到build...

phmatthaus的专栏 5984

【ncnn】将 caffemodel 转换为 NCNN 格式

1、编译win10版本的caffe 详细编译过程参考其他笔记 2、准备需要转换的caffemodel 通常来说,一个caffe模型有以下三个文件: train.prototxt 、deploy.prototxt 、alexnet.caffemodel,其中 train.prototxt 是用于训练的,在部署的时候,只需要 TEST 过程,所以只要有 deploy.prototxt 和caffemo...

zhaotun123的博客 1430
上一篇: virtualenv虚拟python环境
下一篇: python opencv minAreaRect 生成最小外接矩形
lien0906
博客等级 码龄15年 415粉丝 111原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值