AnyLabeling标定及转化成labelmaskID
一、标定工具
在进行分割任务时,对分割工具进行预研和验证,现在AI辅助标定已经成熟,目标则是利用sam进行辅助标定。调研的三款标定工具情况如下:
- labelme:可以加载sam,但是在进行辅助标定后,对图像质量要求较高,真心不好用。主要体现在辅助标定后,无法调整。
- cvat:本地部署手工标注成功了,但在部署辅助标定时,按照教程各种失败,最后放弃了。从宣传效果上看起来挺好用,尤其团队能工作分工合作。
- x-Anylabeling:部署简单,在Windows有执行程序,当然还支持加载自己的模型(此处需要源码安装)。在加载sam模型后,通过point+/point-等操作能细化调整标定框,真心好用。后续直接用anylabeling进行标注了。
另外在通用检测模型中,尝试了大部分模型有较大优化空间,当然希望集成按照label进行目标标定,而不是点击“run”后所有目标都进行标定。当然自己后续可以通过脚本处理也是没有问题的。
二、标定json文件转化为maskID
在训练时使用的时mmsegmention,模型输入是原始图片和maskID,为此需要将标定后的json文件转化为maskID。anylabeling是参考labelme的输出格式相同,当然在anylabeling中有脚本为:polygon_mask_conversion.py,其中的核心代码为:
def polygon_to_mask(self, img_file, mask_file, json_file):
with open(json_file, 'r') as f:
data = json.load(f)
polygons = []
for shape in data['shapes']:
points = shape['points']
polygon = []
for point in points:
x, y = point
polygon.append((x, y))
polygons.append(polygon)
image_width, image_height = self.get_image_size(img_file)
image_shape = (image_height, image_width)
binary_mask = np.zeros(image_shape, dtype=np.uint8)
for polygon_points in polygons:
np_polygon = np.array(polygon_points, np.int32)
np_polygon = np_polygon.reshape((-1, 1, 2))
#只是将区域内设置为255
cv2.fillPoly(binary_mask, [np_polygon], color=255)
cv2.imwrite(mask_file, binary_mask)
里面只是将poly区域内设置为255,则效果图为:
则不符合要求。
答案代码如下:
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")
args = parser.parse_args()
if not osp.exists(args.output_dir):
os.makedirs(args.output_dir)
file_list = [i for i in os.listdir(args.input_dir) if i.endswith("json")]
for file in file_list:
file_name = os.path.join(args.input_dir, file)
json_data = json.load(open(file_name))
height, width = json_data["imageHeight"], json_data["imageWidth"]
#核心代码是labelme实现的,直接调用即可
lbl, lbl_names = utils.shape.labelme_shapes_to_label([height, width], json_data['shapes'])
out_file = osp.join(args.output_dir, '{}.png'.format(os.path.basename(file)))
lbl_pil = Image.fromarray(lbl.astype(np.uint8), mode="P")
lbl_pil.save(out_file)
# utils.lblsave(out_file, lbl)
print('Saved to: %s' % out_file)
核心代码可以去labelme寻找答案。在保存后,效果图如下:
因为数值是1,2,3所以全是黑色,此时要实现将像素值打印在图片上。
三、像素值打印在图片上
在打印上如果每个像素都打上数字,因为像素位置挨着近,数字小,则无法看出,此时需要进行临近区域处理,具体的代码为:
def check_mask():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument("input_dir", help="input annotated directory")
args = parser.parse_args()
file_list = [i for i in os.listdir(args.input_dir) if i.endswith("png")]
file_name = os.path.join(args.input_dir, file_list[0])
image = Image.open(file_name)
image = image.convert("RGB")
# 获取图片的像素数据
pixels = list(image.getdata())
# 创建一个可以在图像上绘制文本的对象
draw = ImageDraw.Draw(image)
# 设置字体和字体大小
font = ImageFont.truetype("arial.ttf", size=12) # 这里使用了Arial字体,你可以替换为其他字体
# 设置绘制像素值的间隔(每隔多少个像素绘制一次)
interval = 10
# 合并像素值的范围(以此范围内的像素值取平均值并绘制)
merge_range = 5
# 在图像上绘制像素值
for y in range(image.height):
for x in range(image.width):
if x % interval == 0 and y % interval == 0:
# 计算合并范围内像素的平均值
total= 0
count = 0
for i in range(-merge_range, merge_range + 1):
for j in range(-merge_range, merge_range + 1):
nx, ny = x + i, y + j
if 0 <= nx < image.width and 0 <= ny < image.height:
pixel = pixels[ny * image.width + nx]
total += pixel[0]
count += 1
# 计算平均值
if count > 0:
avg = total // count
if avg == 0:
continue
pixel_str = str(avg) # 格式化平均像素值
draw.text((x, y), pixel_str, fill=(255, 0, 0), font=font) # 在图像上绘制文本,使用黑色文本颜色
output_path = "output_image.jpg" # 保存的图片路径
image.save(output_path, "JPEG")
效果图如下:
如此便将像素值打印在图片上了。
四、总结
在maskID中,如果调用
utils.lblsave(out_file, lbl)
里面的核心代码是:
def lblsave(filename, lbl):
import imgviz
if osp.splitext(filename)[1] != ".png":
filename += ".png"
# Assume label ranses [-1, 254] for int32,
# and [0, 255] for uint8 as VOC.
if lbl.min() >= -1 and lbl.max() < 255:
lbl_pil = PIL.Image.fromarray(lbl.astype(np.uint8), mode="P")
#增加了此处代码
colormap = imgviz.label_colormap()
lbl_pil.putpalette(colormap.flatten())
lbl_pil.save(filename)
else:
raise ValueError(
"[%s] Cannot save the pixel-wise class label as PNG. "
"Please consider using the .npy format." % filename
)
其结果为:
此时将像素打印在图片上结果是:
AnyLabeling标定及转化成labelmaskID的更多相关文章
- [zt]摄像机标定(Camera calibration)笔记
http://www.cnblogs.com/mfryf/archive/2012/03/31/2426324.html 一 作用建立3D到2D的映射关系,一旦标定后,对于一个摄像机内部参数K(光心焦 ...
- 直接线性变换解法(DLT)用于标定相机
直接线性变换法是建立像点坐标和相应物点物方空间坐标之间直接的线性关系的算法.特点:不需要内外方位元素:适合于非量测相机:满足中.低精度的测量任务:可以标定单个相机. 1 各坐标系之间的关系推导直接线性 ...
- PPT转化成Image、PPTX、XPS、EMF
最近工作经常用到演示文稿,接触到了一款不错的免费软件—Free Spire.Presentation.使用之后发现这款软件非常轻巧,功能还挺齐全.这款软件的转化功能也是非常不错的,平时遇到的各种转换难 ...
- DSO之光度标定
光度标定(Photometric Camera Calibration)是DSO(Direct Sparse Odometry)论文中比较特别的一部分.常规的vSLAM不太考虑光度标定的问题.比如基于 ...
- 相机标定简介与MatLab相机标定工具箱的使用(未涉及原理公式推导)
相机标定 一.相机标定的目的 确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,建立摄像机成像的几何模型,这些几何模型参数就是摄像机参数. 二.通用摄像机模型 世界坐标系.摄像机坐标 ...
- .net 将List序列化成Json字符串
将List类型转化为Json,是我们平常开发时最常见的了.在使用中,有很多种方法,也可以使用. 第一种 第三方组件:Newtonsoft.Json.dll //转化成Json Newtonsoft.J ...
- LL谱面分析和难度标定
LL谱面分析和难度标定 先介绍一下LL谱面的存储方式:TimeLine序列(简称TL序列),TL序列中的每一个元素(即音符)可以由一个C语言中的结构体来表示: struct note{ int lin ...
- [转]opencv3.0 鱼眼相机标定
[原文转自]:http://blog.csdn.net/qq_15947787/article/details/51441031 前两天发表的时候没注意,代码出了点错误,所以修改了一下,重新发上来. ...
- 机器人操作臂运动学入门一--D-H参数标定
最近重新学习机器人方面的知识,想到一年以前在学校选修<机器人学技术基础>这门课的时候,老师虽然讲机器人的各个方面的知识都讲到了,但只是浮光绿影的的提到,并没有真正讲到深处,我的理解也没有更 ...
- 【图像】Matlab图像标定工具箱
参考教程: Matlab工具箱教程 http://www.vision.caltech.edu/bouguetj/calib_doc/ 摄像机模型 http://oliver.zheng.blog ...
随机推荐
- .NET Core 程序实现 Windows 系统 Development、Staging、Production 三种环境的无感部署
〇.前言 日常开发中,程序的环境切换是相当频繁的了,如果不同环境中的某些参数不同,那就需要每次编辑之前手动进行修改,比较麻烦,效率低下. 本文将以 .NET Core WebAPI 项目的配置方法为例 ...
- Docker 镜像命令
Docker 镜像命令 1.Docker images--列出本地镜像 命令:docker images [OPTIONS] [REPOSITORY[:TAG]] 选项 -a :列出本地所有的镜像(含 ...
- C++面试八股文:static和const的关键字有哪些用法?
某日二师兄参加XXX科技公司的C++工程师开发岗位第7面: 面试官:C++中,static和const的关键字有哪些用法? 二师兄:satic关键字主要用在以下三个方面:1.用在全局作用域,修饰的变量 ...
- flutter 的 in_app_web_view实现下载功能
flutter与前端交互,利用in_app_web_view实现下载功能: 首先下载库,终端输入 flutter pub add flutter_inappwebview 之后导出 import 'p ...
- Godot 4.0 遮罩一个2D物体,使其部分显示
本文针对Godot 4.0. 我也查到了Godot 3.5如何实现遮罩,见这个链接 https://ask.godotengine.org/3031/how-do-i-mask-a-sprite 由于 ...
- vue-router之hash与history,以及nginx配置
本篇讲解前端项目的路由模式(以vue-router为例),以及history模式下的项目部署问题. vue-router的路由模式可以通过指定mode属性值控制,可选值:"hash" ...
- Linux系统运维之Web服务器Nginx安装
一.介绍 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.本文先整理web服务器内容. 二.环境及软件版本 操作 ...
- PostgreSQL 12 文档: 部分 II. SQL 语言
部分 II. SQL 语言 这部份描述在PostgreSQL中SQL语言的使用.我们从描述SQL的一般语法开始,然后解释如何创建保存数据的结构.如何填充数据库以及如何查询它.中间的部分列出了在SQL命 ...
- 我开源了团队内部基于SpringBoot Web快速开发的API脚手架stater
我们现在使用SpringBoot 做Web 开发已经比之前SprngMvc 那一套强大很多了. 但是 用SpringBoot Web 做API 开发还是不够简洁有一些. 每次Web API常用功能都需 ...
- 10/29/2017_C语言_三道题
1. 用标准C编程:找出整形数字1-100之间的素数,并打印出来.(素数:除了1和自己本身可以被整除.) 2. 用标准C编程:有两个整形变量m.n,求出这两个数的最小公倍数. 3. 用标准C编程:输出 ...