前言

随着自动化、智能化技术在各行各业获得了广泛应用,化学实验室领域也不可避免的迎来了变革。视觉检测是自动化和智能化的基础,本文将介绍化学实验室常见物体的COCO格式的实例分割数据集的制作方法,后续将使用本文制作好的数据集,进行Mask-RCNN模型的训练和预测,用于检测我们自己的物体。

1. 本文使用的开发环境

Win10,64位+RTX3090

Visual Studio 2017

Python 3.6.13

CUDA 11.3.0+cuDNN 8.2.1

pytorch 1.10.0, torchvision 0.11.1

labelme 5.0.1, fiftyone 0.15.1

mmdetection 2.25.0

2. COCO格式的化学实验室常见物体数据集制作

Labelme数据集标注和COCO类型数据集转换可参考:

通过labelme制作coco格式数据集,并使用mask r-cnn训练_rick_M34的博客-CSDN博客_labelme2coco.py

labelme标注实例实例分割数据并转为COCO格式/VOC格式_ayiya_Oese的博客-CSDN博客_实例分割标注

我们需要自行收集化学实验室里需要被检测的物体的照片,比如烧瓶、烧杯、96孔板等等器材,然后再按下述步骤进行数据集制作:

step1,在项目COCO_style_dataset_IC(你可以改为自己的项目名称)的目录中建立如下的文件夹列表:

将自己的所有需要标注的图像文件放入images/total2019文件夹,注意图像文件名中最好不要有中文字符存在,避免后续程序运行出现异常。

step2,用Labelme对上述文件夹内的图像进行标注,我的图像里有2类检测对象flask和96-well plate,后面打算训练maskRCNN做实例分割检测。用Labelme里的Create Polygons将目标的轮廓标注出来,添加相应的标签即可。

注意一张图片里的多个同类目标,仍然以相同的标签命名,如下所示:

每张图片的标注完成后,都会生成相应的json格式的文件,内部除了含有标注信息外,还保存有整张图像数据。如下图所示:

然后,将上述文件夹内的json文件剪切到label/total2019文件夹内,如下图所示:

step3,通过creat_txt.py生成val2019.txt,train2019.txt,test2019.txt, trainval2019.txt。

 creat_txt.py

# !/usr/bin/python
# -*- coding: utf-8 -*-
import os
import randomtrainval_percent = 0.8  # 验证集+训练集占总比例多少
train_percent = 0.7  # 训练数据集占验证集+训练集比例多少
jsonfilepath = 'labelme/total2019'
txtsavepath = './'
total_xml = os.listdir(jsonfilepath)num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)ftrainval = open('./trainval2019.txt', 'w')
ftest = open('./test2019.txt', 'w')
ftrain = open('./train2019.txt', 'w')
fval = open('./val2019.txt', 'w')for i in list:name = total_xml[i][:-5] + '\n'if i in trainval:ftrainval.write(name)if i in train:ftrain.write(name)else:fval.write(name)else:ftest.write(name)ftrainval.close()
ftrain.close()
fval.close()
ftest.close()

训练集+验证集占总比例,以及训练集数据占训练集+验证集比例,可通过trainval_percent和train_percent调整。

step4,通过classify.py程序将json文件与图片分类。

该步骤将按照step3生成的val2019.txt,train2019.txt,test2019.txt文件,将图像和json文件归到相应的文件夹内。运行完成后,以下文件夹内将存入相应的文件。

 classify.py

import shutil
import cv2 as cvsets=['train2019',  'val2019', 'test2019']
for image_set in sets:image_ids = open('./%s.txt'%(image_set)).read().strip().split()for image_id in image_ids:img = cv.imread('images/total2019/%s.jpg' % (image_id))json='labelme/total2019/%s.json'% (image_id)cv.imwrite('images/%s/%s.jpg' % (image_set,image_id), img)cv.imwrite('labelme/%s/%s.jpg' % (image_set,image_id), img)shutil.copy(json,'labelme/%s/%s.json' % (image_set,image_id))
print("完成")

step5,通过labelme2coco_new.py生成train2019.json, test2019.json, val2019.json。

