基于python脚本的将mmd模型快速改造为c4d模型的一种方法

在这里就不详细说了,详细使用请看视频:
https://www.bilibili.com/video/BV1zh4y1w7kQ

因为不同的mmd模型作者往往不会使用相同的骨骼层级结构,所以mmd模型就很难去用通用的脚本去进行自动化改造
所以在使用过程中会不可避免的出现错误

改造效果:

在这里插入图片描述
在这里插入图片描述

代码如下:

import c4d
# region


def Process_Node(layer, obj, func):

    chlidren_list = obj.GetChildren()

    layer_current = []

    for str in layer:
        layer_current.append(str)

    layer_current.append(obj.GetName())
    pass

    func(obj, layer_current)

    pass

    for child in chlidren_list:
        Process_Node(layer_current, child, func)


def Package_Other(obj_name, ex_list, proc_times):
    pass
    par_obj = doc.SearchObject(obj_name)
    if par_obj is None:
        return

    child_tmp = par_obj.GetChildren()

    # 阻止重复打包
    for child in child_tmp:
        if child.GetName().find("other") != -1:
            return

    new_null_obj = c4d.BaseObject(c4d.Onull)

    doc.InsertObject(new_null_obj)

    new_null_obj.InsertUnder(par_obj)
    new_null_obj.SetName("other"+str(proc_times))

    c4d.EventAdd()

    for child in child_tmp:
        if child.GetName() in ex_list:
            continue
        child.InsertUnder(new_null_obj)
    print("package:", obj_name, ex_list)
    c4d.EventAdd()


def Get_Child_By_Name(obj, child_name):
    pass
    c_list = obj.GetChildren()
    for c in c_list:
        if c.GetName() == child_name:
            return c


def Delete(name):
    bone = doc.SearchObject(name)
    bone.Remove()
    c4d.EventAdd()


def Delete_And_Move_Children(name):

    bone = doc.SearchObject(name)

    if bone is None:
        return

    children_list = bone.GetChildren()
    parent_obj = bone.GetUp()

    for child in children_list:

        pos = child.GetMg()
        child.InsertUnderLast(parent_obj)
        child.SetMg(pos)

    bone.Remove()
    c4d.EventAdd()


def Insert_With_Position(obj, par_obj):
    pass
    pos = obj.GetMg()
    obj.InsertUnderLast(par_obj)
    obj.SetMg(pos)


def Re_Name(obj_name, new_name):
    pass
    # M_左手首
    obj = doc.SearchObject(obj_name)
    obj.SetName(new_name)


def Add_Control_Obj(obj_name, ctl_name, ctl_par_name):
    pass
    obj = doc.SearchObject(obj_name)

    if obj is None:
        return

    ctl_obj = None

# 检查创建控制器
    if obj.GetUp().GetName() != ctl_name:
        pass
        ctl_obj = c4d.BaseObject(c4d.Onull)
        doc.InsertObject(ctl_obj)
        ctl_obj.SetName(ctl_name)

        pos = obj.GetMg()
        ctl_obj.SetMg(pos)
        Insert_With_Position(obj, ctl_obj)
    else:
        pass
        ctl_obj = doc.SearchObject(ctl_name)
# 控制器位置

    ctl_par = doc.SearchObject(ctl_par_name)

    if not ctl_obj.GetUp() is None:
        pass
        if ctl_obj.GetUp().GetName() != ctl_par_name:
            Insert_With_Position(ctl_obj, ctl_par)
    else:
        Insert_With_Position(ctl_obj, ctl_par)
    c4d.EventAdd()


def Add_Control_Obj_Std_Rou(obj_name, ctl_name, ctl_par_name):
    pass
    obj = doc.SearchObject(obj_name)

    if obj is None:
        return

    ctl_obj = None

# 检查创建控制器
    if obj.GetUp().GetName() != ctl_name:
        pass
        ctl_obj = c4d.BaseObject(c4d.Onull)
        doc.InsertObject(ctl_obj)
        ctl_obj.SetName(ctl_name)

        pos = obj.GetMg()
        ctl_obj.SetMg(pos)
        ctl_obj.SetAbsRot((0, 0, 0))
        Insert_With_Position(obj, ctl_obj)
    else:
        pass
        ctl_obj = doc.SearchObject(ctl_name)
