【Fasterrcnn代码】2021广东工业智造创新大赛—智能算法赛

本文介绍了2021年天池广东工业智能创新大赛,赛题关注瓷砖表面瑕疵检测。作者分享了使用Fasterrcnn进行目标检测的实现,包括数据集、评估方式、标注转换和结果提交。Fasterrcnn在处理瓷砖瑕疵检测时面临挑战,如小瑕疵检测效果不佳,但提供了代码和流程供参考。
摘要由CSDN通过智能技术生成


前言

本文仅提供Fasterrcnn对2021年天池大赛——广东工业智能创新大赛初赛的基本检测过程,代码可直接实现,但未添加有效的数据预处理过程,上传后评分结果很低。
本博文可供参考部分:
Fasterrcnn的代码;json文件转换为coco格式;检测结果转换为单独json文件


提示:以下是本篇文章正文内容,下面案例可供参考

一、2021年天池广东工业智能创新大赛初赛简介

1、大赛背景

详细见2021年天池广东工业智能创新大赛
赛题聚焦瓷砖表面瑕疵智能检测,要求选手开发出高效可靠的计算机视觉算法,提升瓷砖表面瑕疵质检的效果和效率,降低对大量人工的依赖。要求算法尽可能快与准确的给出瓷砖疵点具体的位置和类别,主要考察疵点的定位和分类能力

大赛深入到佛山瓷砖知名企业,在产线上架设专业拍摄设备,实地采集生产过程真实数据,解决企业真实的痛点需求。大赛数据覆盖到了瓷砖产线所有常见瑕疵,包括粉团、角裂、滴釉、断墨、滴墨、B孔、落脏、边裂、缺角、砖渣、白边等(实际数据集中分为6种缺陷)。实拍图示例如下:在这里插入图片描述

2、数据集

初赛的数据集是白板瓷砖。花色简单,数量总共约12000张,包含训练集和测试集。
下面是训练集中缺陷标注的json示例(无缺陷图片在json文件中不显示)。

[
    {
        "name": "226_46_t20201125133518273_CAM1.jpg",
        "image_height": 6000,
        "image_width": 8192,
        "category": 4, #缺陷类别
        "bbox": [ #缺陷定位
            1587,
            4900,
            1594,
            4909
        ]
    },
    '''
    '''
]

关于以上“category”指该图片中缺陷的类别,具体数字对应类别如下:

{
  "0": "背景",
  "1": "边异常",
  "2": "角异常",
  "3": "白色点瑕疵",
  "4": "浅色块瑕疵",
  "5": "深色点块瑕疵",
  "6": "光圈瑕疵"
 }

3、评估方式

0.2ACC+0.8mAP

其中ACC:是有瑕疵或无瑕疵的分类指标,考察瑕疵检出能力;mAP:参照PASCALVOC的评估标准计算瑕疵的mAP值。

二、Fasterrcnn简介及实现

1、简介

Faster-RCNN是一个非常有效的目标检测算法,虽然是一个比较早的论文, 但它至今仍是许多目标检测算法的基础。

Faster-RCNN作为一种two-stage的算法,与one-stage的算法相比,two-stage的算法更加复杂且速度较慢,但是检测精度会更高。

事实上也确实是这样,Faster-RCNN的检测效果非常不错,但是检测速度与训练速度有待提高。

(待补充。。。)

参考 Faster-RCNN CSDN

2、实现

(1)、实现平台

pytorch1.7
python3.8

(2)、代码链接和训练

Step1: 下载代码

大佬的代码链接:faster-rcnn-pytorch
本渣的代码链接:
链接:https://pan.baidu.com/s/1qsUOEjCiZOt0MmpoDEhP-w 密码:d12o

(本质相同,本渣的代码是自己在接口方面做了微调,更适合直接用于该赛题)
在这里插入图片描述

Step2: 用训练好的代码直接测试单张图片

运行predict.py文件,随后输入要测试的单张图片文件路径和名称,如img/test.jpeg(提前在img文件夹中放入要检测的图片)

Step3: 用训练好的代码对测试集中的文件进行测试

打开predict_folder.py文件,修改testpath参数,该参数是测试图片所在的文件夹路径。

运行predict_folder.py

运行结束后,检测结果将会存储在test_data.json文件中。

