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 ...
随机推荐
- Python3.9安装
一.安装python3.9 链接:https://pan.baidu.com/s/1mDkgKt2KSoMrKVxesb76Pg?pwd=ma4n 提取码:ma4n --来自百度网盘超级会员V4的分享 ...
- 深入探究for...range语句
1. 引言 在Go语言中,我们经常需要对数据集合进行遍历操作.对于数组来说,使用for语句可以很方便地完成遍历.然而,当我们面对其他数据类型,如map.string 和 channel 时,使用普通的 ...
- 驱动开发:内核LoadLibrary实现DLL注入
远程线程注入是最常用的一种注入技术,在应用层注入是通过CreateRemoteThread这个函数实现的,该函数通过创建线程并调用 LoadLibrary 动态载入指定的DLL来实现注入,而在内核层同 ...
- 【园子资深博主直播】 冰蓝老师《ChatGPT 初探》
AI对经济增长.经济周期.经济形态.社会就业都有着非常巨大的影响,ChatGPT4.0发布后,燃起了我们每一个开发人的激情和恐惧,但各路自媒体信息杂乱无序,缺少非常系统性的ChatGPT原理解读. 此 ...
- 【了解LLM】——LoRA
本文地址:https://www.cnblogs.com/wanger-sjtu/p/17470327.html 论文链接:link code: github 什么是LoRA LoRA,英文全称Low ...
- tvm-多线程代码生成和运行
本文链接 https://www.cnblogs.com/wanger-sjtu/p/16818492.html 调用链 tvm搜索算子在需要多线程运行的算子,是在codegen阶段时插入TVMBac ...
- SQL SERVER 基础使用技巧
1 .编写目的 本人总结了一些实际使用中常常因为疏忽大意而出现各种意想不到的问题,本文档总结相关经验(有些并未得到验证),便于交流学习. 1 基础 1.1 char.varchar.nchar.nva ...
- 介绍Vue router的history模式以及如何配置history模式
引言 Vue router给我们提供了两种路由模式,分别是hash模式和history模式.其中默认是使用hash模式,即URL中带有一个#符号,但是处于业务或个人喜爱的差别,Vue router也提 ...
- 2023年最具威胁的25种安全漏洞(CWE TOP 25)
摘要: CWE Top 25 是通过分析美国国家漏洞数据库(NVD)中的公共漏洞数据来计算的,以获取前两个日历年 CWE 弱点的根本原因映射. 本文分享自华为云社区<2023年最具威胁的25种安 ...
- 个人博客迁移到托管平台Netlify
Netlify是一家国外的静态网站的托管平台,提供免费的https,自动化部署和升级,可以监控GitHub.GitLab或者Bitbucket做到自动更新发布. 个人体会访问速度不是很理想,不如部署在 ...