-
Notifications
You must be signed in to change notification settings - Fork 6
/
semanticSegmentation.py
177 lines (132 loc) · 5.47 KB
/
semanticSegmentation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import sys
import os
import click
import cv2
import numpy as np
from glob import glob
from tqdm import tqdm
import json
from helpers import makeResultsDirectory
from classConversionDict import convertStuffIdToPanopticId
import torch
import torch.nn.functional as F
from addict import Dict
import yaml
from pycocotools import cocostuffhelper as cocostuff
from pycocotools.coco import COCO
mainConfig = Dict(yaml.load(open("./config.yaml")))
makeResultsDirectory(mainConfig.results_folder)
DEEPLAB_ROOT_DIR = os.path.abspath(mainConfig.deeplab_path)
sys.path.append(DEEPLAB_ROOT_DIR)
from libs.models import DeepLabV2_ResNet101_MSC
from libs.utils import dense_crf
# Related to visualization
def createLabels(config_obj):
LabelsPath = os.path.join(DEEPLAB_ROOT_DIR, config_obj.LABELS)
# Label list
with open(LabelsPath) as f:
classes = {}
for label in f:
label = label.rstrip().split("\t")
classes[int(label[0])] = label[1].split(",")[0]
def loadModel(model_path, config_obj, cuda=True):
cuda = cuda and torch.cuda.is_available()
device = torch.device("cuda" if cuda else "cpu")
if cuda:
current_device = torch.cuda.current_device()
print("Running on", torch.cuda.get_device_name(current_device))
else:
print("Running on CPU")
# Model
model = DeepLabV2_ResNet101_MSC(n_classes=config_obj.N_CLASSES)
state_dict = torch.load(model_path, map_location=lambda storage, loc: storage)
model.load_state_dict(state_dict)
model.eval()
model.to(device)
return model
def preProcessImage(image, config_obj, cuda=True):
cuda = cuda and torch.cuda.is_available()
device = torch.device("cuda" if cuda else "cpu")
# This is causing issues as it is not same shape as inst segm.
# scale = config_obj.IMAGE.SIZE.TEST / max(image.shape[:2])
# image = cv2.resize(image, dsize=None, fx=scale, fy=scale)
# image_original = image.astype(np.uint8)
# image -= np.array(
# [
# float(config_obj.IMAGE.MEAN.B),
# float(config_obj.IMAGE.MEAN.G),
# float(config_obj.IMAGE.MEAN.R),
# ]
# )
image = torch.from_numpy(image.transpose(2, 0, 1)).float().unsqueeze(0)
image = image.to(device)
return image
def extractConfig(config_path):
return Dict(yaml.load(open(config_path)))
def extractJpgImagePaths(image_folder):
return glob(os.path.join(image_folder, '*.jpg'))
def extractIdFromPath(image_path):
image_file = image_path.split('/')[-1]
return image_file.split('.')[0]
def makePrediction(config_obj, image_path, model, cuda=True, crf=False):
torch.set_grad_enabled(False)
image_id = extractIdFromPath(image_path)
# Image preprocessing
image = cv2.imread(image_path, cv2.IMREAD_COLOR).astype(float)
image = preProcessImage(image, config_obj, cuda)
# Inference
output = model(image)
output = F.interpolate(
output, size=image.shape[2:], mode="bilinear", align_corners=True
)
output = F.softmax(output, dim=1)
output = output.data.cpu().numpy()[0]
if crf:
output = dense_crf(image_original, output)
labelmap = np.argmax(output, axis=0)
cocoResFormat = cocostuff.segmentationToCocoResult(labelmap, image_id)
return cocoResFormat
# I cant create a JSON file as the segmentation is stores as bytes, need to decode
def decodeSegmentationResults(result_list):
decoded_results = []
for result in result_list:
result_copy = Dict(result)
encodedCounts = result_copy.segmentation.counts
result_copy.segmentation.counts = encodedCounts.decode('utf8')
decoded_results.append(result_copy)
return decoded_results
def convertClassesForPanoptic(result_list):
converted_results = []
for result in result_list:
result_copy = Dict(result)
categoryClass = result_copy.category_id
panopticIndex = convertStuffIdToPanopticId(categoryClass)
if panopticIndex is not None:
result_copy.category_id = panopticIndex
converted_results.append(result_copy)
else:
print ('No index, skipping')
return converted_results
def runPredictions(model_path, config_path, image_folder, cuda=True, limit=None):
config_obj = extractConfig(config_path)
model = loadModel(model_path, config_obj, cuda)
image_path_list = sorted(extractJpgImagePaths(imageFolder))
image_range = limit if limit is not None else len(image_path_list)
total_results = []
for index in tqdm(range(image_range)):
image_path = image_path_list[index]
image_results = makePrediction(config_obj, image_path, model)
total_results.extend(image_results)
decoded_results = decodeSegmentationResults(total_results)
class_conversion = convertClassesForPanoptic(decoded_results)
print (len(class_conversion))
with open('{}/{}.json'.format(mainConfig.results_folder,
mainConfig.semantic_result_json), 'w') as outfile:
json.dump(class_conversion, outfile)
print ('JSON file created in Results folder')
thisDir = os.path.abspath('./')
modelPath = os.path.join(DEEPLAB_ROOT_DIR, 'data', 'models', 'deeplab_resnet101', 'cocostuff164k', 'cocostuff164k_iter100k.pth')
configPath = os.path.join(DEEPLAB_ROOT_DIR, 'config','cocostuff164k.yaml')
imageFolder = os.path.join(thisDir, 'dataset', 'coco', 'val2017')
lim = int(mainConfig.image_limit) if mainConfig.image_limit != 'None' else None
runPredictions(modelPath, configPath, imageFolder, limit=lim)