# 控制器位置

    ctl_par = doc.SearchObject(ctl_par_name)

    if not ctl_obj.GetUp() is None:
        pass
        if ctl_obj.GetUp().GetName() != ctl_par_name:
            Insert_With_Position(ctl_obj, ctl_par)
    else:
        Insert_With_Position(ctl_obj, ctl_par)
    c4d.EventAdd()


def Set_IK_Tag(ik_root_name, ik_end_name, ik_target_name, handle_offset_v3):
    pass
    ik_root = doc.SearchObject(ik_root_name)
    ik_end = doc.SearchObject(ik_end_name)
    ik_target = doc.SearchObject(ik_target_name)

    ik_tag = ik_root.MakeTag(1019561)  # IK标签
    ik_tag[c4d.ID_CA_IK_TAG_TIP] = ik_end
    ik_tag[c4d.ID_CA_IK_TAG_TARGET] = ik_target

    handle = c4d.BaseObject(c4d.Onull)
    doc.InsertObject(handle)
    handle.SetName(ik_root.GetName()+"旋转手柄")
    handle.InsertAfter(ik_root)

    pos = ik_root.GetAbsPos()
    print(pos)
    print(ik_root.GetRelPos())
    handle.SetAbsPos(pos+handle_offset_v3)
    ik_tag[c4d.ID_CA_IK_TAG_POLE] = handle

    handle[c4d.ID_BASEOBJECT_USECOLOR] = 2
    handle[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1, 1, 1)
    handle[c4d.NULLOBJECT_DISPLAY] = 11
    handle[c4d.NULLOBJECT_RADIUS] = 20
    handle[c4d.NULLOBJECT_ORIENTATION] = 3


def Set_Control_Type(obj_name, v3, type, radius, dir_type):
    pass
    obj = doc.SearchObject(obj_name)

    if obj is None:
        return

    obj[c4d.ID_BASEOBJECT_USECOLOR] = 2
    obj[c4d.ID_BASEOBJECT_COLOR] = v3
    obj[c4d.NULLOBJECT_DISPLAY] = type
    obj[c4d.NULLOBJECT_RADIUS] = radius
    obj[c4d.NULLOBJECT_ORIENTATION] = dir_type
    c4d.EventAdd()


def Set_IK_Control(obj_name, IK_Ctl_name, root_name, v3, type, radius, dir_type):
    pass
    obj = doc.SearchObject(obj_name)
    root_obj = doc.SearchObject(root_name)
    if obj is None:
        return

    IK_Ctl = c4d.BaseObject(c4d.Onull)
    doc.InsertObject(IK_Ctl)
    IK_Ctl.SetName(IK_Ctl_name)
    IK_Ctl.InsertUnder(root_obj)

    pos = obj.GetMg()
    IK_Ctl.SetMg(pos)

    IK_Ctl[c4d.ID_BASEOBJECT_USECOLOR] = 2
    IK_Ctl[c4d.ID_BASEOBJECT_COLOR] = v3
    IK_Ctl[c4d.NULLOBJECT_DISPLAY] = type
    IK_Ctl[c4d.NULLOBJECT_RADIUS] = radius
    IK_Ctl[c4d.NULLOBJECT_ORIENTATION] = dir_type
    c4d.EventAdd()


def Set_Bind_Tag_Rou(obj_name, bind_name):
    pass
    obj = doc.SearchObject(obj_name)
    bind = doc.SearchObject(bind_name)
    tag = obj.MakeTag(1019364)  # 绑定

    tag[c4d.ID_CA_CONSTRAINT_TAG_PSR] = 1
    tag[10005] = 0
    tag[10001] = bind


def Set_Bone_Type(obj_name, joint_type, radius):
    pass
    obj = doc.SearchObject(obj_name)
    obj[c4d.ID_CA_JOINT_OBJECT_JOINT_SIZE_MODE] = 0
    obj[c4d.ID_CA_JOINT_OBJECT_JOINT_DISPLAY] = joint_type
    obj[c4d.ID_CA_JOINT_OBJECT_JOINT_SIZE] = radius
    c4d.EventAdd()

