EISeg(Efficient Interactive Segmentation)是基于飞桨开发的一个高效智能的交互式分割标注软件。它涵盖了通用、人像、遥感、医疗、视频等不同方向的高质量交互式分割模型。另外,将EISeg获取到的标注应用到PaddleSeg提供的其他分割模型进行训练,便可得到定制化场景的高精度模型,打通分割任务从数据标注到模型训练及预测的全流程。
Windows上安装EISeg:
1.PaddleSeg在windows上的配置参考:https://blog.csdn.net/fengbingchun/article/details/131344901
2.在已安装PaddleSeg的基础上进行安装,执行如下命令:
pip install eiseg
安装完后,在Anaconda Powershell Prompt中输入eiseg即可运行软件,软件界面如下图所示:
EISeg的使用,打开软件界面后,以人像分隔为例:
1.从https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.8/EISeg/docs/image.md 下载高精度模型static_hrnet18_ocr64_human.zip,解压缩;
2.模型参数加载:文件 --> 加载模型参数:选择static_hrnet18_ocr64_human.pdiparams,
处理OMP Error: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized. Hint This means that multiple copies of the OpenMP runtime have been linked into the program.
解决方法:将Anaconda3/envs/PaddleSeg/Library/bin目录下的libiomp5md.dll重命名或删除
3.图像加载:文件 --> 打开图像:选择图像; 也可打开图像文件夹:文件 --> 打开文件夹:选择文件夹
4.添加标签:点击界面"添加标签"按钮,新建标签,标签分为4列,分别对应像素值、说明、颜色和删除。可点击"标注",导出标签列表、也可载入标签列表和清空标签列表。
5.开始标注:标注首先进入交互式分割模式。鼠标左键代表正点击,表示所选择的前景部分;鼠标右键代表负点击,为用户选定的背景区域。用户可以通过正负点击操作来选择感兴趣的区域,直到满意为止。
交互完成后使用Space(空格)完成交互标注,此时出现多边形边界,进入多边形标注模式。多边形可以删除,通过backspace键。使用鼠标左键点击锚点可以进行拖动。鼠标左键双击锚点可以删除锚点。双击两点之间的边则可在此边添加一个锚点。
6.自动保存设置(文件 --> 自动保存):在使用中可以将自动保存设置上,设定好文件夹即可,这样在使用时切换图像会自动将完成标注的图像进行保存。
标注结果如下图所示:测试图来自于网络,左图为原图,右图为分隔后的结果
分隔后的结果并没有透明图,生成透明图的代码如下所示:image_generic_operations.py
import os
import sys
import cv2
from inspect import currentframe, getframeinfo
import argparse
import numpy as np
def get_image_list(path, image_suffix):
image_list = []
for x in os.listdir(path):
if x.endswith(image_suffix):
image_list.append(path+"/"+x)
return image_list
def get_image_name(image_name):
pos = image_name.rfind("/")
image_name = image_name[pos+1:]
return image_name
def get_image_name2(image_name, image_suffix):
name = get_image_name(image_name)
#name = name[:len(image_suffix)-1] # sometimes, the fetched name is incorrect, for example: 10-1.JPG
pos =name.rfind(".")
return name[:pos]
def image_segment(image_list, image_suffix, path2, image_suffix2, degrees, dst_width, dst_height, result_path):
print("image segment ...")
os.makedirs(result_path, exist_ok=True)
for name in image_list:
print(f"\t{name}")
image_name = get_image_name2(name, image_suffix)
#print(f"image name:{image_name}"); sys.exit(1)
name2 = path2 + "/" + image_name + image_suffix2
print(f"\t{name2}")
bgr = cv2.imread(name, -1)
h1, w1, c1 = bgr.shape
mask = cv2.imread(name2, -1)
h2, w2 = mask.shape
if c1 != 3:
raise Exception("Unsupported number of image channels: {}, {}; Error Line: {}".format(c1, c2, getframeinfo(currentframe()).lineno))
if h1 != h2 or w1 != w2: # rotate
if h1 != w2 or w1 != h2:
raise Exception("Inconsistent image size: {},{}:{},{}; Error Line: {}".format(h1, w1, h2, w2, getframeinfo(currentframe()).lineno))
if degrees == 90:
rotate_code = cv2.ROTATE_90_CLOCKWISE
elif degrees == 180:
rotate_code = cv2.ROTATE_180
elif degrees == 270:
rotate_code = cv2.ROTATE_90_COUNTERCLOCKWISE
else:
raise Exception("Unsupported rotat degrees: {}, it only supports: clockwise 90, 180, 270; Error Line: {}".format(degrees, getframeinfo(currentframe()).lineno))
bgr = cv2.rotate(bgr, rotateCode=rotate_code)
bgra = cv2.cvtColor(bgr, cv2.COLOR_BGR2BGRA)
if dst_width != 0 or dst_height != 0: # resize
if h1 > dst_height and w1 > dst_width:
interpolation = cv2.INTER_AREA
else:
interpolation = cv2.INTER_CUBIC
bgra = cv2.resize(bgra, (dst_width, dst_height), interpolation=interpolation)
mask = cv2.resize(mask, (dst_width, dst_height), interpolation=interpolation)
#h3, w3, c3 = bgra.shape
#result = np.zeros((h3, w3, c3), dtype="uint8")
result = cv2.bitwise_and(bgra, bgra, mask=mask)
cv2.imwrite(result_path+"/"+image_name+".png", result)
def parse_args():
parser = argparse.ArgumentParser(description="image generic operations", add_help=True)
parser.add_argument("--image_src_path", required=True, type=str, help="the path of the image to be operated, for example: ../../test_images")
parser.add_argument("--image_src_path2", default="", type=str, help="the path of the image to be operated, for example: ../../test_images")
parser.add_argument("--operation", required=True, type=str, choices=["rotate", "resize", "segment", "border"], help="specifies the operation to take on the image")
parser.add_argument("--image_dst_path", required=True, type=str, help="the path where the resulting image is saved, for example: ../../test_images/result")
parser.add_argument("--degrees", default=90, type=int, choices=[90, 180, 270], help="the degrees by which the image is rotated clockwise")
parser.add_argument("--width", default=0, type=int, help="the width of the image after scaling")
parser.add_argument("--height", default=0, type=int, help="the height of the image after scaling")
parser.add_argument("--image_suffix", default=".png", type=str, help="the suffix of the processed image")
parser.add_argument("--image_suffix2", default=".png", type=str, help="the suffix of the processed image")
parser.add_argument("--value", default="", type=str, help="pixel value, order: b g r a, the length can be 1 2 3 4, for example: 128 128 255 255")
args = parser.parse_args()
return args
if __name__ == "__main__":
args = parse_args()
if args.value != "":
value = []
for v in args.value.split():
value.append(int(v))
image_list = get_image_list(args.image_src_path, args.image_suffix)
if len(image_list) == 0:
print(f"Warning: no image, directory: {args.image_src_path}")
sys.exit(1)
if args.operation == "segment":
image_segment(image_list, args.image_suffix, args.image_src_path2, args.image_suffix2, args.degrees, args.width, args.height, args.image_dst_path)
print("test finish")
GitHub:https://github.com/fengbingchun/OpenCV_Test