首先,在目录下建立labels.txt文件,内含目标类别信息(前两行__ignore__和_background_不要删掉)。以我的数据为例,含有2类物体,分别为flask和96-well plate:

然后修改labelme2coco_new.py文件内的input_dir, output_dir参数,使之在输出目录生成相应的JPEGImages文件夹、Visualization文件夹和annotations.json文件。

labelme2coco_new.py

#!/usr/bin/env pythonimport argparse
import collections
import datetime
import glob
import json
import os
import os.path as osp
import sys
import uuidimport imgviz
import numpy as npimport labelmetry:import pycocotools.mask
except ImportError:print("Please install pycocotools:\n\n    pip install pycocotools\n")sys.exit(1)def main():#parser = argparse.ArgumentParser(#    formatter_class=argparse.ArgumentDefaultsHelpFormatter#)#parser.add_argument("input_dir", help="input annotated directory")#parser.add_argument("output_dir", help="output dataset directory")#parser.add_argument("--labels", help="labels file", required=True)#parser.add_argument(#    "--noviz", help="no visualization", action="store_true"#)#args = parser.parse_args()input_dir = './labelme/train2019/'output_dir = './annotations/train2019/'labels = 'labels.txt'noviz = Falseif osp.exists(output_dir):print("Output directory already exists:", output_dir)sys.exit(1)os.makedirs(output_dir)os.makedirs(osp.join(output_dir, "JPEGImages"))if not noviz:os.makedirs(osp.join(output_dir, "Visualization"))print("Creating dataset:", output_dir)now = datetime.datetime.now()data = dict(info=dict(description=None,url=None,version=None,year=now.year,contributor=None,date_created=now.strftime("%Y-%m-%d %H:%M:%S.%f"),),licenses=[dict(url=None, id=0, name=None,)],images=[# license, url, file_name, height, width, date_captured, id],type="instances",annotations=[# segmentation, area, iscrowd, image_id, bbox, category_id, id],categories=[# supercategory, id, name],)class_name_to_id = {}for i, line in enumerate(open(labels).readlines()):class_id = i - 1  # starts with -1class_name = line.strip()if class_id == -1:assert class_name == "__ignore__"continueclass_name_to_id[class_name] = class_iddata["categories"].append(dict(supercategory=None, id=class_id, name=class_name,))out_ann_file = osp.join(output_dir, "annotations.json")label_files = glob.glob(osp.join(input_dir, "*.json"))for image_id, filename in enumerate(label_files):print("Generating dataset from:", filename)label_file = labelme.LabelFile(filename=filename)base = osp.splitext(osp.basename(filename))[0]out_img_file = osp.join(output_dir, "JPEGImages", base + ".jpg")img = labelme.utils.img_data_to_arr(label_file.imageData)imgviz.io.imsave(out_img_file, img)data["images"].append(dict(license=0,url=None,#file_name=osp.relpath(out_img_file, osp.dirname(out_ann_file)),file_name=base + ".jpg",height=img.shape[0],width=img.shape[1],date_captured=None,id=image_id,))masks = {}  # for areasegmentations = collections.defaultdict(list)  # for segmentationfor shape in label_file.shapes:points = shape["points"]label = shape["label"]group_id = shape.get("group_id")shape_type = shape.get("shape_type", "polygon")mask = labelme.utils.shape_to_mask(img.shape[:2], points, shape_type)if group_id is None:group_id = uuid.uuid1()instance = (label, group_id)if instance in masks:masks[instance] = masks[instance] | maskelse:masks[instance] = maskif shape_type == "rectangle":(x1, y1), (x2, y2) = pointsx1, x2 = sorted([x1, x2])y1, y2 = sorted([y1, y2])points = [x1, y1, x2, y1, x2, y2, x1, y2]if shape_type == "circle":(x1, y1), (x2, y2) = pointsr = np.linalg.norm([x2 - x1, y2 - y1])# r(1-cos(a/2))<x, a=2*pi/N => N>pi/arccos(1-x/r)# x: tolerance of the gap between the arc and the line segmentn_points_circle = max(int(np.pi / np.arccos(1 - 1 / r)), 12)i = np.arange(n_points_circle)x = x1 + r * np.sin(2 * np.pi / n_points_circle * i)y = y1 + r * np.cos(2 * np.pi / n_points_circle * i)points = np.stack((x, y), axis=1).flatten().tolist()else:points = np.asarray(points).flatten().tolist()segmentations[instance].append(points)segmentations = dict(segmentations)for instance, mask in masks.items():cls_name, group_id = instanceif cls_name not in class_name_to_id:continuecls_id = class_name_to_id[cls_name]mask = np.asfortranarray(mask.astype(np.uint8))mask = pycocotools.mask.encode(mask)area = float(pycocotools.mask.area(mask))bbox = pycocotools.mask.toBbox(mask).flatten().tolist()data["annotations"].append(dict(id=len(data["annotations"]),image_id=image_id,category_id=cls_id,segmentation=segmentations[instance],area=area,bbox=bbox,iscrowd=0,))if not noviz:viz = imgif masks:listdata_labels = []listdata_captions = []listdata_masks = []for (cnm, gid), msk in masks.items():if cnm in class_name_to_id:listdata_labels.append(class_name_to_id[cnm])listdata_captions.append(cnm)listdata_masks.append(msk)listdata = zip(listdata_labels, listdata_captions, listdata_masks)labels, captions, masks = zip(*listdata)#labels, captions, masks = zip(*[(listdata_labels, listdata_captions, listdata_masks)]) #print(len(masks))#labels, captions, masks = zip(#    *[#        (class_name_to_id[cnm], cnm, msk)#        for (cnm, gid), msk in masks.items()#        if cnm in class_name_to_id#    ]#)viz = imgviz.instances2rgb(image=img,labels=labels,masks=masks,captions=captions,font_size=15,line_width=2,)out_viz_file = osp.join(output_dir, "Visualization", base + ".jpg")imgviz.io.imsave(out_viz_file, viz)with open(out_ann_file, "w") as f:json.dump(data, f)if __name__ == "__main__":main()

