使用 Mask RCNN 和 Yolov5 进行划痕检测

人工智能等各类编程培训资料整理,所有资源无秘无压缩-购买会员

介绍

本文的重点是检测汽车划痕,与针对不同类型产品的自主质量检测系统的开发同步。在停车场,这种检测为客户提供了他们的汽车安全的保证;此外,如果发生某些事情,检测系统将有助于对这种情况进行谨慎处理。

我将这个问题作为一个单类分类问题来解决,将凹痕、损坏和划痕视为划痕,并进一步在 Flask 的帮助下制作了一个基本应用程序。我将向你介绍我在做这个项目时获得的所有想法、代码、算法和知识,我将通过Mask RCNN和Yolov5实现这个项目。

使用 Yolv5 进行预测

这是模型的最终结果。

学习目标

了解如何使用Mask RCNN和Yolov5 执行 自定义对象检测。在使用在 coco 数据集和 Resnet50 上训练的模型时利用迁移学习。了解质量数据收集和数据注释的重要性是任何项目中不可或缺且最耗时的部分。目录

收集数据集

使用 Mask RCNN 进行实例分割

2.1 导入库

2.2 划分数据集

2.3 创建一个 Scratch 类

2.4 数据增强

2.5 创建模型

2.6 训练模型

通过 Yolov5 进行目标检测

3.1 数据标注

3.2 训练

3.3 结果

结论和要点

收集数据集

为了收集数据,我制作了一个数据抓取器,使用 Beautiful Soup 从adobe、Istock photo等在线网站抓取数据。

url=https://stock.adobe.com/in/search/images?k=car%20scratch

#makearequesttotheurl

r=requests.get(url)

#createoursoup

soup=BeautifulSoup(r.text,html.parser)

print(soup.title.text)

images=soup.find_all(img)

forimageinimages[-1]:

name=image[alt]

link=image[src]

withopen(name.replace(,-).replace(/,)+.jpg,wb)asf:

im=requests.get(link)

f.write(im.content)

由于网站关于抓取的隐私政策,大部分图像都没有被抓取。由于隐私问题,我直接从 Istock photo、Shutter photo 和 Adobe 下载了图像。

我从大约 80 张图像开始,增加到 350 张图像,并进一步增加到大约 900 张图像以进行最终注释。

使用 Mask RCNN 进行实例分割

图像分割是基于像素将图像分割成不同的区域。Mask RCNN 是一种用于实例分割的模型,它是图像分割的一种子类型,可在对象边界中分离实例。它是在 Faster RCNN 的基础上进一步构建的。Faster RCNN 对每个对象都有两个输出,分别是类标签和边界框偏移,Mask RCNN 是第三个输出的附加,即对象的掩码。

Mask RCNN 架构

Mask RCNN 的架构由以下部分组成:

骨干网络区域提案网络掩码表示感兴趣区域RoI

使用 Mask RCNN 检测汽车划痕的优势在于,我们可以使用多边形而不仅仅是边界框,并在我们的目标上创建一个掩码,使我们能够以更准确和简洁的方式获得和可视化结果。

让我们开始使用 Mask RCNN 来实现我们的问题。

导入库

导入实施我们的 Mask RCNN 算法所需的所有库。

#importinglibraries

importpandasaspd

importnumpyasnp

importcv2

importos

importre

fromPILimportImage

importalbumentationsasA

fromalbumentations.pytorch.transformsimportToTensorV2

importtorch

importtorchvision

fromtorchvision.models.detection.faster_rcnnimportFastRCNNPredictor

fromtorchvision.models.detectionimportFasterRCNN

fromtorchvision.models.detection.rpnimportAnchorGenerator

fromtorch.utils.dataimportDataLoader,Dataset

fromtorch.utils.data.samplerimportSequentialSampler

frommatplotlibimportpyplotasplt

划分数据集

此处使用的数据采用 .csv 格式,其中包含边界框的 x、y、w 和 h 坐标,而数据使用数据注释器 make-sense 进行注释。

make-sense:https://www.makesense.ai/

image_ids=train_df[image_id].unique()

print(len(image_ids))

valid_ids=image_ids[-10:]

train_ids=image_ids[:-10]

#validandtraindf

valid_df=train_df[train_df[image_id].isin(valid_ids)]

train_df=train_df[train_df[image_id].isin(train_ids)]

创建一个 Scratch 类

创建我们的 Scratch Dataset 类,它转换我们的数据集并返回所需的参数。

classScratchDataset(Dataset):

def__init__(self,dataframe,image_dir,transforms=None):

super().__init__()

self.image_ids=dataframe[image_id].unique()

self.df=dataframe

self.image_dir=image_dir

self.transforms=transforms

def__getitem__(self,index:int):

image_id=self.image_ids[index]

records=self.df[self.df[image_id]==image_id]

image=cv2.imread(f{self.image_dir}/{image_id}.jpg,cv2.IMREAD_COLOR)

image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB).astype(np.float32)

image/=255.0

boxes=records[[x,y,w,h]].values

boxes[:,2]=boxes[:,0]+boxes[:,2]

boxes[:,3]=boxes[:,1]+boxes[:,3]

area=(boxes[:,3]-boxes[:,1])*(boxes[:,2]-boxes[:,0])

area=torch.as_tensor(area,dtype=torch.float32)

#thereisonlyoneclass

labels=torch.ones((records.shape[0],),dtype=torch.int64)

#supposeallinstancesarenotcrowd

iscrowd=torch.zeros((records.shape[0],),dtype=torch.int64)

target={}

target[boxes]=boxes

target[labels]=labels

target[image_id]=torch.tensor([index])

target[area]=area

target[iscrowd]=iscrowd

ifself.transforms:

sample={

image:image,

bboxes:target[boxes],

labels:labels

}

sample=self.transforms(**sample)

image=sample[image]

target[boxes]=torch.tensor(sample[bboxes])

returnimage,target,image_id

def__len__(self)->int:

returnself.image_ids.shape[0]

这里img_dir,是保存图像的目录路径。

数据扩充

在这里,我们使用 Albumentations 进行数据扩充。

#Albumenations

defget_train_transform():

returnA.Compose([

A.Flip(0.5),

ToTensorV2(p=1.0)

],bbox_params={format:pascal_voc,label_fields:[labels]})

defget_valid_transform():

returnA.Compose([

ToTensorV2(p=1.0)

],bbox_params={format:pascal_voc,label_fields:[labels]})

创建模型

我们将使用 Resnet50 模型和 Mask RCNN。

#loadamodelpre-trainedonCOCO

model=torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)

num_classes=2#1classscratch+background

#getnumberofinputfeaturesfortheclassifier

in_features=model.roi_heads.box_predictor.cls_score.in_features

#replacethepre-trainedheadwithanewone

model.roi_heads.box_predictor=FastRCNNPredictor(in_features,num_classes)

让我们开始创建一个 Averager 类以及训练和验证数据加载器,这将成为训练我们模型时的关键组件。

classAverager:

def__init__(self):

self.current_total=0.0

self.iterations=0.0

defsend(self,value):

self.current_total+=value

self.iterations+=1

@property

defvalue(self):

ifself.iterations==0:

return0

else:

return1.0*self.current_total/self.iterations

defreset(self):

self.current_total=0.0

self.iterations=0.0

defcollate_fn(batch):

returntuple(zip(*batch))

train_dataset=WheatDataset(train_df,DIR_TRAIN,get_train_transform())

valid_dataset=WheatDataset(valid_df,DIR_TRAIN,get_valid_transform())

#splitthedatasetintrainandtestset

indices=torch.randperm(len(train_dataset)).tolist()

train_data_loader=DataLoader(

train_dataset,

batch_size=16,

shuffle=False,

num_workers=4,

collate_fn=collate_fn

)

valid_data_loader=DataLoader(

valid_dataset,

batch_size=8,

shuffle=False,

num_workers=4,

collate_fn=collate_fn

)

训练模型

我们正在激活“cuda”并访问可用的 GPU。weight_decay=0.0005,momentum=0.9,动态学习率从 0.05 开始。

device=torch.device(cuda)iftorch.cuda.is_available()elsetorch.device(cpu)

images,targets,image_ids=next(iter(train_data_loader))

model.to(device)

params=[pforpinmodel.parameters()ifp.requires_grad]

optimizer=torch.optim.SGD(params,lr=0.005,momentum=0.9,

weight_decay=0.0005)

#lr_scheduler=torch.optim.lr_scheduler.StepLR(optimizer,step_size=3,gamma=0.1)

lr_scheduler=None

num_epochs=2

loss_hist=Averager()

itr=1

forepochinrange(num_epochs):

loss_hist.reset()

forimages,targets,image_ids,intrain_data_loader:

images=list(image.to(device)forimageinimages)

targets=[{k:v.to(device)fork,vint.items()}fortintargets]

loss_dict=model(images,targets)

