一. 从OpenImagess收集指定物体图片
煮个栗子,从OpenImages收集大量包含眼镜的图片。
总体来说,分2步:
1.获取包含眼镜的图片的id列表(注:图片文件名 = id + ".jpg")
2.根据id列表下载相应的图片。
具体来说:
1.打开OpenImages网站,看看它长啥样
https://storage.googleapis.com/openimages/web/index.html
在菜单栏,在Type下拉菜单中选择Detection,在Category下拉菜单中选择Glasses
由于我们对太阳眼镜不感兴趣,所以就只从检测标注文件里“Glasses”类别获取图片id
2.获取感兴趣图片的id
首先,返回首页,并点击Download。(或者,在Explore页面的右上角点击Download也可)
这个什么可视化工具我们先不管(新出来的,上次没看到,下次探索下)
官网给出了手工下载感兴趣类别图片集的流程,包括:首先下载downloader.py文件,然后自己写个脚本,生成感兴趣图片的id列表的txt文件,接着运行downloader.py文件
要做到这一点,我们首先需要下载:边界框的标注文件(因为我们根据标有“Glasses”的边界框来筛选包含眼镜的图片)和Metadata里的Class Names文件
右键下载后得到:边界框标注csv文件oidv6-train-annotations-bbox.csv
,类别名描述文件oidv6-class-descriptions.csv
。
边界框标注csv文件很大,手动Notepad++打开或者python脚本import csv
都打不开,会导致电脑卡死,需要python脚本import pandas
。类别名描述csv文件比较小,几百k,手动Notepad++打开,我们先看看这个文件里内容长啥样
LabelName,DisplayName
/m/0100nhbf,Sprenger's tulip
/m/0104x9kv,Vinegret
/m/0105jzwx,Dabu-dabu
/m/0105ld7g,Pistachio ice cream
/m/0105lxy5,Woku
/m/0105n86x,Pastila
/m/0105ts35,Burasa
/m/0108_09c,Summer snowflake
/m/010dmf,Isle of man tt
/m/010jjr,Amusement park
/m/010l12,Roller coaster
/m/010lq47b,Witch hat
/m/010ls_cv,Sandwich Cookies
/m/010xc,Aspartame
/m/01127,Air conditioning
/m/0114n,Atari jaguar
/m/01154,Atari lynx
/m/01172_8x,Pencil skirt
/m/0117_25k,Saffron crocus
...
所以,我们要写个脚本,根据DisplayName
为Glasses
找到对应的LabelName
import csv
with open('oidv6-class-descriptions.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
if 'Glasses' in row[1]:
print (row)
输出是:
['/m/0jyfg', 'Glasses']
就这样,我们找到了眼镜对应的LabelName
, 是/m/0jyfg
,然后,根据以下脚本生成包含图片id的txt文件
import pandas as pd
import os.path
import os
txt_file_name = 'name_the_file_whatever_you_like.txt'
if os.path.isfile(txt_file_name):
os.remove(txt_file_name)
file = open(txt_file_name,'w')
idset = set()
metadata = pd.read_csv('oidv6-train-annotations-bbox.csv')
total_rows = metadata.shape[0]
for i in range(total_rows):
if metadata.loc[i]['LabelName'] == '/m/0jyfg':
img_id = 'train/' + metadata.loc[i]['ImageID']
idset.add(img_id)
for d in idset:
file.write(d+'\n')
file.close()
由于oidv6-train-annotations-bbox.csv
里行数很多,这个脚本运行大概需要2万年。然后,我们就得到了图片id列表的txt文件,打开,它是长这样的:
train/cc08388b2ca1c118
train/13840c988a6795b8
train/8e263f0d55360e04
train/a9302564d7575e64
train/82dc1a7e5c8049f0
train/b72e84b2f4f18c6c
train/0a8defe621c42111
train/16005aa4569109f5
train/6c41c0ceb7e5e600
train/6470016c2b9b2902
...
然后将这个txt文件和downloader.py
文件放在同个目录,然后运行:
python downloader.py name_the_file_whatever_you_like.txt --download_folder=imgs --num_processes=2
然后就开始下载并存放在程序创建的文件夹imgs
里了
二. 生成标签
以人像分割为例
1.进入阿里云视觉智能平台
在浏览器上搜索“阿里云视觉智能开放平台”,进入“阿里云视觉智能开放平台”,支付宝扫码登录
也可直接按网址进入:https://vision.aliyun.com/
2.单张图片生成标签
依次点击“能力广场”、“分割抠图”、“人像分割”、“上传图片”、“结果下载”
3.批量生成标签
如果你想要批量的处理图片,你还需要预先开通阿里云的OSS存储
OSS是云端存储器,类似于百度云,可以为你的数据集的每张图片生成url地址,然后就可以自己撰写脚本,使用for循环将每个图片的url送入阿里云的分割功能
3.1首先找到OSS
进入这个链接:https://homenew.console.aliyun.com/home/dashboard/ProductAndService
另一种方式:你也可以首先进入阿里云的首页:https://www.aliyun.com/,然后进入控制台
点击“产品与服务”,“对象存储OSS”
3.2上传图片至OSS
进入OSS后要创建一个bucket,类似于仓库。这一步最关键的是要将读写权限设置为“公共可读”,否则后面调用分割功能就会失败
存储空间(Bucket)是用于存储对象(Object)的容器。在上传前,要先创建Bucket。创建Bucket如下:
(1)单击Bucket列表,然后单击创建Bucket。
(2)也可以单击概览,然后单击右上角的创建Bucket。
(3)在创建Bucket面板,按如下说明配置必要参数。其他参数均可保持默认配置,也可以在Bucket创建完成后单独配置。
使用命令行工具:ossutil
要先在服务器上安装ossutil
安装过程参考官方提供的教程
wget http://gosspublic.alicdn.com/ossutil/1.7.3/ossutil64
chmod 755 ossutil64
(这一句干嘛的,用不用,我也忘了)
安装好,在服务器上切换到ossutil所在目录:cd /xxxxx/oss
第一次用ossutil要需要运行:chmod +x ossutil64; mv ossutil64 ossutil
然后运行命令行帮助指令./ossutil help ls -L ch
如果上一句指令输出显示正常,那么你就可以执行下一行指令完成大规模数据集的上传了:
./ossutil cp -r /xxxxxx your local file folder xxxxxxx/ oss:// your bucket name / the file folder in the bucket /
这里容易出错的是dst_dir一定要按照上面这个格式写,是oss://
开头,而不是https://
开头。另外整个命令行开头的./ossutil
别忘了
OSS更多使用问题可参考官方帮助文档:在搜索框了搜索“OSS”,然后找到文档,然后点进去
3.3批量对已存储至OSS的图片生成标签
首先要返回第1步和第2步,进入“阿里云视觉智能开放平台”,点击“能力广场”、“分割抠图”、“人像分割”,开通人像分割的服务,拿到密钥。
参照示例代码,撰写示例脚本:
from aliyunsdkcore.client import AcsClient
from aliyunsdkimageseg.request.v20191230 import SegmentBodyRequest
import json
import urllib.request
import os
input_set = set(os.listdir("/your local img file folder/")) # for idx use in ‘for’ loop, you can also use txt or csv that write imgname_list instead
alpha_save_root = "/your local label file save folder/"
finiset = set(os.listdir(alpha_save_root))
client = AcsClient("<accessKeyId>", "<accessSecret>", "cn-shanghai")
url_head = "https://***your bucket address***-bucket.oss-cn-shanghai.aliyuncs.com/ the file folder in the bucket/"
request = SegmentBodyRequest.SegmentBodyRequest()
for i in range(50):
files = input_set - finiset
print("\n\n\n\nlen(files)",len(files))
print(len(input_set))
print(len(finiset))
for file in files:
if "jpg" in file or "png" in file:
try:
input_url = url_head + file
request.set_ImageURL(input_url)
request.set_ReturnForm("mask")
response = client.do_action_with_exception(request)
response_dict = json.loads(response)
alpha_url = response_dict["Data"]["ImageURL"]
urllib.request.urlretrieve(alpha_url, alpha_save_root + file)
except:
print("ERRORA", file)
else:
print("ERRORB", file)
然后运行这个脚本。查看分割结果
注意:不是每一张图片都能被成功分割。例如人像分割功能,假如图片中没有人,或者置信度比较低的话,可能就没有分割结果