Commit f8772570 authored by bailuo's avatar bailuo
Browse files

init

parents
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrack
"""
The MOT-only setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrack):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_det_convnext_tiny_800x1280"
self.mot_only = True
self.samples_per_epoch = 100000
self.mot_weight = 1
self.mhs = False
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrackMask
"""
The MOT-only setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrackMask):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_track_tiny_mot_only"
self.mot_only = True
self.samples_per_epoch = 100000
self.mot_weight = 1
self.mhs = False
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrack
"""
The Real-Time setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrack):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_det_convnext_tiny_800x1280"
self.input_size = (640, 1024)
self.test_size = (640, 1024)
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrackMask
"""
The Real-Time setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrackMask):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_track_tiny_rt"
self.input_size = (640, 1024)
self.test_size = (640, 1024)
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrack
"""
The SOT-only setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrack):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_det_convnext_tiny_800x1280"
self.sot_only = True
self.samples_per_epoch = 100000
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrack
"""
The SOT-only setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrack):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_det_convnext_tiny_800x1280"
self.sot_only = True
self.samples_per_epoch = 10000
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrack
"""
The SOT-only setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrack):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_det_convnext_tiny_800x1280"
self.sot_only = True
self.samples_per_epoch = 10000
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrack
"""
The SOT-only setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrack):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_track_tiny_sot_only_dcu" #"unicorn_det_convnext_tiny_800x1280"
self.sot_only = True
self.samples_per_epoch = 100
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2022 ByteDance. All Rights Reserved.
import os
from unicorn.exp import ExpTrackMask
"""
The VOS-only setting used in the ablation
We load weights pretrained on COCO with input resolution of 800x1280
"""
class Exp(ExpTrackMask):
def __init__(self):
super(Exp, self).__init__()
self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
self.pretrain_name = "unicorn_track_tiny_sot_only"
self.sot_only = True
self.samples_per_epoch = 100000
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# private
.idea/
.vscode/
MIT License
Copyright (c) 2021 Pang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# -*- coding: utf-8 -*-
import argparse
import os
import pickle
import warnings
import cv2
import numpy as np
import yaml
from joblib import delayed, Parallel
from prettytable import PrettyTable as ptable
from metrics import f_boundary, jaccard
my_parser = argparse.ArgumentParser(
description="The code is based on `https://github.com/davisvideochallenge/davis`",
epilog="Enjoy the program! :)",
allow_abbrev=False,
)
my_parser.version = "1.0.0"
my_parser.add_argument("-v", "--version", action="version")
my_parser.add_argument(
"--name_list_path",
default="/home/lart/Datasets/VideoSeg/DAVIS-2017-trainval-480p/DAVIS/ImageSets/2016/val.txt",
type=str,
help="the information file of DAVIS 2016 Dataset",
)
my_parser.add_argument(
"--mask_root",
default="/home/lart/Datasets/VideoSeg/DAVIS-2017-trainval-480p/DAVIS/Annotations/480p",
type=str,
help="the annotation folder of DAVIS 2016 Dataset",
)
my_parser.add_argument(
"--pred_path",
default="/home/lart/coding/USVideoSeg/output/HDFNet_WSGNR50_V1/pre",
type=str,
help="the prediction folder of the method",
)
my_parser.add_argument(
"--save_path",
default="./output/HDFNet_WSGNR50_V1.pkl",
type=str,
help="the file path for saving evaluation results",
)
my_parser.add_argument(
"--ignore_head",
default="True",
choices=["True", "False"],
type=str,
help="whether to ignore the first frame during evaluation",
)
my_parser.add_argument(
"--ignore_tail",
default="True",
choices=["True", "False"],
type=str,
help="whether to ignore the last frame during evaluation",
)
my_parser.add_argument(
"--n_jobs",
default=2,
type=int,
help="the number of jobs for parallel evaluating the performance",
)
def print_all_keys(data_dict, level: int = 0):
level += 1
if isinstance(data_dict, dict):
for k, v in data_dict.items():
print(f" {'|=' * level}>> {k}")
print_all_keys(v, level=level)
elif isinstance(data_dict, (list, tuple)):
for item in data_dict:
print_all_keys(item, level=level)
else:
return
def get_eval_video_name_list_from_yml(path: str, data_set: str) -> list:
with open(path, encoding="utf-8", mode="r") as f_stream:
data_info_dict = yaml.load(f_stream, Loader=yaml.FullLoader)
eval_video_name_list = []
for video_dict in data_info_dict["sequences"]:
if video_dict["set"] == data_set:
eval_video_name_list.append(video_dict["name"])
return eval_video_name_list
def get_mean_recall_decay_for_video(per_frame_values):
"""Compute mean,recall and decay from per-frame evaluation.
Arguments:
per_frame_values (ndarray): per-frame evaluation
Returns:
M,O,D (float,float,float):
return evaluation statistics: mean,recall,decay.
"""
# strip off nan values
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=RuntimeWarning)
M = np.nanmean(per_frame_values)
O = np.nanmean(per_frame_values[1:-1] > 0.5)
# Compute decay as implemented in Matlab
per_frame_values = per_frame_values[1:-1] # Remove first frame
N_bins = 4
ids = np.round(np.linspace(1, len(per_frame_values), N_bins + 1) + 1e-10) - 1
ids = ids.astype(np.uint8)
D_bins = [per_frame_values[ids[i] : ids[i + 1] + 1] for i in range(0, 4)]
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=RuntimeWarning)
D = np.nanmean(D_bins[0]) - np.nanmean(D_bins[3])
return M, O, D
def _read_and_eval_file(mask_video_path: str, pred_video_path: str, frame_name: str):
frame_mask_path = os.path.join(mask_video_path, frame_name)
frame_pred_path = os.path.join(pred_video_path, frame_name)
frame_mask = cv2.imread(frame_mask_path, 0) # h, w
frame_pred = cv2.imread(frame_pred_path, 0)
binary_frame_mask = (frame_mask > 0).astype(np.float32)
binary_frame_pred = (frame_pred > 0).astype(np.float32)
J_score = jaccard.db_eval_iou(
annotation=binary_frame_mask, segmentation=binary_frame_pred
)
F_score = f_boundary.db_eval_boundary(
foreground_mask=binary_frame_pred, gt_mask=binary_frame_mask
)
return J_score, F_score
def _eval_video_sequence(
method_pre_path: str,
mask_data_root: str,
video_name: str,
ignore_head: bool,
ignore_tail: bool,
):
print(f"processing {video_name}...")
mask_video_path = os.path.join(mask_data_root, video_name)
pred_video_path = os.path.join(method_pre_path, video_name)
mask_frame_path_list = sorted(os.listdir(mask_video_path))
if ignore_head:
mask_frame_path_list = mask_frame_path_list[1:]
if ignore_tail:
mask_frame_path_list = mask_frame_path_list[:-1]
frame_score_list = [
_read_and_eval_file(
mask_video_path=mask_video_path,
pred_video_path=pred_video_path,
frame_name=frame_name,
)
for frame_name in mask_frame_path_list
]
if ignore_head:
frame_score_list = [[np.nan, np.nan]] + frame_score_list
if ignore_tail:
frame_score_list += [[np.nan, np.nan]]
frame_score_array = np.asarray(frame_score_list)
M, O, D = zip(
*[
get_mean_recall_decay_for_video(frame_score_array[:, i])
for i in range(frame_score_array.shape[1])
]
)
return {
video_name: {
"pre_frame": frame_score_array,
"mean": np.asarray(M),
"recall": np.asarray(O),
"decay": np.asarray(D),
}
}
def get_method_score_dict(
method_pre_path: str,
mask_data_root: str,
video_name_list: list,
ignore_head: bool = True,
ignore_tail: bool = True,
n_jobs: int = 2,
):
video_score_list = Parallel(n_jobs=n_jobs)(
delayed(_eval_video_sequence)(
method_pre_path=method_pre_path,
mask_data_root=mask_data_root,
video_name=video_name,
ignore_head=ignore_head,
ignore_tail=ignore_tail,
)
for video_name in video_name_list
)
video_score_dict = {
list(kv.keys())[0]: list(kv.values())[0] for kv in video_score_list
}
return video_score_dict
def get_method_average_score_dict(method_score_dict: dict):
# average_score_dict = {"total": 0, "mean": 0, "recall": 0, "decay": 0}
average_score_dict = {"Average": {"mean": 0, "recall": 0, "decay": 0}}
for k, v in method_score_dict.items():
# average_score_item = np.nanmean(v["pre_frame"], axis=0)
# average_score_dict[k] = average_score_item
average_score_dict[k] = {
"mean": v["mean"],
"recall": v["recall"],
"decay": v["decay"],
}
# average_score_dict["total"] += average_score_item
average_score_dict["Average"]["mean"] += v["mean"]
average_score_dict["Average"]["recall"] += v["recall"]
average_score_dict["Average"]["decay"] += v["decay"]
# average_score_dict['Average']["total"] /= len(method_score_dict)
average_score_dict["Average"]["mean"] /= len(method_score_dict)
average_score_dict["Average"]["recall"] /= len(method_score_dict)
average_score_dict["Average"]["decay"] /= len(method_score_dict)
return average_score_dict
def save_to_file(data, save_path: str):
with open(save_path, mode="wb") as f:
pickle.dump(data, f)
def read_from_file(file_path: str):
with open(file_path, mode="rb") as f:
data = pickle.load(f)
return data
def convert_data_dict_to_table(data_dict: dict, video_name_list: list):
table = ptable(["Video", "J(M)", "J(O)", "J(D)", "F(M)", "F(O)", "F(D)"])
for video_name in video_name_list:
table.add_row(
[video_name]
+ [
f"{data_dict[video_name][x][y]: .3f}"
for y in range(2)
for x in ["mean", "recall", "decay"]
]
)
return "\n" + str(table) + "\n"
def get_eval_video_name_list_from_txt(path: str) -> list:
name_list = []
with open(path, encoding="utf-8", mode="r") as f:
for line in f:
line = line.strip()
if line:
name_list.append(line)
return name_list
def eval_method_from_data(
method_pre_path: str,
mask_data_root: str,
ignore_head: bool,
ignore_tail: bool,
name_list_path: str,
save_path: str = "./output/average.pkl",
n_jobs: int = 2,
):
"""
根据给定方法的预测结果来评估在davis 2016上的性能
:param method_pre_path: 模型预测结果,该路径下包含各个视频预测的结果,与Annotations文件夹布局一致
:param mask_data_root: davis 2016的Annotations文件夹
:param ignore_head: 评估时是否忽略第一帧
:param ignore_tail: 评估时是否忽略最后一帧
:param name_list_path: davis 2016数据集的信息文件(db_info.yml)或者是2017中提供的 2016/val.txt
:param save_path: 保存导出的模型评估结果的文件路径
:param n_jobs: 多进程评估时使用的进程数
"""
if name_list_path.endswith(".yml") or name_list_path.endswith(".yaml"):
# read yaml and get the list that will be used to eval the model
eval_video_name_list = get_eval_video_name_list_from_yml(
path=name_list_path, data_set="test"
)
elif name_list_path.endswith(".txt"):
eval_video_name_list = get_eval_video_name_list_from_txt(path=name_list_path)
else:
raise ValueError
# tervese the each video
method_score_dict = get_method_score_dict(
method_pre_path=method_pre_path,
mask_data_root=mask_data_root,
video_name_list=eval_video_name_list,
ignore_head=ignore_head,
ignore_tail=ignore_tail,
n_jobs=n_jobs,
)
# get the average score
average_score_dict = get_method_average_score_dict(
method_score_dict=method_score_dict
)
if save_path != None:
save_to_file(data=average_score_dict, save_path=save_path)
# show the results
eval_video_name_list += ["Average"]
table_str = convert_data_dict_to_table(
data_dict=average_score_dict, video_name_list=eval_video_name_list
)
print(table_str)
def show_results_from_data_file(file_path: str = "./output/average.pkl"):
"""
展示给定的模型评估结果文件中包含的模型的结果
:param file_path: 保存导出的模型评估结果的文件路径
"""
average_score_dict = read_from_file(file_path=file_path)
eval_video_name_list = list(average_score_dict.keys())
eval_video_name_list[0], eval_video_name_list[-1] = (
eval_video_name_list[-1],
eval_video_name_list[0],
)
# show the results
table_str = convert_data_dict_to_table(
data_dict=average_score_dict, video_name_list=eval_video_name_list
)
print(table_str)
if __name__ == "__main__":
args = my_parser.parse_args()
eval_method_from_data(
method_pre_path=args.pred_path,
mask_data_root=args.mask_root,
ignore_tail=True if args.ignore_tail == "True" else False,
ignore_head=True if args.ignore_head == "True" else False,
name_list_path=args.name_list_path,
save_path=args.save_path,
n_jobs=args.n_jobs,
)
# show_results_from_data_file("./output/dybinary_ave.pkl")
# show_results_from_data_file("./output/HDFNet_WSGNR50_V1.pkl")
# show_results_from_data_file("./output/matnet_ave.pkl")
# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------
# A Benchmark Dataset and Evaluation Methodology for Video Object Segmentation
# -----------------------------------------------------------------------------
# Copyright (c) 2016 Federico Perazzi
# Licensed under the BSD License [see LICENSE for details]
# Written by Federico Perazzi
# ----------------------------------------------------------------------------
from math import floor
import numpy as np
from skimage.morphology import binary_dilation, disk
""" Utilities for computing, reading and saving benchmark evaluation."""
def db_eval_boundary(foreground_mask, gt_mask, bound_th=0.008):
"""
Compute mean,recall and decay from per-frame evaluation.
Calculates precision/recall for boundaries between foreground_mask and
gt_mask using morphological operators to speed it up.
Arguments:
foreground_mask (ndarray): binary segmentation image.
gt_mask (ndarray): binary annotated image.
Returns:
F (float): boundaries F-measure
P (float): boundaries precision
R (float): boundaries recall
"""
assert np.atleast_3d(foreground_mask).shape[2] == 1
bound_pix = (
bound_th if bound_th >= 1 else np.ceil(bound_th * np.linalg.norm(foreground_mask.shape))
)
# Get the pixel boundaries of both masks
fg_boundary = seg2bmap(foreground_mask)
gt_boundary = seg2bmap(gt_mask)
fg_dil = binary_dilation(fg_boundary, disk(bound_pix))
gt_dil = binary_dilation(gt_boundary, disk(bound_pix))
# Get the intersection
gt_match = gt_boundary * fg_dil
fg_match = fg_boundary * gt_dil
# Area of the intersection
n_fg = np.sum(fg_boundary)
n_gt = np.sum(gt_boundary)
# % Compute precision and recall
if n_fg == 0 and n_gt > 0:
precision = 1
recall = 0
elif n_fg > 0 and n_gt == 0:
precision = 0
recall = 1
elif n_fg == 0 and n_gt == 0:
precision = 1
recall = 1
else:
precision = np.sum(fg_match) / float(n_fg)
recall = np.sum(gt_match) / float(n_gt)
# Compute F measure
if precision + recall == 0:
F = 0
else:
F = 2 * precision * recall / (precision + recall)
return F
def seg2bmap(seg, width=None, height=None):
"""
From a segmentation, compute a binary boundary map with 1 pixel wide
boundaries. The boundary pixels are offset by 1/2 pixel towards the
origin from the actual segment boundary.
Arguments:
seg : Segments labeled from 1..k.
width : Width of desired bmap <= seg.shape[1]
height : Height of desired bmap <= seg.shape[0]
Returns:
bmap (ndarray): Binary boundary map.
David Martin <dmartin@eecs.berkeley.edu>
January 2003
"""
seg = seg.astype(np.bool)
seg[seg > 0] = 1
assert np.atleast_3d(seg).shape[2] == 1
width = seg.shape[1] if width is None else width
height = seg.shape[0] if height is None else height
h, w = seg.shape[:2]
ar1 = float(width) / float(height)
ar2 = float(w) / float(h)
assert not (
width > w | height > h | abs(ar1 - ar2) > 0.01
), "Can" "t convert %dx%d seg to %dx%d bmap." % (
w,
h,
width,
height,
)
e = np.zeros_like(seg)
s = np.zeros_like(seg)
se = np.zeros_like(seg)
e[:, :-1] = seg[:, 1:]
s[:-1, :] = seg[1:, :]
se[:-1, :-1] = seg[1:, 1:]
b = seg ^ e | seg ^ s | seg ^ se
b[-1, :] = seg[-1, :] ^ e[-1, :]
b[:, -1] = seg[:, -1] ^ s[:, -1]
b[-1, -1] = 0
if w == width and h == height:
bmap = b
else:
bmap = np.zeros((height, width))
for x in range(w):
for y in range(h):
if b[y, x]:
j = 1 + floor((y - 1) + height / h)
i = 1 + floor((x - 1) + width / h)
bmap[j, i] = 1
return bmap
# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------
# A Benchmark Dataset and Evaluation Methodology for Video Object Segmentation
# -----------------------------------------------------------------------------
# Copyright (c) 2016 Federico Perazzi
# Licensed under the BSD License [see LICENSE for details]
# Written by Federico Perazzi
# ----------------------------------------------------------------------------
""" Compute Jaccard Index. """
import numpy as np
def db_eval_iou(annotation, segmentation):
"""Compute region similarity as the Jaccard Index.
Arguments:
annotation (ndarray): binary annotation map.
segmentation (ndarray): binary segmentation map.
Return:
jaccard (float): region similarity
"""
annotation = annotation.astype(np.bool)
segmentation = segmentation.astype(np.bool)
if np.isclose(np.sum(annotation), 0) and np.isclose(np.sum(segmentation), 0):
return 1
else:
return np.sum((annotation & segmentation)) / np.sum(
(annotation | segmentation), dtype=np.float32
)
# 基于python的视频目标分割测评工具箱
A Python-based video object segmentation evaluation toolbox.
## 特性
* 针对**DAVIS 2016无监督视频目标分割**任务,提供`"J(M)", "J(O)", "J(D)", "F(M)", "F(O)", "F(D)"`等指标的评估(代码借鉴自davis官方的代码,建议使用前验证下)
- 导出对指定的模型预测结果的评估结果
- 表格化展示不同视频上模型预测的性能
## 依赖项
- `joblib`: 多进程加速计算
- `prettytable`: 输出好看的表格
## 使用方法
### DAVIS 2016无监督视频目标分割任务
1. `python eval_unvos_method.py --help`
2. 配置相关项后执行代码
python3 eval.py --name_list_path /opt/tiger/omnitrack/data/DAVIS/ImageSets/2016/val.txt --mask_root /opt/tiger/omnitrack/data/DAVIS/Annotations/480p --pred_path /opt/tiger/omnitrack/test/vos_baseline_tiny_10f_stm_DAVIS_16val --save_path /opt/tiger/omnitrack/result.pkl
\ No newline at end of file
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
docs/site/
/site
# mypy
.mypy_cache/
# pytest
.pytest_cache
# Pylint
.pylintrc
# PyCharm
.idea/
.DS_Store
# Generated C code
_mask.c
BSD 3-Clause License
Copyright (c) 2020, DAVIS: Densely Annotated VIdeo Segmentation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# DAVIS 2017 Semi-supervised and Unsupervised evaluation package
This package is used to evaluate semi-supervised and unsupervised video multi-object segmentation models for the <a href="https://davischallenge.org/davis2017/code.html" target="_blank">DAVIS 2017</a> dataset.
This tool is also used to evaluate the submissions in the Codalab site for the <a href="https://competitions.codalab.org/competitions/20516" target="_blank">Semi-supervised DAVIS Challenge</a> and the <a href="https://competitions.codalab.org/competitions/20515" target="_blank">Unsupervised DAVIS Challenge</a>
### Installation
```bash
# Download the code
git clone https://github.com/davisvideochallenge/davis2017-evaluation.git && cd davis2017-evaluation
# Install it - Python 3.6 or higher required
python setup.py install
```
If you don't want to specify the DAVIS path every time, you can modify the default value in the variable `default_davis_path` in `evaluation_method.py`(the following examples assume that you have set it).
Otherwise, you can specify the path in every call using using the flag `--davis_path /path/to/DAVIS` when calling `evaluation_method.py`.
Once the evaluation has finished, two different CSV files will be generated inside the folder with the results:
- `global_results-SUBSET.csv` contains the overall results for a certain `SUBSET`.
- `per-sequence_results-SUBSET.csv` contain the per sequence results for a certain `SUBSET`.
If a folder that contains the previous files is evaluated again, the results will be read from the CSV files instead of recomputing them.
## Evaluate DAVIS 2017 Semi-supervised
In order to evaluate your semi-supervised method in DAVIS 2017, execute the following command substituting `results/semi-supervised/osvos` by the folder path that contains your results:
```bash
python evaluation_method.py --task semi-supervised --results_path results/semi-supervised/osvos
```
The semi-supervised results have been generated using [OSVOS](https://github.com/kmaninis/OSVOS-caffe).
## Evaluate DAVIS 2017 Unsupervised
In order to evaluate your unsupervised method in DAVIS 2017, execute the following command substituting `results/unsupervised/rvos` by the folder path that contains your results:
```bash
python evaluation_method.py --task unsupervised --results_path results/unsupervised/rvos
```
The unsupervised results example have been generated using [RVOS](https://github.com/imatge-upc/rvos).
## Evaluation running in Codalab
In case you would like to know which is the evaluation script that is running in the Codalab servers, check the `evaluation_codalab.py` script.
This package runs in the following docker image: [scaelles/codalab:anaconda3-2018.12](https://cloud.docker.com/u/scaelles/repository/docker/scaelles/codalab)
## Citation
Please cite both papers in your publications if DAVIS or this code helps your research.
```latex
@article{Caelles_arXiv_2019,
author = {Sergi Caelles and Jordi Pont-Tuset and Federico Perazzi and Alberto Montes and Kevis-Kokitsi Maninis and Luc {Van Gool}},
title = {The 2019 DAVIS Challenge on VOS: Unsupervised Multi-Object Segmentation},
journal = {arXiv},
year = {2019}
}
```
```latex
@article{Pont-Tuset_arXiv_2017,
author = {Jordi Pont-Tuset and Federico Perazzi and Sergi Caelles and Pablo Arbel\'aez and Alexander Sorkine-Hornung and Luc {Van Gool}},
title = {The 2017 DAVIS Challenge on Video Object Segmentation},
journal = {arXiv:1704.00675},
year = {2017}
}
```
from __future__ import absolute_import
__version__ = '0.1.0'
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment