【Fasterrcnn代码】2021广东工业智造创新大赛—智能算法赛_如何import get_new_img_size-程序员宅基地

技术标签: 人工智能  pytorch实现  


前言

本文仅提供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的运行过程,下一步再进行尝试其他手段。

还望各位大佬多指点!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37412775/article/details/112917974

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法