Skip to content

Commit

Permalink
file
Browse files Browse the repository at this point in the history
  • Loading branch information
ChunmengLiu1 committed May 25, 2023
1 parent 020bd14 commit afd2ff5
Show file tree
Hide file tree
Showing 49 changed files with 54,129 additions and 0 deletions.
158 changes: 158 additions & 0 deletions evaluation.py
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)
139 changes: 139 additions & 0 deletions infer.py
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 added network/__pycache__/conformer.cpython-36.pyc
Binary file not shown.
Binary file added network/__pycache__/conformer.cpython-37.pyc
Binary file not shown.
Binary file not shown.
Binary file added network/__pycache__/conformer_CAM.cpython-36.pyc
Binary file not shown.
Binary file added network/__pycache__/conformer_CAM.cpython-37.pyc
Binary file not shown.
Binary file added network/__pycache__/conformer_coco.cpython-36.pyc
Binary file not shown.
Binary file added network/__pycache__/conformer_copy.cpython-36.pyc
Binary file not shown.
Binary file added network/__pycache__/conformer_copy.cpython-37.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit afd2ff5

Please sign in to comment.