pytorch_小黄人项目

六眼飞鱼酱① 提交于 2019-12-19 02:28:05

前提:实验使用10000个样本。

其中,下文:

  • 1.通道处理:用于将背景影像处理为通道相同的影像。
  • 2.查看通道分离效果:用于查看通道分离结果。
  • 3.创建数据:创建正负样本数据集。

1. 通道处理

from  PIL import Image
import os
"""通道处理"""
def  convertImage():
    listpath=os.listdir("data_image")
    print(listpath)
    for index,path in enumerate(listpath):
        img=Image.open(os.path.join("data_image",path))
        img=img.convert("RGB")#变换通道
        img=img.resize((224,224),Image.ANTIALIAS)#变换尺寸
        # img.show()
        img.save("images/{}.jpg".format(index))#保存


if __name__ == '__main__':
    convertImage()

2. 查看通道分离效果

from  PIL import Image
# 查看通道分离效果
img = Image.open("yellow/2.png")#原始影像(尺寸大小:128*128)
r, g, b, a = img.split()  # 分离原始影像通道
backgruond=Image.open("pic10013.jpg")#背景影像
backgruond=backgruond.resize((128,128))#变换背景影像尺寸与原始影像尺寸相同
r1,g1,b1=backgruond.split()#分离背景影像通道
imgnew = Image.merge("RGB", (r1, g1, b))  # 合并背景与原始影像通道
imgnew.show()

3. 创建数据

共10000张数据。其中,1-4000张做正样本;8000-9000张做正样本。

import numpy as np
from  PIL import Image
import os

def createDataset(dirimage):
    listpath=os.listdir(dirimage)
    for index,path in enumerate(listpath):
        img=Image.open(os.path.join(dirimage,path))
        #正样本
        if index <4000 or (index>8000 and index<9000):#小于两千or大于等于4000并且小于5000为“正样本”

            minions=Image.open("yellow/{}.png".format(np.random.randint(1,21)))#随机拿出1-20张小黄人影像中的一张影像
            """
            实验
            import numpy as np
            a=np.random.randint(1,21)
            print(a)
            """
            #缩放。
            h=w=np.random.randint(64,180)#原本大小128*128。随机给一个宽高
            minions=minions.resize((h,w),Image.ANTIALIAS)#缩放到随机宽高参数
            #旋转
            minions=minions.rotate(np.random.randint(-30,45))#旋转-30-45度之间的随机一个角度
            #翻转(翻转一部分影像)
            minions=minions.transpose(Image.FLIP_LEFT_RIGHT) if np.random.randint(0,2)==1 else minions #给一个0-2之间的随机数。当随机数等于1翻转,否则不翻转。

            #粘贴小黄人
            x,y=np.random.randint(0,224-w),np.random.randint(0,224-h)#随机给一个点去粘贴。点的x坐标范围为0到244减去小黄人的宽度之间;点的y坐标范围为0到244减去小黄人的高度之间。(背景影像尺寸:224*224)
            r,g,b,a=minions.split()
            img.paste(minions, (x,y),mask=a)#粘贴。掩码:用粘贴图片的背景修改小黄人
            print(x,y)
            if not os.path.isdir("dataset"):
                os.mkdir("dataset")
            img.save("dataset/{}.{}.{}.{}.{}.{}.jpg".format(index,x,y,x+w,y+h,1))#顺序:序号、坐标、大小、正样本(1表示)
         #负样本:直接不执行正样本内容,直接保存图片。
        else:
            img.save("dataset/{}.0.0.0.0.0.jpg".format(index))


if __name__ == '__main__':
    createDataset("images")

4. 数据集

共10000张数据。

  • 其中,前8000张做训练集;后2000张做验证集。
  • 保证训练集中(前8000张)有1-4000张为张样本,4000-8000张为负样本;验证集中(后2000张)有8000-9000张为正样本,9000-10000张为负样本。
import torch
from torch.utils.data import Dataset,DataLoader
import os
from  PIL  import Image
import numpy as np
import torchvision.transforms as trans