# endregion


# -----------------------名称标准化------------------------------D
root_name = doc.GetFirstObject().GetName()
Re_Name(root_name, "root")

# 一些mmd模型的骨骼名称不带字母“D”
try:
    pass
    Re_Name("右足", "右足D")
    Re_Name("右ひざ", "右ひざD")
    Re_Name("右足首", "右足首D")

    Re_Name("左足", "左足D")
    Re_Name("左ひざ", "左ひざD")
    Re_Name("左足首", "左足首D")

except:
    pass

# ---------------------------------------------------------------
bone_root_obj = doc.SearchObject("全ての親")

# -----------------------名称唯一化-----------------------
# region
Name_List = []


def Rename_Repeated_Name(obj, layer_current):
    pass
    name_tmp = obj.GetName()
    changed = False
    while True:
        if name_tmp in Name_List:
            name_tmp = name_tmp+"_"
            changed = True
            continue
        break
    if changed:
        print(obj.GetName(), "--->", name_tmp)

    obj.SetName(name_tmp)
    Name_List.append(name_tmp)


Process_Node([], bone_root_obj, Rename_Repeated_Name)
# endregion
# ----------------------- 删除无子级无权重的对象-----------------------
# region


class Node_With_Weight:

    def __init__(self, name, obj_ref, bone_root_obj):
        pass
        self.obj_ref = obj_ref
        self.bone_root_obj = bone_root_obj
        self.name = name

        self.parent_List = []

        node_tmp = obj_ref
        while True:

            self.parent_List.append(node_tmp.GetName())

            if node_tmp.GetName() != bone_root_obj.GetName():
                pass
            else:
                self.parent_List.reverse()
                break

            node_tmp = node_tmp.GetUp()

    # 更新路径信息
    def Path_Update(self):
        pass

        self.parent_List = []

        node_tmp = self.obj_ref
        while True:

            self.parent_List.append(node_tmp.GetName())
            if node_tmp.GetName() != bone_root_obj.GetName():
                pass
            else:
                self.parent_List.reverse()
                break

            node_tmp = node_tmp.GetUp()


# 判断给定的路径是否是带有权重的对象的路径
def Is_Path_Has_Weight(list):
    pass
    for node in Obj_Name_With_Weight:
        if node.parent_List == list:
            return True
    return False


Obj_Name_With_Weight = []

mesh_obj = doc.SearchObject("Mesh")
weight_tag = mesh_obj.GetTag(c4d.Tweights)
joint_count = weight_tag.GetJointCount()

# 获取所有带有权重的骨骼的名称
for i in range(joint_count):

    node = Node_With_Weight(weight_tag.GetJoint(
        i).GetName(), weight_tag.GetJoint(i), bone_root_obj)
    Obj_Name_With_Weight.append(node)


obj_ready_for_delete_list = []


def Delete_Obj_With_No_Children_No_Weight(obj, layer_current):
    pass
    children_list = obj.GetChildren()
    if (not Is_Path_Has_Weight(layer_current)) and len(children_list) == 0:
        obj_ready_for_delete_list.append(obj)
        # print(obj.GetName())


while True:
    pass
    obj_ready_for_delete_list = []

    Process_Node([], bone_root_obj, Delete_Obj_With_No_Children_No_Weight)

    for obj in obj_ready_for_delete_list:
        obj.Remove()

    if len(obj_ready_for_delete_list) == 0:
        break
c4d.EventAdd()
# endregion

# -------------------------删除所有保护,IK,绑定标签---------------------------
# region


def Delete_Protection_Tag(obj, layer_current):
    pass
    obj.KillTag(c4d.Tprotection)
    try:
        obj.KillTag(1019561)
    except:
        pass
    try:
        obj.KillTag(1019364)
    except:
        pass