losses=sum(lossforlossinloss_dict.values())

loss_value=losses.item()

loss_hist.send(loss_value)

optimizer.zero_grad()

losses.backward()

optimizer.step()

ifitr%50==0:

print(fIteration#{itr}loss:{loss_value})

itr+=1

#updatethelearningrate

iflr_schedulerisnotNone:

lr_scheduler.step()

print(fEpoch#{epoch}loss:{loss_hist.value})

但我无法实现这一点,因为仅仅 80 张图片就花了 10 个小时甚至更多时间。

使用 Mask RCNN 进行自定义训练的时间复杂度是巨大的,而且你需要大量的计算能力,这对我来说是没有的。

我希望你有好的计算资源并且你可以实现它。

通过 Yolov5 进行目标检测

Yolo 主要用于对象检测,由 Ultralytics 发布,已成为基准算法,例如视觉数据分割。Yolov5 比 Yolov4 更快、更高效,并且可以很好地泛化到新图像。

Yolov5: https://github.com/ultralytics/yolov5/releases

Yolov5架构

该算法的工作原理如下:

残差块边界框回归交并比(IOU)非极大值抑制 a

Yolov5 更快、更小,与以前的版本大致一样准确。在 coco 数据集上训练,它与边界框配合得很好。

让我们从问题案例中 Yolov5 的实现开始;我使用 google collab 来运行其中的代码。

数据标注

我使用了一个有意义的数据注释器来注释数据集。当数据被精确注释时,即小而切中要点时,Yolo 不能很好地工作,因为它不能很好地泛化到小边界框。因此数据标注有点棘手,需要对区域进行统一标注。

训练

加载模型后,

model=torch.hub.load(ultralytics/yolov5,yolov5s)

我们添加了 Yolo 工作所需的 yaml 文件和数据(图像在一个文件夹中,而注释作为文本文件在另一个文件夹中)我们训练了我们的模型,批量大小为 16,图像大小为 320*320。

!cdyolov5&&pythontrain.py–img320–batch16–epochs50–datacarScr_up.yaml–weightslast.pt

虽然在 Yolo 文档中,它声称要运行 300 个 epochs 才能获得良好的结果,但我们将其降低到 50 个 epochs,并且在超参数调整之后,我们的模型甚至在 30 个 epochs 内就开始表现不错。

对于超参数调优,我们使用 Yolo 提供的 evolution,其中数据经过 10 个 epoch 的训练,进行 300 次进化。

!cdyolov5&&pythontrain.py–img320–batch32–epochs10–datacarScr_up.yaml–weightsyolov5s.pt–cache–evolve

结果

ExpprecisionrecallmAP_0.51个0.0030.5110.0012个0.6590.3110.3633个0.6240.5360.5124个0.5720.6100.519

下图代表实验 4,每个实验都在不同数量的图像和注释上进行训练。汽车有划痕的预测如下:

使用 Yolov5 进行预测

在这种情况下,精度和召回率很小,因为使用 Yolo,我们正在处理边界框,这些指标取决于实际框和预测框的联合交集 (IOU)。

让我们看看用 Yolov5 训练我们的数据集 50 个时期后获得的指标

我们可以看到,在 20 个 epoch 之后,指标趋于稳定,可以看出 Yolo 可以非常快地学习这种关系并很好地泛化到我们的问题陈述,即使我们拥有的数据少于 1000 张图像。

结论

我们可以看到 Yolov5 和 Mask RCNN 对于我们的问题陈述非常有效,尽管我无法实现后者的代码。在使用 Yolov5 进行自定义训练时,排除指标,它能够非常好地预测,检测样本图像中的所有划痕和损坏。

我们在本文中学习了如何收集、注释和训练不同的模型,以及训练不同模型需要什么。

在上面,我将损坏和划痕视为一个单独的类别。数据注释和收集是该解决方案不可或缺的部分。如果我们使用多边形并增加我们的数据集大小,我们肯定可以做得更好。

PS:这不适用于没有损坏的汽车。因为我们只在包含有划痕和损坏的汽车的数据上训练它。

免责声明: 1、本站信息来自网络,版权争议与本站无关 2、本站所有主题由该帖子作者发表,该帖子作者与本站享有帖子相关版权 3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和本站的同意 4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责 5、用户所发布的一切软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 6、您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 7、请支持正版软件、得到更好的正版服务。 8、如有侵权请立即告知本站,本站将及时予与删除 9、本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章和视频仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。
600学习网 » 使用 Mask RCNN 和 Yolov5 进行划痕检测