总共要修改参数和运行程序3次(train2019, val2019, test2019),最后得到如下图所示的文件。

至此完成了COCO类型数据集的制作。

如果想要预览我们标注的数据集,可以查看Visulization文件夹内的图片。也可以使用fiftyone,具体代码见view_coco_style_data.py文件,只需要把文件里的data_path和labels_path设置为上图JPEGImages文件夹路径和annotations.json文件文件路径,然后运行程序即可。

view_coco_style_data.py

# pip install urllib3==1.25.11
# 降版本,否则报错import fiftyone as fo
import fiftyone.zoo as fozdataset = fo.Dataset.from_dir(dataset_type=fo.types.COCODetectionDataset,label_types = ["segmentations"],data_path=r'E:\Code\Python\COCO_style_dataset_IC\COCO_style_dataset_IC\annotations\train2019\JPEGImages',labels_path=r'E:\Code\Python\COCO_style_dataset_IC\COCO_style_dataset_IC\annotations\train2019\annotations.json',
)session = fo.launch_app(dataset, port = 5151)  # 没有指定port则默则5151
session.wait()  # 官网给的示例没有这一句,记得加上,不然程序不会等待,在网页中看不到我们要的效果

制作好的数据集预览效果如下图所示:

化学实验室自动化 - 1. 深度学习视觉检测(实例分割) - COCO格式的化学实验室常见物体实例分割数据集制作相关推荐

  1. 化学实验室自动化 - 1. 深度学习视觉检测(实例分割) - Mask-RCNN模型训练和预测

    在上一篇文章中,我们完成了化学实验室常见物体的COCO格式的实例分割数据集制作.上一篇文章的数据集中总共只有65张图像,而且被分成了训练集.验证集和测试集,经Mask-RCNN模型训练测试,发现模型的 ...

  2. 【flask整合深度学习】ubuntu系统下显示深度学习视觉检测结果图片并可在web端访问,配置允许手机浏览器打开

    介绍 flask文件 前端代码 输入命令 介绍 之前有一篇flask和mongodb交互的记录文: https://blog.csdn.net/qq_41358574/article/details/ ...

  3. 深度学习视觉系统在雪糕盒产品中的全方位识别检测

    2021年,中国冰淇淋行业市场超过1600亿元,冰淇淋市场规模为全球第一.作为盛放雪糕的载体,雪糕盒的质量也尤为重要.在生产过程中,有的雪糕盒表面会存在缺陷,或是雪糕盒与机器硬件之间的碰撞造成雪糕盒表 ...

  4. fasterrcnn深度学习口罩检测

    fasterrcnn深度学习口罩检测 前言 FasterRCNN原理详解 训练我们自己的FasterRCNN 使用labelimg制作我们自己的VOC数据集 FasterRCNN训练详解 源码地址与小 ...

  5. 视觉SLAM如何基于深度学习闭环检测?

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:计算机视觉life 请问有做视觉SLAM基于深度学习闭环 ...

  6. 普渡大学利用深度学习自动检测核反应堆裂缝

    美国普渡大学正在开发人工智能系统利用深度学习技术检测核反应堆裂缝,未来能帮助减少发生事故和维护成本. 普渡大学(Purdue University)正在开发一个系统,使用人工智能技术检测核反应堆视频中 ...

  7. 姿态检测 树莓派_怎样在树莓派上轻松实现深度学习目标检测?

    原标题:怎样在树莓派上轻松实现深度学习目标检测? 雷锋网按:本文为 AI 研习社编译的技术博客,原标题 How to easily Detect Objects with Deep Learning ...

  8. 【西安交大】2020年最新深度学习目标检测方法综述

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 目标检测的任务是从图像中精确且高效地识别.定位出大量预定义类别的物体实例.随着深度 ...

  9. 【每周CV论文】深度学习文本检测与识别入门必读文章

    欢迎来到<每周CV论文推荐>.在这个专栏里,还是本着有三AI一贯的原则,专注于让大家能够系统性完成学习,所以我们推荐的文章也必定是同一主题的. 文本检测和识别是计算机视觉的一个非常重要的应 ...