Process_Node([], bone_root_obj, Delete_Protection_Tag)
c4d.EventAdd()
# endregion
# --------------------------打包组件骨骼---------------------------------
proc_times = 0
Package_Other("下半身", ["右足", "左足"], proc_times)
proc_times = proc_times+1
Package_Other("上半身2", ["右肩", "左肩", "首"], proc_times)
proc_times = proc_times+1
Package_Other("頭", [], proc_times)
# --------------------------转换Tpose----------------------------------
doc.SearchObject("右腕")[c4d.ID_BASEOBJECT_REL_ROTATION, c4d.VECTOR_Z] = 0.611
doc.SearchObject("左腕")[c4d.ID_BASEOBJECT_REL_ROTATION, c4d.VECTOR_Z] = -0.611
# --------------------------删除无用对象-------------------------------------
Delete_And_Move_Children("全ての親")
Delete_And_Move_Children("センター")
Delete_And_Move_Children("グルーブ")
Delete_And_Move_Children("腰")
Delete_And_Move_Children("左肩P")
Delete_And_Move_Children("右肩P")
Delete_And_Move_Children("腰キャンセル右")
Delete_And_Move_Children("腰キャンセル左")
# ---------------------------加入控制器------------------------------------

Add_Control_Obj("上半身", "M_上半身", "root")
Add_Control_Obj("上半身2", "M_上半身_2", "M_上半身")
Add_Control_Obj("首", "M_首", "M_上半身_2")
Add_Control_Obj("頭", "M_首_2", "M_首")

Add_Control_Obj_Std_Rou("左肩", "M_左肩", "M_上半身_2")
Add_Control_Obj_Std_Rou("左肩", "M_左肩_2", "M_左肩")

Add_Control_Obj_Std_Rou("右肩", "M_右肩", "M_上半身_2")
Add_Control_Obj_Std_Rou("右肩", "M_右肩_2", "M_右肩")

Add_Control_Obj_Std_Rou("左腕", "M_L_0", "M_左肩_2")
Add_Control_Obj_Std_Rou("左ひじ", "M_L_1", "M_L_0")
Add_Control_Obj_Std_Rou("左手首", "M_L_2", "M_L_1")
Add_Control_Obj_Std_Rou("左手首", "M_左手首", "M_L_2")


Add_Control_Obj_Std_Rou("右腕", "M_R_0", "M_右肩_2")
Add_Control_Obj_Std_Rou("右ひじ", "M_R_1", "M_R_0")
Add_Control_Obj_Std_Rou("右手首", "M_R_2", "M_R_1")
Add_Control_Obj_Std_Rou("右手首", "M_右手首", "M_R_2")

Add_Control_Obj("下半身", "M_下半身", "root")
Add_Control_Obj("下半身", "M_下半身_2", "M_下半身")

Insert_With_Position(doc.SearchObject("右足D"), doc.SearchObject("M_下半身_2"))
Insert_With_Position(doc.SearchObject("左足D"), doc.SearchObject("M_下半身_2"))
c4d.EventAdd()
# -------------------------重命名----------------------------------
Re_Name("右足D", "M_右足D")
Re_Name("右ひざD", "M_右足D2")
Re_Name("右足首D", "M_右足首D")

Re_Name("左足D", "M_左足D")
Re_Name("左ひざD", "M_左足D2")
Re_Name("左足首D", "M_左足首D")

Re_Name("左手首", "M_左手首_2")
Re_Name("右手首", "M_右手首_2")


old_name_list_X = ["小指1", "小指2", "小指3"]
new_name_list_X = ["小指1", "小指2", "小指3"]
for id in range(0, 3):
    Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
    Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])

old_name_list_X = ["薬指1", "薬指2", "薬指3"]
new_name_list_X = ["无名指1", "无名指2", "无名指3"]
for id in range(0, 3):
    Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
    Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])

old_name_list_X = ["中指1", "中指2", "中指3"]
new_name_list_X = ["中指1", "中指2", "中指3"]
for id in range(0, 3):
    Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
    Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])

old_name_list_X = ["人指1", "人指2", "人指3"]
new_name_list_X = ["人指1", "人指2", "人指3"]
for id in range(0, 3):
    Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
    Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])

