-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
020bd14
commit afd2ff5
Showing
49 changed files
with
54,129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import os | ||
import pandas as pd | ||
import numpy as np | ||
from PIL import Image | ||
import multiprocessing | ||
import argparse | ||
from IPython import embed | ||
|
||
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" | ||
os.environ["CUDA_VISIBLE_DEVICES"] = "1" | ||
|
||
palette = [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, 128, 64, 128, 0, 192, 128, 128, 192, 128, | ||
64, 64, 0, 192, 64, 0, 64, 192, 0, 192, 192, 0] | ||
|
||
categories = ['background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', | ||
'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', | ||
'tvmonitor'] | ||
|
||
pmod_folder = './save/230304_pmod/' | ||
if not os.path.exists(pmod_folder): | ||
os.makedirs(pmod_folder) | ||
|
||
|
||
def do_python_eval(predict_folder, gt_folder, name_list, num_cls=21, input_type='png', threshold=1.0, printlog=False): | ||
TP = [] | ||
P = [] | ||
T = [] | ||
for i in range(num_cls): | ||
TP.append(multiprocessing.Value('i', 0, lock=True)) | ||
P.append(multiprocessing.Value('i', 0, lock=True)) | ||
T.append(multiprocessing.Value('i', 0, lock=True)) | ||
|
||
def compare(start, step, TP, P, T, input_type, threshold): | ||
for idx in range(start, len(name_list), step): | ||
name = name_list[idx] | ||
if input_type == 'png': | ||
predict_file = os.path.join(predict_folder, '%s.png' % name) | ||
predict = np.array(Image.open(predict_file)) # cv2.imread(predict_file) | ||
elif input_type == 'npy': | ||
predict_file = os.path.join(predict_folder, '%s.npy' % name) | ||
predict_dict = np.load(predict_file, allow_pickle=True).item() | ||
h, w = list(predict_dict.values())[0].shape | ||
tensor = np.zeros((21, h, w), np.float32) | ||
for key in predict_dict.keys(): | ||
tensor[key + 1] = predict_dict[key] | ||
tensor[0, :, :] = threshold | ||
predict = np.argmax(tensor, axis=0).astype(np.uint8) | ||
|
||
# save pmod pseudo labels | ||
out = Image.fromarray(predict.astype(np.uint8), mode='P') | ||
out.putpalette(palette) | ||
out_name = pmod_folder + '/' + name + '.png' | ||
out.save(out_name) | ||
|
||
gt_file = os.path.join(gt_folder, '%s.png' % name) | ||
gt = np.array(Image.open(gt_file)) | ||
cal = gt < 255 | ||
mask = (predict == gt) * cal | ||
|
||
for i in range(num_cls): | ||
P[i].acquire() | ||
P[i].value += np.sum((predict == i) * cal) | ||
P[i].release() | ||
T[i].acquire() | ||
T[i].value += np.sum((gt == i) * cal) | ||
T[i].release() | ||
TP[i].acquire() | ||
TP[i].value += np.sum((gt == i) * mask) | ||
TP[i].release() | ||
|
||
p_list = [] | ||
for i in range(8): | ||
p = multiprocessing.Process(target=compare, args=(i, 8, TP, P, T, input_type, threshold)) | ||
p.start() | ||
p_list.append(p) | ||
for p in p_list: | ||
p.join() | ||
IoU = [] | ||
T_TP = [] | ||
P_TP = [] | ||
FP_ALL = [] | ||
FN_ALL = [] | ||
for i in range(num_cls): | ||
IoU.append(TP[i].value / (T[i].value + P[i].value - TP[i].value + 1e-10)) | ||
T_TP.append(T[i].value / (TP[i].value + 1e-10)) | ||
P_TP.append(P[i].value / (TP[i].value + 1e-10)) | ||
FP_ALL.append((P[i].value - TP[i].value) / (T[i].value + P[i].value - TP[i].value + 1e-10)) | ||
FN_ALL.append((T[i].value - TP[i].value) / (T[i].value + P[i].value - TP[i].value + 1e-10)) | ||
loglist = {} | ||
for i in range(num_cls): | ||
loglist[categories[i]] = IoU[i] * 100 | ||
|
||
miou = np.mean(np.array(IoU)) | ||
loglist['mIoU'] = miou * 100 | ||
if printlog: | ||
for i in range(num_cls): | ||
if i % 2 != 1: | ||
print('%11s:%7.3f%%' % (categories[i], IoU[i] * 100), end='\t') | ||
else: | ||
print('%11s:%7.3f%%' % (categories[i], IoU[i] * 100)) | ||
print('\n======================================================') | ||
print('%11s:%7.3f%%' % ('mIoU', miou * 100)) | ||
return loglist | ||
|
||
|
||
def writedict(file, dictionary): | ||
s = '' | ||
for key in dictionary.keys(): | ||
sub = '%s:%s ' % (key, dictionary[key]) | ||
s += sub | ||
s += '\n' | ||
file.write(s) | ||
|
||
|
||
def writelog(filepath, metric, comment): | ||
filepath = filepath | ||
logfile = open(filepath, 'a') | ||
import time | ||
logfile.write(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) | ||
logfile.write('\t%s\n' % comment) | ||
writedict(logfile, metric) | ||
logfile.write('=====================================\n') | ||
logfile.close() | ||
|
||
|
||
if __name__ == '__main__': | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument("--list", default='voc12/train_id.txt', type=str) # or 'voc12/val_id.txt', 'voc12/trainaug_id.txt' | ||
parser.add_argument("--predict_dir", default='save/out_cam', type=str) | ||
parser.add_argument("--gt_dir", default='../VOCdevkit/VOC2012/SegmentationClassAug', type=str) | ||
parser.add_argument('--logfile', default='./evallog_MECPformer.txt', type=str) | ||
parser.add_argument('--comment', required=True, type=str) | ||
parser.add_argument('--type', default='npy', choices=['npy', 'png'], type=str) | ||
# parser.add_argument('--t', default=0.45, type=float) | ||
# parser.add_argument('--curve', default=False, type=bool) | ||
parser.add_argument('--t', default=None, type=float) | ||
parser.add_argument('--curve', default=True, type=bool) | ||
args = parser.parse_args() | ||
|
||
if args.type == 'npy': | ||
assert args.t is not None or args.curve | ||
df = pd.read_csv(args.list, names=['filename']) | ||
name_list = df['filename'].values | ||
if not args.curve: | ||
print('=====begining...=====') | ||
loglist = do_python_eval(args.predict_dir, args.gt_dir, name_list, 21, args.type, args.t, printlog=True) | ||
writelog(args.logfile, loglist, args.comment) | ||
else: | ||
l = [] | ||
for i in range(30, 60): | ||
t = i / 100.0 | ||
loglist = do_python_eval(args.predict_dir, args.gt_dir, name_list, 21, args.type, t) | ||
l.append(loglist['mIoU']) | ||
print('%d/60 background score: %.3f\tmIoU: %.3f%%' % (i, t, loglist['mIoU'])) | ||
writelog(args.logfile, {'mIoU': l}, args.comment) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
|
||
import numpy as np | ||
import torch | ||
import os | ||
import voc12.data_copy | ||
import voc12.data | ||
import importlib | ||
from torch.utils.data import DataLoader | ||
import torchvision | ||
from tool import imutils, infer_utils | ||
import argparse | ||
from PIL import Image | ||
import torch.nn.functional as F | ||
|
||
|
||
palette = [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, 128, 64, 128, 0, 192, 128, 128, 192, 128, | ||
64, 64, 0, 192, 64, 0, 64, 192, 0, 192, 192, 0] | ||
|
||
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" | ||
os.environ["CUDA_VISIBLE_DEVICES"] = "0" | ||
|
||
if __name__ == '__main__': | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument("--weights", required=True, type=str) | ||
parser.add_argument("--network", default='network.conformer_CAM', type=str) | ||
parser.add_argument("--infer_list", default='voc12/train_aug.txt', type=str) # or 'voc12/val.txt', 'voc12/train_aug.txt' | ||
parser.add_argument("--num_workers", default=0, type=int) | ||
parser.add_argument("--voc12_root", default='../VOCdevkit/VOC2012', type=str) | ||
parser.add_argument("--save", default='./save', type=str) | ||
parser.add_argument("--out_cam", default='save/out_cam', type=str) | ||
parser.add_argument("--arch", default='sm21', type=str) | ||
parser.add_argument("--method", default='transcam', type=str) | ||
|
||
args = parser.parse_args() | ||
print(args) | ||
|
||
if not os.path.exists(args.save): | ||
os.makedirs(args.save) | ||
|
||
if not os.path.exists(args.out_cam): | ||
os.makedirs(args.out_cam) | ||
|
||
|
||
attention_folder = args.save + '/attention' + args.infer_list[5:-4] | ||
if not os.path.exists(attention_folder): | ||
os.makedirs(attention_folder) | ||
|
||
heatmap_folder = args.save + '/heatmap' + args.infer_list[5:-4] | ||
if not os.path.exists(heatmap_folder): | ||
os.makedirs(heatmap_folder) | ||
|
||
pmod_folder = args.save + '/pmod' + args.infer_list[5:-4] | ||
if not os.path.exists(pmod_folder): | ||
os.makedirs(pmod_folder) | ||
|
||
model = getattr(importlib.import_module(args.network), 'Net_' + args.arch)() | ||
|
||
model.load_state_dict(torch.load(args.weights)) | ||
|
||
model.eval() | ||
model.cuda() | ||
|
||
n_parameters = sum(p.numel() for p in model.parameters() if p.requires_grad) | ||
print('number of params:', n_parameters) | ||
|
||
infer_dataset = voc12.data_copy.VOC12ClsDatasetMSF(args.infer_list, voc12_root=args.voc12_root, | ||
inter_transform=torchvision.transforms.Compose( | ||
[ | ||
np.asarray, | ||
imutils.Normalize(), | ||
imutils.HWC_to_CHW])) | ||
|
||
infer_data_loader = DataLoader(infer_dataset, shuffle=False, num_workers=args.num_workers, pin_memory=True) | ||
print('infer beginning...') | ||
for iter, (img_name, img_list, label) in enumerate(infer_data_loader): | ||
img_name = img_name[0]; label = label[0] | ||
|
||
img_path = voc12.data.get_img_path(img_name, args.voc12_root) | ||
orig_img = np.asarray(Image.open(img_path)) | ||
orig_img_size = orig_img.shape[:2] | ||
|
||
cam_list = [] | ||
sal_att_list = [] | ||
|
||
with torch.no_grad(): | ||
for i, img in enumerate(img_list): | ||
logits_conv, logits_trans, trans_patch_logits, cam = model(args.method, img.cuda()) | ||
cam = F.interpolate(cam[:, 1:, :, :], orig_img_size, mode='bilinear', align_corners=False)[0] | ||
cam = cam.cpu().numpy() * label.clone().view(20, 1, 1).numpy() | ||
|
||
if i % 2 == 1: | ||
cam = np.flip(cam, axis=-1) | ||
|
||
cam_list.append(cam) | ||
|
||
|
||
sum_cam = np.sum(cam_list, axis=0) | ||
sum_cam[sum_cam < 0] = 0 | ||
|
||
|
||
cam_max = np.max(sum_cam, (1,2), keepdims=True) | ||
cam_min = np.min(sum_cam, (1,2), keepdims=True) | ||
sum_cam[sum_cam < cam_min+1e-5] = 0 | ||
norm_cam = (sum_cam-cam_min-1e-5) / (cam_max - cam_min + 1e-5) | ||
|
||
ZERO = infer_utils.save_att(label, norm_cam, attention_folder, img_name) | ||
|
||
orig_img_ht = torch.from_numpy(orig_img) | ||
orig_img_ht = orig_img_ht.permute(2, 0, 1) | ||
orig_img_ht = orig_img_ht.unsqueeze(0) | ||
infer_utils.draw_single_heatmap(norm_cam, label, orig_img_ht, heatmap_folder, img_name) | ||
|
||
# generate pmod initial seed | ||
bg = [np.ones((orig_img.shape[0], orig_img.shape[1])) * 0.40] # 0.4 is the simple threshold to delete noise information | ||
cam_21 = np.concatenate((bg, norm_cam), axis=0) # | ||
seg_map = np.asarray(np.argmax(cam_21, axis=0), dtype=int) | ||
out = Image.fromarray(seg_map.astype(np.uint8), mode='P') | ||
out.putpalette(palette) | ||
out_name = pmod_folder + '/' + img_name + '.png' | ||
out.save(out_name) | ||
|
||
cam_dict = {} | ||
for i in range(20): | ||
if label[i] > 1e-5: | ||
cam_dict[i] = norm_cam[i] | ||
|
||
if args.out_cam is not None: | ||
np.save(os.path.join(args.out_cam, img_name + '.npy'), cam_dict) | ||
|
||
h, w = list(cam_dict.values())[0].shape | ||
tensor = np.zeros((21, h, w), np.float32) | ||
for key in cam_dict.keys(): | ||
tensor[key+1] = cam_dict[key] | ||
|
||
if iter % 500 == 0: | ||
print('over iter:', iter) |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.