最新文章

  1. Science:细菌和古菌多重抗性系统抵御噬菌体和外来质粒
  2. 写博客必备的复制黏贴
  3. 干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的?
  4. 一位小小码蚁工作2年多感想
  5. jenkins中通过Publish Over SSH将项目部署到远程机器上
  6. eclipse和Tomcat绑定
  7. python启动多个进程_Python程序中的进程操作--—--开启多进程
  8. android服务的应用,Android学习指南之十四:Service详解及应用实例
  9. jquery validate验证remote时的多状态问题
  10. js学习总结----浏览器滚动条卷去的高度scrolltop
  11. fmt—fmt:formatDate的输出格式
  12. linux宿主机文件拷贝,linux 虚拟机和宿主机相互拷贝文件
  13. 石灰窑计算机控制上料,石灰窑自动化控制系统
  14. flow_from_directory返回值
  15. 电源中104电容的作用
  16. mysql日期函数之DATEDIFF() if()用法 case when用法
  17. 封神演义人物实力分级点评
  18. PNG怎么转换成PDF?这篇文章教会你
  19. vue双向绑定数据更新会频繁触发render更新
  20. 史上最全的测试用例设计方法

热门文章

  1. 安装完docker命令后,通过安装mysql、tomcat、nignx,安装普罗米修斯监控软件
  2. mysql 字段移动平均值_Excel-移动平均分析(趋势分析)
  3. 科技云报道:大风起兮,元宇宙的迷惑与野望
  4. 【Python】 如何生成代码图类似苹果电脑格式
  5. ORACLE通配符转义
  6. 武侠已死?那你肯定没看过第四届橙瓜网络文学奖评分榜上这几本
  7. (阅读笔记)PARE:A Simple and Strong Baseline for Monolingual and MultilingualDistantly Supervis
  8. 名帖195 黄庭坚 行书《松风阁诗帖》
  9. 【Python】高级特性 一
  10. DirectUI 入门(一) 介绍及配置环境