Step4: 训练自己的faster-rcnn网络

因为文件大小限制,请先下载赛题中给出的训练集图片9.1G。赛题训练集图片 并将训练集图片放置在faster-rcnn/VOCdevkit/VOC2007/JPEGImages文件夹中。

验证集图片2.77G 验证集图片,并将验证集图片放置在
faster-rcnn/test文件夹中。

点击train.py进行训练。

三、如何将大赛提供的json注释转化为coco格式进行训练?

详见jsonxml文件夹。
在这里插入图片描述
其中JPEGJmages存放训练集的图片,用于进行训练。main.py是转化的代码,train_annos.json是大赛提供的训练集的标注。

main.py的内容如下:

import json
from xml.etree import ElementTree as ET

import cv2
import math

img_paths = '/home/XXX/桌面/fasterrcnn/faster-rcnn/VOCdevkit/VOC2007/JPEGImages/'

with open('train_annos.json', 'r') as f:
    image_meta = json.load(f, encoding='etf-8')

each_img_meta = {}
for each_item in image_meta:
    each_img_meta[each_item['name']] = []

for idx, each_item in enumerate(image_meta):
    bbox = each_item['bbox']
    bbox.append(each_item['category'])
    each_img_meta[each_item['name']].append(bbox)


# 创建xml文件的函数
def create_tree(image_name, h, w):
    global annotation
    # 创建树根annotation
    annotation = ET.Element('annotation')
    # 创建一级分支folder
    folder = ET.SubElement(annotation, 'folder')
    # 添加folder标签内容
    folder.text = None

    # 创建一级分支filename
    filename = ET.SubElement(annotation, 'filename')
    filename.text = image_name

    # 创建一级分支source
    source = ET.SubElement(annotation, 'source')
    # 创建source下的二级分支database
    database = ET.SubElement(source, 'database')
    database.text = 'Unknown'

    # 创建一级分支size
    size = ET.SubElement(annotation, 'size')
    # 创建size下的二级分支图像的宽、高及depth
    width = ET.SubElement(size, 'width')
    width.text = str(w)
    height = ET.SubElement(size, 'height')
    height.text = str(h)
    depth = ET.SubElement(size, 'depth')
    depth.text = '3'

    # 创建一级分支segmented
    segmented = ET.SubElement(annotation, 'segmented')
    segmented.text = '0'


# 定义一个创建一级分支object的函数
def create_object(root, xi, yi, xa, ya, obj_name):  # 参数依次,树根,xmin,ymin,xmax,ymax
    # 创建一级分支object
    _object = ET.SubElement(root, 'object')
    # 创建二级分支
    name = ET.SubElement(_object, 'name')
    # print(obj_name)
    name.text = str(obj_name)
    pose = ET.SubElement(_object, 'pose')
    pose.text = 'Unspecified'
    truncated = ET.SubElement(_object, 'truncated')
    truncated.text = '0'
    difficult = ET.SubElement(_object, 'difficult')
    difficult.text = '0'
    #     # 创建bndbox
    bndbox = ET.SubElement(_object, 'bndbox')
    xmin = ET.SubElement(bndbox, 'xmin')
    xmin.text = '%s' % xi
    ymin = ET.SubElement(bndbox, 'ymin')
    ymin.text = '%s' % yi
    xmax = ET.SubElement(bndbox, 'xmax')
    xmax.text = '%s' % xa
    ymax = ET.SubElement(bndbox, 'ymax')
    ymax.text = '%s' % ya


import os