old_name_list_X = ["親指0", "親指1", "親指2"]
new_name_list_X = ["大拇指0", "大拇指1", "大拇指2"]
for id in range(0, 3):
    Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
    Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])

Set_Bone_Type("M_左大拇指0", 2, 10)
Set_Bone_Type("M_左无名指1", 2, 10)
Set_Bone_Type("M_左中指1", 2, 10)
Set_Bone_Type("M_左小指1", 2, 10)
Set_Bone_Type("M_左人指1", 2, 10)

Set_Bone_Type("M_右大拇指0", 2, 10)
Set_Bone_Type("M_右无名指1", 2, 10)
Set_Bone_Type("M_右中指1", 2, 10)
Set_Bone_Type("M_右小指1", 2, 10)
Set_Bone_Type("M_右人指1", 2, 10)


c4d.EventAdd()
# ----------------------------------控制器样式----------------------------
Set_Control_Type("M_上半身", c4d.Vector(1, 0, 0), 2, 140, 3)
Set_Control_Type("M_首", c4d.Vector(1, 0, 0), 2, 150, 3)

Set_Control_Type("M_左肩", c4d.Vector(0, 1, 0), 13, 70, 3)
Set_Control_Type("M_右肩", c4d.Vector(0, 0, 1), 13, 70, 3)

Set_Control_Type("M_下半身", c4d.Vector(0, 0, 1), 8, 96, 3)

# ---------------------------------IK控制器------------------------------

Set_IK_Control("M_R_2", "右手IK", "root", c4d.Vector(1, 1, 1), 11, 50, 3)
Set_IK_Control("M_L_2", "左手IK", "root", c4d.Vector(1, 1, 1), 11, 50, 3)

Set_IK_Control("M_右足首D", "右足IK", "root", c4d.Vector(1, 1, 1), 11, 50, 3)
Set_IK_Control("M_左足首D", "左足IK", "root", c4d.Vector(1, 1, 1), 11, 50, 3)

Set_IK_Tag("M_右足D", "M_右足首D", "右足IK", c4d.Vector(0, -184, -488))
Set_IK_Tag("M_左足D", "M_左足首D", "左足IK", c4d.Vector(0, -184, -488))

Set_IK_Tag("M_R_0", "M_R_2", "右手IK", c4d.Vector(0, 0, 270))
Set_IK_Tag("M_L_0", "M_L_2", "左手IK", c4d.Vector(0, 0, 270))


# ------------------------------绑定----------------------
Set_Bind_Tag_Rou("M_右足首D", "右足IK")
Set_Bind_Tag_Rou("M_左足首D", "左足IK")

Set_Bind_Tag_Rou("M_左手首", "左手IK")
Set_Bind_Tag_Rou("M_右手首", "右手IK")


c4d.EventAdd()
# -----------------------重心对象-----------------------
weight_c_obj = c4d.BaseObject(c4d.Onull)
doc.InsertObject(weight_c_obj)
weight_c_obj.InsertUnder(doc.SearchObject("root"))
weight_c_obj.SetName("M_重心")

obj_M_dhb = doc.SearchObject("M_下半身")
weight_c_obj.SetMg(obj_M_dhb.GetMg())
Set_Control_Type("M_重心", c4d.Vector(1, 0, 0), 3, 450, 3)

Insert_With_Position(doc.SearchObject("M_上半身"), weight_c_obj)
Insert_With_Position(doc.SearchObject("M_下半身"), weight_c_obj)
# -----------------------中心对象-----------------------
c_obj = c4d.BaseObject(c4d.Onull)
doc.InsertObject(c_obj)
c_obj.InsertUnder(doc.SearchObject("root"))
c_obj.SetName("M_中心")

c_obj.SetMg(obj_M_dhb.GetMg())
Set_Control_Type("M_中心", c4d.Vector(0, 0, 1), 11, 108, 2)
c_obj[c4d.NULLOBJECT_ASPECTRATIO] = 1.5
Insert_With_Position(weight_c_obj, c_obj)

