|
|
@ -5,7 +5,7 @@ import sys |
|
|
|
import argparse |
|
|
|
import argparse |
|
|
|
import time |
|
|
|
import time |
|
|
|
|
|
|
|
|
|
|
|
from imagenet_cls_test_alexnet import CaffeModel, DnnCaffeModel |
|
|
|
from imagenet_cls_test_alexnet import CaffeModel, DNNOnnxModel |
|
|
|
try: |
|
|
|
try: |
|
|
|
import cv2 as cv |
|
|
|
import cv2 as cv |
|
|
|
except ImportError: |
|
|
|
except ImportError: |
|
|
@ -58,14 +58,14 @@ class MeanChannelsPreproc: |
|
|
|
pass |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
@staticmethod |
|
|
|
def process(img): |
|
|
|
def process(img, framework): |
|
|
|
image_data = np.array(img).transpose(2, 0, 1).astype(np.float32) |
|
|
|
image_data = None |
|
|
|
mean = np.ones(image_data.shape) |
|
|
|
if framework == "Caffe": |
|
|
|
mean[0] *= 104 |
|
|
|
image_data = cv.dnn.blobFromImage(img, scalefactor=1.0, mean=(123.0, 117.0, 104.0), swapRB=True) |
|
|
|
mean[1] *= 117 |
|
|
|
elif framework == "DNN (ONNX)": |
|
|
|
mean[2] *= 123 |
|
|
|
image_data = cv.dnn.blobFromImage(img, scalefactor=0.019, mean=(123.675, 116.28, 103.53), swapRB=True) |
|
|
|
image_data -= mean |
|
|
|
else: |
|
|
|
image_data = np.expand_dims(image_data, 0) |
|
|
|
raise ValueError("Unknown framework") |
|
|
|
return image_data |
|
|
|
return image_data |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -105,10 +105,10 @@ class PASCALDataFetch(DatasetImageFetch): |
|
|
|
colors = [] |
|
|
|
colors = [] |
|
|
|
i = 0 |
|
|
|
i = 0 |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, img_dir, segm_dir, names_file, segm_cls_colors_file, preproc): |
|
|
|
def __init__(self, img_dir, segm_dir, names_file, segm_cls_colors, preproc): |
|
|
|
self.img_dir = img_dir |
|
|
|
self.img_dir = img_dir |
|
|
|
self.segm_dir = segm_dir |
|
|
|
self.segm_dir = segm_dir |
|
|
|
self.colors = self.read_colors(segm_cls_colors_file) |
|
|
|
self.colors = self.read_colors(segm_cls_colors) |
|
|
|
self.data_prepoc = preproc |
|
|
|
self.data_prepoc = preproc |
|
|
|
self.i = 0 |
|
|
|
self.i = 0 |
|
|
|
|
|
|
|
|
|
|
@ -117,26 +117,30 @@ class PASCALDataFetch(DatasetImageFetch): |
|
|
|
self.names.append(l.rstrip()) |
|
|
|
self.names.append(l.rstrip()) |
|
|
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
@staticmethod |
|
|
|
def read_colors(img_classes_file): |
|
|
|
def read_colors(colors): |
|
|
|
result = [] |
|
|
|
result = [] |
|
|
|
with open(img_classes_file) as f: |
|
|
|
for color in colors: |
|
|
|
for l in f.readlines(): |
|
|
|
result.append(DatasetImageFetch.pix_to_c(color)) |
|
|
|
color = np.array(map(int, l.split()[1:])) |
|
|
|
|
|
|
|
result.append(DatasetImageFetch.pix_to_c(color)) |
|
|
|
|
|
|
|
return result |
|
|
|
return result |
|
|
|
|
|
|
|
|
|
|
|
def __iter__(self): |
|
|
|
def __iter__(self): |
|
|
|
return self |
|
|
|
return self |
|
|
|
|
|
|
|
|
|
|
|
def next(self): |
|
|
|
def __next__(self): |
|
|
|
if self.i < len(self.names): |
|
|
|
if self.i < len(self.names): |
|
|
|
name = self.names[self.i] |
|
|
|
name = self.names[self.i] |
|
|
|
self.i += 1 |
|
|
|
self.i += 1 |
|
|
|
segm_file = self.segm_dir + name + ".png" |
|
|
|
segm_file = self.segm_dir + name + ".png" |
|
|
|
img_file = self.img_dir + name + ".jpg" |
|
|
|
img_file = self.img_dir + name + ".jpg" |
|
|
|
gt = self.color_to_gt(cv.imread(segm_file, cv.IMREAD_COLOR)[:, :, ::-1], self.colors) |
|
|
|
gt = self.color_to_gt(cv.imread(segm_file, cv.IMREAD_COLOR)[:, :, ::-1], self.colors) |
|
|
|
img = self.data_prepoc.process(cv.imread(img_file, cv.IMREAD_COLOR)[:, :, ::-1]) |
|
|
|
img = cv.imread(img_file, cv.IMREAD_COLOR) |
|
|
|
return img, gt |
|
|
|
img_caffe = self.data_prepoc.process(img[:, :, ::-1], "Caffe") |
|
|
|
|
|
|
|
img_dnn = self.data_prepoc.process(img[:, :, ::-1], "DNN (ONNX)") |
|
|
|
|
|
|
|
img_dict = { |
|
|
|
|
|
|
|
"Caffe": img_caffe, |
|
|
|
|
|
|
|
"DNN (ONNX)": img_dnn |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return img_dict, gt |
|
|
|
else: |
|
|
|
else: |
|
|
|
self.i = 0 |
|
|
|
self.i = 0 |
|
|
|
raise StopIteration |
|
|
|
raise StopIteration |
|
|
@ -160,12 +164,13 @@ class SemSegmEvaluation: |
|
|
|
blobs_l_inf_diff = [sys.float_info.min] * len(frameworks) |
|
|
|
blobs_l_inf_diff = [sys.float_info.min] * len(frameworks) |
|
|
|
inference_time = [0.0] * len(frameworks) |
|
|
|
inference_time = [0.0] * len(frameworks) |
|
|
|
|
|
|
|
|
|
|
|
for in_blob, gt in data_fetcher: |
|
|
|
for in_blob_dict, gt in data_fetcher: |
|
|
|
frameworks_out = [] |
|
|
|
frameworks_out = [] |
|
|
|
samples_handled += 1 |
|
|
|
samples_handled += 1 |
|
|
|
for i in range(len(frameworks)): |
|
|
|
for i in range(len(frameworks)): |
|
|
|
start = time.time() |
|
|
|
start = time.time() |
|
|
|
out = frameworks[i].get_output(in_blob) |
|
|
|
framework_name = frameworks[i].get_name() |
|
|
|
|
|
|
|
out = frameworks[i].get_output(in_blob_dict[framework_name]) |
|
|
|
end = time.time() |
|
|
|
end = time.time() |
|
|
|
segm = eval_segm_result(out) |
|
|
|
segm = eval_segm_result(out) |
|
|
|
conf_mats[i] += get_conf_mat(gt, segm[0]) |
|
|
|
conf_mats[i] += get_conf_mat(gt, segm[0]) |
|
|
@ -198,28 +203,53 @@ class SemSegmEvaluation: |
|
|
|
log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':' |
|
|
|
log_str = frameworks[0].get_name() + " vs " + frameworks[i].get_name() + ':' |
|
|
|
print('Final l1 diff', log_str, blobs_l1_diff[i] / blobs_l1_diff_count[i], file=self.log) |
|
|
|
print('Final l1 diff', log_str, blobs_l1_diff[i] / blobs_l1_diff_count[i], file=self.log) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# PASCAL VOC 2012 classes colors |
|
|
|
|
|
|
|
colors_pascal_voc_2012 = [ |
|
|
|
|
|
|
|
[0, 0, 0], |
|
|
|
|
|
|
|
[128, 0, 0], |
|
|
|
|
|
|
|
[0, 128, 0], |
|
|
|
|
|
|
|
[128, 128, 0], |
|
|
|
|
|
|
|
[0, 0, 128], |
|
|
|
|
|
|
|
[128, 0, 128], |
|
|
|
|
|
|
|
[0, 128, 128], |
|
|
|
|
|
|
|
[128, 128, 128], |
|
|
|
|
|
|
|
[64, 0, 0], |
|
|
|
|
|
|
|
[192, 0, 0], |
|
|
|
|
|
|
|
[64, 128, 0], |
|
|
|
|
|
|
|
[192, 128, 0], |
|
|
|
|
|
|
|
[64, 0, 128], |
|
|
|
|
|
|
|
[192, 0, 128], |
|
|
|
|
|
|
|
[64, 128, 128], |
|
|
|
|
|
|
|
[192, 128, 128], |
|
|
|
|
|
|
|
[0, 64, 0], |
|
|
|
|
|
|
|
[128, 64, 0], |
|
|
|
|
|
|
|
[0, 192, 0], |
|
|
|
|
|
|
|
[128, 192, 0], |
|
|
|
|
|
|
|
[0, 64, 128], |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
if __name__ == "__main__": |
|
|
|
parser = argparse.ArgumentParser() |
|
|
|
parser = argparse.ArgumentParser() |
|
|
|
parser.add_argument("--imgs_dir", help="path to PASCAL VOC 2012 images dir, data/VOC2012/JPEGImages") |
|
|
|
parser.add_argument("--imgs_dir", help="path to PASCAL VOC 2012 images dir, data/VOC2012/JPEGImages") |
|
|
|
parser.add_argument("--segm_dir", help="path to PASCAL VOC 2012 segmentation dir, data/VOC2012/SegmentationClass/") |
|
|
|
parser.add_argument("--segm_dir", help="path to PASCAL VOC 2012 segmentation dir, data/VOC2012/SegmentationClass/") |
|
|
|
parser.add_argument("--val_names", help="path to file with validation set image names, download it here: " |
|
|
|
parser.add_argument("--val_names", help="path to file with validation set image names, download it here: " |
|
|
|
"https://github.com/shelhamer/fcn.berkeleyvision.org/blob/master/data/pascal/seg11valid.txt") |
|
|
|
"https://github.com/shelhamer/fcn.berkeleyvision.org/blob/master/data/pascal/seg11valid.txt") |
|
|
|
parser.add_argument("--cls_file", help="path to file with colors for classes, download it here: " |
|
|
|
|
|
|
|
"https://github.com/opencv/opencv/blob/4.x/samples/data/dnn/pascal-classes.txt") |
|
|
|
|
|
|
|
parser.add_argument("--prototxt", help="path to caffe prototxt, download it here: " |
|
|
|
parser.add_argument("--prototxt", help="path to caffe prototxt, download it here: " |
|
|
|
"https://github.com/opencv/opencv/blob/4.x/samples/data/dnn/fcn8s-heavy-pascal.prototxt") |
|
|
|
"https://github.com/opencv/opencv/blob/4.x/samples/data/dnn/fcn8s-heavy-pascal.prototxt") |
|
|
|
parser.add_argument("--caffemodel", help="path to caffemodel file, download it here: " |
|
|
|
parser.add_argument("--caffemodel", help="path to caffemodel file, download it here: " |
|
|
|
"http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel") |
|
|
|
"http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel") |
|
|
|
parser.add_argument("--log", help="path to logging file") |
|
|
|
parser.add_argument("--onnxmodel", help="path to onnx model file, download it here: " |
|
|
|
|
|
|
|
"https://github.com/onnx/models/raw/491ce05590abb7551d7fae43c067c060eeb575a6/validated/vision/object_detection_segmentation/fcn/model/fcn-resnet50-12.onnx") |
|
|
|
|
|
|
|
parser.add_argument("--log", help="path to logging file", default='log.txt') |
|
|
|
parser.add_argument("--in_blob", help="name for input blob", default='data') |
|
|
|
parser.add_argument("--in_blob", help="name for input blob", default='data') |
|
|
|
parser.add_argument("--out_blob", help="name for output blob", default='score') |
|
|
|
parser.add_argument("--out_blob", help="name for output blob", default='score') |
|
|
|
args = parser.parse_args() |
|
|
|
args = parser.parse_args() |
|
|
|
|
|
|
|
|
|
|
|
prep = MeanChannelsPreproc() |
|
|
|
prep = MeanChannelsPreproc() |
|
|
|
df = PASCALDataFetch(args.imgs_dir, args.segm_dir, args.val_names, args.cls_file, prep) |
|
|
|
df = PASCALDataFetch(args.imgs_dir, args.segm_dir, args.val_names, colors_pascal_voc_2012, prep) |
|
|
|
|
|
|
|
|
|
|
|
fw = [CaffeModel(args.prototxt, args.caffemodel, args.in_blob, args.out_blob, True), |
|
|
|
fw = [CaffeModel(args.prototxt, args.caffemodel, args.in_blob, args.out_blob, True), |
|
|
|
DnnCaffeModel(args.prototxt, args.caffemodel, '', args.out_blob)] |
|
|
|
DNNOnnxModel(args.onnxmodel, args.in_blob, args.out_blob)] |
|
|
|
|
|
|
|
|
|
|
|
segm_eval = SemSegmEvaluation(args.log) |
|
|
|
segm_eval = SemSegmEvaluation(args.log) |
|
|
|
segm_eval.process(fw, df) |
|
|
|
segm_eval.process(fw, df) |
|
|
|