os.makedirs('./JPEGImages',exist_ok=True)
os.makedirs('./Annotations',exist_ok=True)
window_s = 1333
for idx, each_item in enumerate(image_meta):
    # print(each_item)

    bbox = each_item['bbox']
    img = cv2.imread(img_paths + each_item['name'])
    h, w = img.shape[:2]

    # each_img_meta[each_item['name']].append(bbox)
    center_x, center_y = int(bbox[0] + (bbox[2] - bbox[0]) / 2), int((bbox[3] - bbox[1]) / 2 + bbox[1])

    x, y, r, b = center_x - window_s // 2, center_y - window_s // 2, center_x + window_s // 2, center_y + window_s // 2

    x = max(0, x)
    y = max(0, y)
    r = min(r, w)
    b = min(b, h)

    boxes = each_img_meta[each_item['name']]

    annotations = []
    for e_box in boxes:
        if x < e_box[0] < r and y < e_box[1] < b and x < e_box[2] < r and y < e_box[3] < b:
            e_box = [int(i) for i in e_box]
            e_box[0] = math.floor(e_box[0] - x)
            e_box[1] = math.floor(e_box[1] - y)
            e_box[2] = math.ceil(e_box[2] - x)
            e_box[3] = math.ceil(e_box[3] - y)
            annotations.append(e_box)

    print('process id:', idx, "|", annotations)
    slice_img = img[y:b, x:r]

    create_tree(each_item['name'], window_s, window_s)

    for anno in annotations:
        create_object(annotation, anno[0], anno[1], anno[2], anno[3], anno[4])
    tree = ET.ElementTree(annotation)

    slice_name=each_item['name'][:-4]+'_'+str(x)+'_'+str(y)+'.jpg'
    xml_name=each_item['name'][:-4]+'_'+str(x)+'_'+str(y)+'.xml'
    cv2.imwrite('./JPEGImages/' + slice_name, slice_img)
    tree.write('./Annotations/' + xml_name)

    # for anno in annotations:
    #     cv2.putText(slice_img, str(anno[4]), (int(anno[0]) - 5, int(anno[1]) - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
    #                 (0, 255, 0))
    #     cv2.rectangle(slice_img, (int(anno[0]), int(anno[1])), (int(anno[2]), int(anno[3])), (0, 255, 0), 2)
    # cv2.imshow('slice_img', slice_img)
    #
    # cv2.waitKey(1000)

    if x < 0 or y < 0 or r > w or b > h:
        print(idx)
        print(each_item['name'])

四、训练结束后如何将测试结果转化为json文件进行提交?

在以上“二、2、(2)、Step3: 用训练好的代码对测试集中的文件进行测试”中对文件夹中图片进行测试时,predict_folder.py中已经展示了进行测试时顺便将测试结果添加到json文件中的过程了。

主要思路是: 从文件夹中依次读取图片——输入训练好的网络中进行检测——将检测结果根据大赛提交要求,将label,bbox,category,score等提取出来——创建包含这4项检测结果的字典——将字典写入json文件中——所有图片检测完成,关闭json文件。

具体实现代码为:

from frcnn import FRCNN
from PIL import Image
import os
import json
import numpy as np
import torch
from nets.frcnn_training import get_new_img_size
from utils.utils import DecodeBox

# ---------------------------------------------------------------------------------------
# 对测试集进行目标检测,并将其结果写入json文件中
# ---------------------------------------------------------------------------------------

test_path = 'testset' #放置测试图片的文件夹路径
images_totalnum = len([lists for lists in os.listdir(test_path) if os.path.isfile(os.path.join(test_path, lists))]) #测试集中图片的总数量

frcnn = FRCNN()

class NpEncoder(json.JSONEncoder):
    '''
    json文件写入操作防止出现编码错误
    '''
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        else:
            return super(NpEncoder, self).default(obj)

image_num = 1
with open('test_data.json','w') as json_file:
    for filename in os.listdir(r'./' + test_path):
        image = Image.open(test_path + '/' + filename)
        image = image.convert("RGB")
        try:
            label,score,bbox = frcnn.detect_image(image)
            for i in range(len(label)):
                test_dict = {
                    'name': filename,
                    "category": label[i],
                    "bbox": bbox[i],
                    "score": score[i]
                }
                json_str = json.dumps(test_dict, cls=NpEncoder)
                json_file.write(json_str + ',' + '\n')
                print(str(image_num)+"/"+str(images_totalnum)+ ' | label: ' + (label[i]) +'  score:' + str(score[i]))
            image_num += 1
        except:
            print(str(image_num)+"/"+str(images_totalnum)+' is no defect.')
            image_num += 1
print("Writing to a JSONFile is finishing!")

总结

虽然训练了100个epoch后,验证集的loss已经达到0.1943,但未对图片进行切图,滑窗等手段,使得faster-rcnn直接预测本赛题中的瑕疵效果很差,resize后更是看不到小的瑕疵点。

这里mark一下faster-rcnn的运行过程,下一步再进行尝试其他手段。

还望各位大佬多指点!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值