本文仅提供Fasterrcnn对2021年天池大赛——广东工业智能创新大赛初赛的基本检测过程,代码可直接实现,但未添加有效的数据预处理过程,上传后评分结果很低。
本博文可供参考部分:
Fasterrcnn的代码;json文件转换为coco格式;检测结果转换为单独json文件;
提示:以下是本篇文章正文内容,下面案例可供参考
详细见2021年天池广东工业智能创新大赛
赛题聚焦瓷砖表面瑕疵智能检测,要求选手开发出高效可靠的计算机视觉算法,提升瓷砖表面瑕疵质检的效果和效率,降低对大量人工的依赖。要求算法尽可能快与准确的给出瓷砖疵点具体的位置和类别,主要考察疵点的定位和分类能力。
大赛深入到佛山瓷砖知名企业,在产线上架设专业拍摄设备,实地采集生产过程真实数据,解决企业真实的痛点需求。大赛数据覆盖到了瓷砖产线所有常见瑕疵,包括粉团、角裂、滴釉、断墨、滴墨、B孔、落脏、边裂、缺角、砖渣、白边等(实际数据集中分为6种缺陷)。实拍图示例如下:
初赛的数据集是白板瓷砖。花色简单,数量总共约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": "光圈瑕疵"
}
0.2ACC+0.8mAP
其中ACC:是有瑕疵或无瑕疵的分类指标,考察瑕疵检出能力;mAP:参照PASCALVOC的评估标准计算瑕疵的mAP值。
Faster-RCNN是一个非常有效的目标检测算法,虽然是一个比较早的论文, 但它至今仍是许多目标检测算法的基础。
Faster-RCNN作为一种two-stage的算法,与one-stage的算法相比,two-stage的算法更加复杂且速度较慢,但是检测精度会更高。
事实上也确实是这样,Faster-RCNN的检测效果非常不错,但是检测速度与训练速度有待提高。
(待补充。。。)
pytorch1.7
python3.8
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进行训练。
详见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'])
在以上“二、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的运行过程,下一步再进行尝试其他手段。
还望各位大佬多指点!
文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态
文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境
文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn
文章浏览阅读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
文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机
文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk
文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入
文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。 Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。
文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动
文章浏览阅读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技术的停车场管理系统实现与设计
文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;gt;Jni-&amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图
文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法