class MyDataset(Dataset):
    mean=[0.5371, 0.5178, 0.4985]
    std=[0.3075, 0.3010, 0.3107]
    def __init__(self, root=None, train=True, transforms=None):
        self.path=root
        self.listpath=os.listdir(self.path)
        self.listpath.sort(key=lambda x :int(x[:x.index(".")]))#排序
        self.transforms=transforms
        if train:
            self.listpath=self.listpath[:8000]#前8000张为训练集
        else:
            self.listpath=self.listpath[8000:10000]#测试集

    def __len__(self):
        return len(self.listpath)

    def __getitem__(self, index):
        imgpath=self.listpath[index]
        img=Image.open(os.path.join(self.path,imgpath))
        data=self.transforms(img)

        labels=imgpath.split(".")
        axis=np.array(labels[1:5],dtype=np.float32)/224#归一化
        category=np.array(labels[5:6],dtype=np.float32)#保证轴相同。labels[5]会不一样
        target=np.concatenate((axis,category))#拼接。前面四个做坐标损失,后面一个做是和否
        return data,target

if __name__ == '__main__':
    data=MyDataset(r"dataset",transforms=trans.Compose([trans.ToTensor(),trans.Normalize(MyDataset.mean,MyDataset.std)]))
    print(data[0])

    #查看数据
    # data = MyDataset(r"dataset",transforms=trans.Compose([trans.ToTensor()]))
    # print(len(data))
    # print(data[0])
    # print(data.listpath)

    #拼接
    # a=np.array([0.2,0.3,0.5,0.2])
    # b=np.array([1])
    # print(np.concatenate((a,b)))

    #求均值和方差
    # loader=DataLoader(dataset=data,batch_size=10000,shuffle=True)
    # data=next(iter(loader))[0]#loader:列表。包装为迭代器
    # mean=torch.mean(data,dim=(0,2,3))
    # std=torch.std(data,dim=(0,2,3))
    # print(mean,std)

5. 神经网络

一般,网络设计成“葫芦状”。入口建议小。

import torch.nn as nn
import torch

