PowerShell + python 批量进行labelme生成标注数据并提取标注内容
文章目录
Before we begin
这里介绍了如何通过Python编写爬虫程序爬取网页内容,以爬取谷歌图片为例,然后我们接下来希望通过我们爬取的图片构建一个数据集用于模型训练,首先我们必须做好图片的标注工作
1,图片标注
1.1 Mask R-CNN
推荐大家去看一下关于Mask R-CNN,Fast/Faster R-CNN,R-CNN,好吧还有CNN这一系列的论文,或者说,你也可以直接去下载Mask R-CNN在Github上的代码项目,然后安装去跑一下。这个是一个进行自动标注的卷积神经网络(事实上这个网络分为了上下两部分网络,具体可以去看一下论文或者是别人翻译好的博客),通过训练这个网络可以实现基于labelme的图片自动标注,提取目标内容,具有非常不错的效果,可以亲自去试一下。
1.2 labelme
简称labelme,全称label by me,就是由我进行标注,即:手动完成几百张图片的标注。。。可以亲自去试一下txtx
数据集将会是这样的:
其中:
-
img.png
:原图 -
label.png
:标注图片 -
label_viz.png
:标明了标注内容和背景内容的图片
2,PowerShell 批处理
2.1 PowerShell
如果你没用过PowerShell,在运行(Cmd + R)中输入PowerShell
,你就可以见到它了
2.2 PowerShell 批量进行 labelme_json_to_dataset
我们可以在json_to_dataset.py中看到这样的warning
语句:
def main():
logger.warning('This script is aimed to demonstrate how to convert the'
'JSON file to a single image dataset, and not to handle'
'multiple JSON files to generate a real-use dataset.')
“警告:这个脚本目的是展示如何将一个JSON文件转为一张图片的数据集,而不是批量处理JSON文件来生成一个具有实用性的数据集”
大意如上,所以我们需要自己编写一个批处理脚本,并且,将标注内容抓取出来(事实上,labelme_json_to_dataset只是生成两张图片一张是用不同颜色对不同标注区域进行填充的图片,另外一张是将非标注区域)。
我们将要编写的是一个PowerShell脚本,代码如下:
$jsons = get-childitem -Filter *.json
$jsons | foreach-object{
labelme_json_to_dataset $_.Name
}
其中$_
表示当前的对象,Name
是对象的一个属性,即文件或者文件夹的名称(包含后缀)
所以这份代码所要做的工作就是:
- 首先得到所有的
json
文件,存储在一个变量$jsons
中(PowerShell的变量都是以一个$
开头来和cmdlet
以及其他命令区分开来) - 然后对每个
json
文件传递给labelme_json_to_dataset
进行数据集生成
最终会在当前文件夹下生成对应数量的数据集文件夹。
2.3 Python + PowerShell 提取标注内容
接下来,我们希望将标注内容从原图中提取出来,这很简单,因为我们得到的label.png
其实就是一个mask:我们只保留原图中对应mask位置非零的部分。
代码如下:
import sys
import os
import numpy as np
import cv2
def error(arguments):
print('ERROR: ' + str(len(arguments)) + 'doesn\'t match valid numbers of argument' )
print('expect: [-image_file] [-label_image_file]')
def __main__():
script_name = sys.argv[0]
if len(sys.argv) >= 3:
# directory name
dir_name = sys.argv[1]
# original imgage
origin_img_file = sys.argv[2]
# label.png as the mask
mask_img_file = sys.argv[3]
try:
origin = cv2.imread(os.path.join(dir_name, origin_img_file))
# raise an exception if we couldn't read the image successfully,
# cause cv2.imread doesn't handle this exception for us. It will
# be of `NoneType` when it can not be loaded successfully
if not type(origin) is np.ndarray:
raise Exception(origin_img_file + ' doesn\'t exist!')
mask = cv2.imread(os.path.join(dir_name, mask_img_file))
# same as above
if not type(mask) is np.ndarray:
raise Exception(mask_img_file + ' doesn\'t exist!')
# explore the mask
for i in range(mask.shape[0]):
for j in range(mask.shape[1]):
# apply mask
if mask[i][j][0] + mask[i][j][1] + mask[i][j][2] == 0:
origin[i][j][0] = 0
origin[i][j][1] = 0
origin[i][j][2] = 0
else:
continue
# save result image under the specified output directory
output_path = os.path.join('./dataset', dir_name + '_result.png')
cv2.imwrite(output_path, origin)
print(output_path)
except Exception as err:
print(err)
else:
error(sys.argv)
if __name__ == '__main__':
__main__()
对于python相关的使用这里就不再赘述(对于这份代码中命令行传递给脚本的参数,即sys.argv
,下面将会作进一步的说明)。
当然,我们必须对每个数据集文件夹都做这样的操作,所以同样的我们需要编写一个批处理文件:
rm dataset -recursive
md dataset
$dirs = get-childitem -Filter *_json
$dirs | foreach-object{
$items = get-childitem $_
python scoup_target_bat.py $_.Name $items[0].Name $items[2].Name
}
其中:
-
scoup_target_bat.py
:即我们上面的python文件 -
$_.Name
:传递给脚本的第一个参数,即这个数据集文件夹的名称 -
$items[0].Name
:传递给脚本的第二个参数,即数据集文件夹中的img.png
-
$items[2].Name
:传递给脚本的第三个参数,即数据集文件夹中的label.png