Insert_With_Position(doc.SearchObject("左足IK"), c_obj)
Insert_With_Position(doc.SearchObject("右足IK"), c_obj)
Insert_With_Position(doc.SearchObject("左手IK"), c_obj)
Insert_With_Position(doc.SearchObject("右手IK"), c_obj)

Insert_With_Position(doc.SearchObject("M_右足D旋转手柄"), doc.SearchObject("M_中心"))
Insert_With_Position(doc.SearchObject("M_左足D旋转手柄"), doc.SearchObject("M_中心"))

Insert_With_Position(doc.SearchObject("M_L_0旋转手柄"), doc.SearchObject("M_中心"))
Insert_With_Position(doc.SearchObject("M_R_0旋转手柄"), doc.SearchObject("M_中心"))
c4d.EventAdd()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是基于Python的使用MMD损失函数训练DCNN模型代码: 首先,我们需要导入需要的库,包括tensorflow、numpy、sklearn等: ```python import tensorflow as tf import numpy as np from sklearn.model_selection import train_test_split from sklearn.metrics import confusion_matrix ``` 然后,我们需要定义一些超参数,包括学习率、迭代次数、批次大小等: ```python learning_rate = 0.001 num_epochs = 100 batch_size = 128 ``` 接着,我们需要读取数据集。这里我们使用CWRU的0HP文件夹数据集,该数据集包含10个类别的轴承故障数据。我们将数据集分为训练集和测试集,并且将数据进行标准化处理: ```python # 读取数据集 data = np.load('0HP.npy') labels = np.load('0HP_labels.npy') # 将数据集分为训练集和测试集 train_data, test_data, train_labels, test_labels = train_test_split(data, labels, test_size=0.2) # 对数据进行标准化处理 mean = np.mean(train_data, axis=0) std = np.std(train_data, axis=0) train_data = (train_data - mean) / std test_data = (test_data - mean) / std ``` 接下来,我们需要构建DCNN模型。这里我们使用包含3个卷积层和2个全连接层的模型。我们将MMD损失函数定义为模型的一部分,并且使用Adam优化器进行训练: ```python # 定义MMD损失函数 def mmd_loss(source_features, target_features): source_mean = tf.reduce_mean(source_features, axis=0) target_mean = tf.reduce_mean(target_features, axis=0) source_cov = tf.matmul(tf.transpose(source_features - source_mean), source_features - source_mean) target_cov = tf.matmul(tf.transpose(target_features - target_mean), target_features - target_mean) return tf.reduce_sum(tf.square(source_cov - target_cov)) # 定义DCNN模型 def dcnn_model(input_shape, num_classes): model = tf.keras.Sequential([ tf.keras.layers.Conv1D(32, 5, activation='relu', input_shape=input_shape), tf.keras.layers.MaxPooling1D(2), tf.keras.layers.Conv1D(64, 5, activation='relu'), tf.keras.layers.MaxPooling1D(2), tf.keras.layers.Conv1D(128, 5, activation='relu'), tf.keras.layers.Flatten(), tf.keras.layers.Dense(256, activation='relu'), tf.keras.layers.Dense(num_classes, activation='softmax') ]) return model # 构建模型 input_shape = train_data[0].shape num_classes = len(np.unique(train_labels)) model = dcnn_model(input_shape, num_classes) # 将MMD损失函数添加到模型中 source_features = model(train_data) target_features = model(test_data) mmd_loss_value = mmd_loss(source_features, target_features) model.add_loss(mmd_loss_value) # 编译模型 model.compile(optimizer=tf.keras.optimizers.Adam(lr=learning_rate), loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(train_data, train_labels, epochs=num_epochs, batch_size=batch_size, validation_data=(test_data, test_labels)) ``` 最后,我们可以使用训练好的模型对测试集进行预测,并且计算混淆矩阵和分类准确率: ```python # 对测试集进行预测 predictions = model.predict(test_data) predicted_labels = np.argmax(predictions, axis=1) # 计算混淆矩阵和分类准确率 cm = confusion_matrix(test_labels, predicted_labels) accuracy = np.trace(cm) / np.sum(cm) print('Confusion matrix:\n', cm) print('Classification accuracy:', accuracy) ``` 希望这份代码能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值