class MyNet(nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        self.cnn_layer=nn.Sequential(
            #先用两层小卷积代替大卷积卷原始图片
            nn.Conv2d(3,16,3,1),
            nn.ReLU(),
            nn.Conv2d(16,32,3,1),#特征图大小:(224-3+2*0)/1+1=222
            nn.ReLU(),
            nn.MaxPool2d(2,2),#特征图大小:(222-2+2*0)/2+1=111
            #接下来
            nn.Conv2d(32,64,3,1),#特征图大小:(111-3+2*0)/1+1=109
            nn.ReLU(),
            nn.MaxPool2d(2,2),#特征图大小:(109-2+2*0)/2+1=54
            nn.Conv2d(64,128,3,1),#特征图大小:(54-3+2*0)/1+1=52
            nn.ReLU(),
            nn.MaxPool2d(2,2),#特征图大小:(52-2+2*0)/2+1=26
            nn.Conv2d(128,256,3,1),#特征图大小:(26-3+2*0)/1+1=24
            nn.ReLU(),
            nn.AvgPool2d(2,2),#末尾加平均池化。#特征图大小:(24-2+2*0)/2+1=12
            nn.Conv2d(256,64,3,1),#特征图大小:(12-3+2*0)/1+1=10
            nn.ReLU()
        )

        self.mlp_layer=nn.Sequential(
            nn.Linear(10*10*64, 128),#接收WHC,输出128。
            nn.ReLU(),
            nn.Linear(128,5)
        )

    def forward(self,x):
        x=self.cnn_layer(x)
        x=x.reshape(-1,10*10*64)#变形
        x=self.mlp_layer(x)
        category=torch.sigmoid(x[:,0])#类别。第一个作类别分类。(120.34.41.134.141.1,与最后一个值比较类别。数值位置任意)
        axes=torch.relu(x[:,1:])#坐标。第一到结尾作坐标。

        return category, axes

6. 训练网络

6.1 测试结果显示说明

在这里插入图片描述

6.2 准确率说明

预测为正样本中真正是正样本的数目/预测为正样本的数目
在这里插入图片描述

准确率:

 TP = np.intersect1d(a, b).size  # 求交集(取出举例中的65个)
            print(TP)  # 求交集(举例中的65个)
            print(TP / AP)  # (举例中的65/70)

6.3召回率

预测为正样本中真正是正样本的数目/元数据中正样本的数目

print(TP/b)#召回率

6.4 代码:

import torch
from torch.utils.data import DataLoader
import  torch.nn as nn
import torchvision.transforms as trans
from PIL import Image,ImageDraw
import matplotlib.pyplot as plt
import numpy as np
from MyData import MyDataset
from MyNet import MyNet

class Trainer:
    def __init__(self):
        transforms=trans.Compose([
            trans.ToTensor(),
            trans.Normalize(MyDataset.mean,MyDataset.std)
        ])

        self.train_dataset=MyDataset(root=r"dataset",train=True,transforms=transforms)
        self.test_dataset=MyDataset(root=r"dataset",train=False,transforms=transforms)
        # self.net=MyNet()
        self.net = MyNet().cuda()
        self.offset_lossfunc=nn.MSELoss()#位置
        self.category_lossfunc=nn.BCELoss()#类别
        self.optimier=torch.optim.Adam((self.net.parameters()))

    def train(self):
        trainloader=DataLoader(dataset=self.train_dataset,batch_size=32,shuffle=True)#原则一批数据越多越好。保证一定量。
        losses=[]
        for i in range(20):
            print("epochs:{}".format(i))
            for j,(x,y) in enumerate(trainloader):
                if torch.cuda.is_available():
                    x=x.cuda()
                    y=y.cuda()
                category,axes=self.net(x)#类别和坐标。
                loss1=self.category_lossfunc(category,y[:,4])#类别做损失
                loss2=self.offset_lossfunc(axes,y[:,0:4])#坐标做损失
                loss=loss1+loss2

                if j%5==0:
                    losses.append(loss.float())
                    print("{}/{},loss:{}".format(j,len(trainloader),loss.float()))
                    plt.clf()
                    plt.plot(losses)
                    plt.pause(0.1)

                self.optimier.zero_grad()
                loss.backward()
                self.optimier.step()

        torch.save(self.net,"models/net.pth")


    #正确率
    def test(self):
        testloader=DataLoader(dataset=self.test_dataset,batch_size=32,shuffle=True)
        net=torch.load("models/net.pth")
        total=0
        for x,y in testloader:
            x,y=x.cuda(),y.cuda()
            category,axes=net(x)
            total += (category.round() == y[:, 4]).sum()  # 识别对的总张数。(输出的值进行四舍五入)
            del x,y,category,axes  # 清空变量。避免内存溢出。
        print("正确率",total)#GC

    # 做法1:取出预测为正样本的四个坐标
    def test1(self):
        testloader = DataLoader(dataset=self.test_dataset, batch_size=32, shuffle=True)
        net = torch.load("models/net.pth")
        total = 0
        for x, y in testloader:
            x, y = x.cuda(), y.cuda()
            category, axes = net(x)
            total += (category.round() == y[:, 4]).sum()
            for i , cate in enumerate(category):#类别的地址&内容
                if cate.round():
                    boex=axes[i]#第i个元素的四个坐标
                    print(boex)
                    return


    #做法2:取出预测为正样本的四个坐标和对应的测试数据的四个坐标。
    def test2(self):
        testloader = DataLoader(dataset=self.test_dataset, batch_size=32, shuffle=True)
        net = torch.load("models/net.pth")
        total = 0
        for x, y in testloader:
            x, y = x.cuda(), y.cuda()
            category, axes = net(x)
            total += (category.round() == y[:, 4]).sum()
            # print(category.round())
            index=category.round()==1#找出预测认为正样本的位置
            # print(index)#预测的正样本有正确、有错误
            # for i in axes[index]:#循环预测的所有为正样本的坐标
            for j,i in enumerate(axes[index ]):
                # print(i)
                # i.data.cpu().numpy()#取出数据(numpy格式)
                # print(i.data.cpu().numpy())
                boxes=(i.data.cpu().numpy()*224)#i.data.cpu().numpy():预测出来的坐标。*224:还原。
                target_box=y[index][j,0:4]*224#y[index]:预测为正样本的所有标签。y[index][j,0:4]:预测为正样本的所有标签情况下预测出来的坐标。
                print(boxes)
                print(target_box)
                return
                # target_box=y[index][j,0:4]*224#y[index]:
                # 一堆数据里,取出100张,预测认为80张是正的(它认为是正的的标签取出正的的boxes)。
                # 需要找到它认为是正的的boexs的标签。


    #做法3(图片形式显示)
    def test3(self):
        testloader = DataLoader(dataset=self.test_dataset, batch_size=32, shuffle=True)
        net = torch.load("models/net.pth")
        total = 0
        for x, y in testloader:
            x, y = x.cuda(), y.cuda()
            category, axes = net(x)
            total += (category.round() == y[:, 4]).sum()
            # print(category.round())
            index = category.round() == 1  # 找出正样本的位置
            target = y[index]  # 找出预测正确的标签
            # print(index)
            # for i in axes[index]:#循环预测的所有为正样本的坐标
            """
            原图形状(举例):n、3、224、224。目前形状:3
            还原数据需形状相同。
            1.将均值和方差变为tensor:
            mean=torch.tensor([0.5371, 0.5178, 0.4985])
            std=torch.tensor([0.3075, 0.3010, 0.3107])
            2.将正样本数据广播:
            reshape(-1,3,1,1)
            """
            # x = (x[index].cpu() * MyDataset.std.reshape(-1,3,1,1) + MyDataset.mean.reshape(-1,3,1,1)) * 255.  # 还原正样本的数据
            x = (x[index].cpu() * MyDataset.std.reshape(-1, 3, 1, 1) + MyDataset.mean.reshape(-1, 3, 1,1))   # 还原预测为正样本的数据。不用乘以255.。trans.ToPILImage("RGB"):自带乘以255.
            for j, i in enumerate(axes[index]):
                # print(i)
                # i.data.cpu().numpy()#取出数据(numpy格式)
                # print(i.data.cpu().numpy())
                boxes = (i.data.cpu().numpy() * 224)  # i.data.cpu().numpy():预测出来的坐标。*224:还原。
                target_box = target[j, 0:4] * 224
                # print(boxes)
                # print(target_box)
                # return

                img=trans.ToPILImage("RGB")(x[j])#显示预测为正样本对应的测试数
                # Image.fromarray()
                img.show()


    #做法4(画图显示)
    def test4(self):
        testloader = DataLoader(dataset=self.test_dataset, batch_size=32, shuffle=True)
        net = torch.load("models/net.pth")
        total = 0
        for x, y in testloader:
            x, y = x.cuda(), y.cuda()
            category, axes = net(x)
            total += (category.round() == y[:, 4]).sum()
            # print(category.round())
            index = category.round() == 1  # 找出正样本的位置
            target = y[index]  # 找出预测正确的标签
            # print(index)
            # for i in axes[index]:#循环预测的所有为正样本的坐标
            """
            原始数据:100,3,224,224。目前数据:3
            还原数据需形状相同。
            1.将均值和方差变为tensor:
            mean=torch.tensor([0.5371, 0.5178, 0.4985])
            std=torch.tensor([0.3075, 0.3010, 0.3107])
            2.将正样本数据广播:
            reshape(-1,3,1,1)
            """
            # x = (x[index].cpu() * MyDataset.std.reshape(-1,3,1,1) + MyDataset.mean.reshape(-1,3,1,1)) * 255.  # 还原正样本的数据
            x = (x[index].cpu() * MyDataset.std.reshape(-1, 3, 1, 1) + MyDataset.mean.reshape(-1, 3, 1,1))   # 还原正样本的数据。不用乘以255.。trans.ToPILImage("RGB"):自带乘以255.
            for j, i in enumerate(axes[index]):
                # print(i)
                # i.data.cpu().numpy()#取出数据(numpy格式)
                # print(i.data.cpu().numpy())
                boxes = (i.data.cpu().numpy() * 224)  # i.data.cpu().numpy():预测出来的坐标。*224:还原。
                target_box = target[j, 0:4] * 224
                # print(boxes)
                # print(target_box)
                # return

                img=trans.ToPILImage("RGB")(x[j])
                # Image.fromarray()
                plt.imshow(img)
                plt.show()


    #做法5(画图显示(画出框))
    def test5(self):
        testloader = DataLoader(dataset=self.test_dataset, batch_size=32, shuffle=True)
        net = torch.load("models/net.pth")
        total = 0
        for x, y in testloader:
            x, y = x.cuda(), y.cuda()
            category, axes = net(x)
            total += (category.round() == y[:, 4]).sum()
            # print(category.round())
            index = category.round() == 1  # 找出正样本的位置
            target = y[index]  # 找出预测正确的标签
            # print(index)
            # for i in axes[index]:#循环预测的所有为正样本的坐标
            """
            原始数据:100,3,224,224。目前数据:3
            还原数据需形状相同。
            1.将均值和方差变为tensor:
            mean=torch.tensor([0.5371, 0.5178, 0.4985])
            std=torch.tensor([0.3075, 0.3010, 0.3107])
            2.将正样本数据广播:
            reshape(-1,3,1,1)
            """
            # x = (x[index].cpu() * MyDataset.std.reshape(-1,3,1,1) + MyDataset.mean.reshape(-1,3,1,1)) * 255.  # 还原正样本的数据
            x = (x[index].cpu() * MyDataset.std.reshape(-1, 3, 1, 1) + MyDataset.mean.reshape(-1, 3, 1,1))   # 还原正样本的数据。不用乘以255.。trans.ToPILImage("RGB"):自带乘以255.
            for j, i in enumerate(axes[index]):
                # print(i)
                # i.data.cpu().numpy()#取出数据(numpy格式)
                # print(i.data.cpu().numpy())
                boxes = (i.data.cpu().numpy() * 224).astype(np.int32)  # i.data.cpu().numpy():预测出来的坐标。*224:还原。并转整型。
                # print(boxes)
                # return
                target_box = (target[j, 0:4].data.cpu().numpy() * 224).astype(np.int32)#转整型。
                # print(boxes)
                # print(target_box)
                # return

                img=trans.ToPILImage("RGB")(x[j])
                # Image.fromarray()
                plt.clf()
                plt.axis("off")
                draw=ImageDraw.Draw(img)
                draw.rectangle(boxes.tolist(),outline="red")
                # print(boxes.shape)
                # print(target_box.shape)
                # print(boxes)
                # print(target_box)
                # return
                draw.rectangle(target_box.tolist(), outline="yellow")#tolist():因为不支持numpy,只支持简单的python类型
                plt.imshow(img)
                plt.pause(1)
                plt.show()

            del x,y,category,axes,index,target,boxes,target_box,img,draw



    #准确率
    def test6(self):
        testloader = DataLoader(dataset=self.test_dataset, batch_size=32, shuffle=True)
        net = torch.load("models/net.pth")
        total = 0
        for x, y in testloader:
            x, y = x.cuda(), y.cuda()
            category, axes = net(x)
            index = category.round() == 1
            target = y[index]

            AP = category.round().sum()  # 预测为的正样本数(举例中的70个)
            print(category.round())
            # return
            a = torch.nonzero(category.round()).flatten().data.cpu().numpy()  # 找出预测正确的非零元素(即,等于1)的索引。(举例中的65个)
            b = torch.nonzero(y[:, 4]).flatten().data.cpu().numpy() # 找出原数据标签中正样本的索引
            print(a)
            print(b)
            print(a.size, b.size)
            # return
            TP = np.intersect1d(a, b).size  # 求交集(取出举例中的65个)
            print(TP)  # 求交集(举例中的65个)
            print(TP / AP)  # (举例中的65/70)


            del x, y, category, axes, index, target
        print("正确率", total)


    #召回率
    def test7(self):
        testloader = DataLoader(dataset=self.test_dataset, batch_size=32, shuffle=True)
        net = torch.load("models/net.pth")
        total = 0
        for x, y in testloader:
            x, y = x.cuda(), y.cuda()
            category, axes = net(x)
            index = category.round() == 1
            target = y[index]

            AP = category.round().sum()  # 预测为的正样本数(举例中的70个)
            print(AP)
            # print(category.round())
            # return
            a = torch.nonzero(category.round()).flatten().data.cpu().numpy()  # 找出预测正确的非零元素(即,等于1)的索引。(举例中的65个)
            b = torch.nonzero(y[:, 4]).flatten().data.cpu().numpy() # 找出原数据标签中正样本的索引
            print(a)
            print(b)
            # print(a.size, b.size)
            # return
            TP = np.intersect1d(a, b).size  # 求交集(取出举例中的65个)
            print(TP)  # 求交集(举例中的65个)
            print(TP / AP)  # (举例中的65/70)准确率
            print(TP/b)#召回率
            del x, y, category, axes, index, target
        print("正确率", total)


if __name__ == '__main__':
    train=Trainer()
    # train.train()
    # train.test1()
    # train.test2()
    # train.test3()
    # train.test4()
    # train.test5()
    # train.test6()
    train.test7()

6.5 测试结果展示

(1)正确率

正确率 tensor(1997, device='cuda:0')

(2)做法1:取出预测为正样本的四个坐标。

tensor([0.0863, 0.1701, 0.8625, 0.9645], device='cuda:0',
       grad_fn=<SelectBackward>)

(3)做法2:取出预测为正样本的四个坐标和对应的测试数据的四个坐标。

[ 38.395405  46.357677 188.06209  195.22275 ]
tensor([ 40.,  38., 215., 213.], device='cuda:0')

(4)做法3(图片形式显示)

图片显示预测出正样本对应的测试数据:

在这里插入图片描述

(5)做法4(画图显示(未画出框))

其中,重要的一个代码:

draw.rectangle(target_box.tolist(), outline="yellow")#tolist():因为不支持numpy,只支持简单的python类型

在这里插入图片描述

(6)做法5(画图显示(画出框))

在这里插入图片描述

7. 数据标注

7.1 标注软件

精灵标注助手: http://www.jinglingbiaozhu.com/

7.2 使用方法

  • 选择标注项目:在【首页】选择要标注的项目类型;(本例选择【机器视觉项目】)
  • 新建项目:在【首页】单击【新建】按钮;
  • 选择标注类型:在弹出的【新建项目】对话框中子对话框选择标注类型;(本例选择位置标注)
  • 项目名称设置:【图片文件夹】:选择要标注图片的文件夹;【分类值】:写入分类的项目名称。如:单个物体:小黄人;多个物体:汽车、人、野马…;
  • 开始标注:在弹出的【位置标注】对话框左侧选择要进行标注的形状元素,鼠标变为“十字架”形式,开始进行标注。每标注一张图片时,在【位置标注】对话框右侧【标注信息】中选择物体名称;
  • 标注:点击【位置标注】对话框左侧【后一个】进行下一个图片;
  • 保存结果:“ctrl+s”保存结果;
  • 导出结果:点击【位置标注】对话框左侧【导出】,选择【输出方式】,本例选择【JSON】,选择【保存位置】。将结果导出。

7.3 JSON说明

  • 查看标注结果:打开导出文件夹位置,以记事本形式打开JSON格式文件。结果如下:
{"path":"D:\\AI_clb\\code\\20191210_小黄人项目讲解\\dataset\\1004.10.47.178.215.1.jpg","outputs":{"object":[{"name":"小黄人","bndbox":{"xmin":23,"ymin":58,"xmax":173,"ymax":205}}]},"time_labeled":1576634927095,"labeled":true,"size":{"width":224,"height":224,"depth":3}}
  • 校验JSON格式文件:在网上搜索校验工具,网址: http://www.bejson.com/ 或者:https://tool.oschina.net/codeformat/json
  • 将输出的JSON格式文件内容放入上述网站的检验器,点击【格式化校验】,结果如下:
    在这里插入图片描述

说明:JSON格式就是字典格式。

7.4 XML格式

  • 将【输出方式】选为【xml】;
  • 用PyCharm 打开:
<?xml version="1.0" ?>
<doc>
	<path>D:\AI_clb\code\20191210_小黄人项目讲解\dataset\1004.10.47.178.215.1.jpg</path>
	<outputs>
		<object>
			<item>
				<name>小黄人</name>
				<bndbox>
					<xmin>23</xmin>
					<ymin>58</ymin>
					<xmax>173</xmax>
					<ymax>205</ymax>
				</bndbox>
			</item>
		</object>
	</outputs>
	<time_labeled>1576634927095</time_labeled>
	<labeled>true</labeled>
	<size>
		<width>224</width>
		<height>224</height>
		<depth>3</depth>
	</size>
</doc>
  • 用读写XML格式校验工具进行校验。

7.5 MongoDB格式

是一种缓存数据库,可存到内存中。

8. 附加

准确率(Accuracy)、精确率(Precision)、 召回率(Recall)、 F值(F-Measure)、 AUC(Area under Curve )、ROC(receiver operating characteristic ): https://blog.csdn.net/u011630575/article/details/80250177

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!