Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolve conflict #3

Open
wants to merge 12 commits into
base: jh
Choose a base branch
from
Open
4 changes: 2 additions & 2 deletions efficientdet_/config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
num_epochs = 150


batch_size=4
batch_size=16

num_workers=4
num_workers=0

lr=0.005

Expand Down
105 changes: 60 additions & 45 deletions efficientdet_/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def get_test_transform():
# Effdet config를 통해 모델 불러오기 + ckpt load
def load_net(checkpoint_path, device):
config = get_efficientdet_config('tf_efficientdet_d3')
config.num_classes = 3
config.num_classes = 4
config.image_size = (512,512)

config.soft_nms = False
Expand All @@ -89,14 +89,25 @@ def load_net(checkpoint_path, device):
def valid_fn(val_data_loader,test_ann, model, device):
outputs = []
ground_truths=[]
labels=[]

for images, image_ids in tqdm(val_data_loader):
# gpu 계산을 위해 image.to(device)
image_dir='./data_test/01. data/Image'
record=test_ann.iloc[image_ids]
image_name=record['image_name']
image_path=os.path.join(image_dir,record['dataset'])
test=cv2.imread(os.path.join(image_path,image_name))
h, w, c = test.shape

a=images
images = torch.stack(images) # bs, ch, w, h
images = images.to(device).float()
print(image_ids)

output = model(images)

for out in output:
outputs.append({'boxes': out.detach().cpu().numpy()[:,:4],
outputs.append({'boxes': out.detach().cpu().numpy()[:,:4]*np.array([w,h,w,h])/512,
'scores': out.detach().cpu().numpy()[:,4],
'labels': out.detach().cpu().numpy()[:,-1]})
for image_id in image_ids:
Expand All @@ -105,7 +116,7 @@ def valid_fn(val_data_loader,test_ann, model, device):
ground_truths.append(boxes)


return outputs,ground_truths
return outputs,ground_truths,labels

def collate_fn(batch):
return tuple(zip(*batch))
Expand Down Expand Up @@ -137,59 +148,63 @@ def calculate_iou(box1, box2):
return iou

# 메트릭 계산 함수
def calculate_metrics(predictions, ground_truths, iou_threshold=0.0001):
def calculate_metrics(predictions_boxes,predictions_labels, ground_truths,labels, iou_threshold=0.2):
"""
Calculate precision, recall, and IoU score for a set of predictions and ground truth boxes.
"""
total_true_positives = 0
total_false_positives = 0
total_false_negatives = 0
total_iou_score = 0

for pred_boxes, gt_boxes in zip(predictions, ground_truths):
matched = [False] * len(gt_boxes)

for pred_box in pred_boxes: # 모든 prediction에 대해
result=np.zeros((4,4))

for pred_boxes, pred_labels, gt_boxes,gt_labels in zip(predictions_boxes, predictions_labels, ground_truths, labels):
if len(pred_labels)==0:
pred_labels=np.append(pred_labels,3)
pred_boxes=np.append(pred_boxes,0)

for pred_box,pred_label in zip(pred_boxes,pred_labels): # 모든 prediction에 대해
best_iou = 0
best_match = None

for i, gt_box in enumerate(gt_boxes):
iou = calculate_iou(pred_box, gt_box)

if iou > best_iou:
best_iou = iou
best_match = i
for gt_box, gt_label in zip(gt_boxes,gt_labels):
if pred_label==3:
x=int(pred_label)
else:
iou = calculate_iou(pred_box, gt_box)
if iou > best_iou:
best_iou = iou
x=int(gt_label)
y=int(pred_label)

if best_iou > iou_threshold:
if not matched[best_match]:
total_true_positives += 1
total_iou_score += best_iou
matched[best_match] = True
if best_iou > iou_threshold :
result[x][y]+=1

else:
total_false_positives += 1

total_false_negatives += len(gt_boxes) - sum(matched)

precision = total_true_positives / (total_true_positives + total_false_positives) if (total_true_positives + total_false_positives) != 0 else 0
recall = total_true_positives / (total_true_positives + total_false_negatives) if (total_true_positives + total_false_negatives) != 0 else 0
average_iou = total_iou_score / total_true_positives if total_true_positives != 0 else 0

return {'precision': precision, 'recall': recall, 'average_iou': average_iou}
if len(gt_boxes)==0:
result[3][int(pred_label)]+=1
else:
result[x][3]+=1

print(result)
Porosity_precision = result[1][1]/sum(result[:,1])
Porosity_recall = result[1][1]/sum(result[1,:])
Porosity_F1_score = 2*Porosity_precision*Porosity_recall/(Porosity_precision+Porosity_recall)
slag_precision = result[2][2]/sum(result[:,2])
slag_recall = result[2][2]/sum(result[2,:])
slag_F1_score = 2*slag_precision*slag_recall/(slag_precision+slag_recall)

return {'Porosity_precision': Porosity_precision, 'Porosity_recall': Porosity_recall, 'Porosity_F1_score': Porosity_F1_score,
'slag_precision': slag_precision, 'slag_recall': slag_recall, 'slag_F1_score': slag_F1_score}


def main():
test_ann_dir='.annotations/test_total.csv'
image_dir='/home/irteam/junghye-dcloud-dir/pathfinder/data/Image'
test_ann_dir='./data_test/01. data/annotations_v2/test_total.csv'
image_dir='./data_test/01. data/Image'
test_dataset=RT_dataset(image_dir,test_ann_dir,transforms=get_test_transform())
test_ann=pd.read_csv(test_ann_dir)
#epoch=50
checkpoint_path=f'/home/irteam/junghye-dcloud-dir/pathfinder/models/effdet_best_loss_modifiedann.pth'
score_threshold=0.01 # score : 모델이 해당 객체를 올바르게 감지했다고 확신하는 정도
checkpoint_path=f'./models/effdet_best_loss_modifiedann.pth'
score_threshold=0.2 # score : 모델이 해당 객체를 올바르게 감지했다고 확신하는 정도
test_data_loader=DataLoader(
test_dataset,
batch_size=2,
batch_size=1,
shuffle=False,
num_workers=4,
num_workers=0,
collate_fn=collate_fn
)

Expand All @@ -198,7 +213,7 @@ def main():

model=load_net(checkpoint_path,device)

outputs,ground_truths=valid_fn(test_data_loader,test_ann,model,device)
outputs,gt_boxes,gt_labels=valid_fn(test_data_loader,test_ann,model,device)

# calculate precision, recall, average_iou scores
# 테스트 데이터에서 상위 점수를 가진 bounding box만 선택
Expand All @@ -208,8 +223,8 @@ def main():
predictions.append(valid_boxes)

# calculate precision, recall, average_iou scores
metrics = calculate_metrics(predictions, ground_truths)
metrics = calculate_metrics(predictions_boxes,predictions_labels,gt_boxes,gt_labels)
print(metrics)

if __name__ == "__main__":
main()
main()
4 changes: 2 additions & 2 deletions efficientdet_/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
def get_net(checkpoint_path=None):

config = get_efficientdet_config('tf_efficientdet_d3')
config.num_classes = 3
config.num_classes = 4
config.image_size = (512,512)

config.soft_nms = False
Expand All @@ -18,4 +18,4 @@ def get_net(checkpoint_path=None):
checkpoint = torch.load(checkpoint_path)
net.load_state_dict(checkpoint['model_state_dict'])

return DetBenchTrain(net)
return DetBenchTrain(net)
12 changes: 6 additions & 6 deletions faster-rcnn/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Config=dict(
EPOCHS=150,
LR=2e-4,
IMG_SIZE=224,
EPOCHS=50,
LR=5e-4,
IMG_SIZE=640,
DR_RATE=0.35,
NUM_CLASSES=4,
TRAIN_BS=4,
VALID_BS=2,
TRAIN_BS=8,
VALID_BS=4,
NUM_WORKERS=4,
WEIGHT_DECAY=0.0005,
CONTRAST='AFTER'
CONTRAST='AFTER',

)
166 changes: 166 additions & 0 deletions faster-rcnn/inference.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import sys
sys.path.append('/content/drive/MyDrive/Pathfinder-Models/utils')
import os
import numpy as np
import pandas as pd

# for ignoring warnings
import warnings
warnings.filterwarnings('ignore')

import cv2

import torch
import torchvision
from torchvision import transforms as torchtrans
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
from torchvision.ops import nms


from tqdm import tqdm
import utils
import transforms as T
from dataset import RT_Dataset
from config import Config
from augment import get_transform

from torchvision.models.detection.ssd import SSDClassificationHead
from torchvision.models.detection import _utils
from torchvision.models.detection import SSD300_VGG16_Weights



# model
def get_object_detection_model(num_classes):

# load a model pre-trained pre-trained on COCO
model = torchvision.models.detection.fasterrcnn_resnet50_fpn_v2(pretrained=True)

# get number of input features for the classifier
in_features = model.roi_heads.box_predictor.cls_score.in_features
# replace the pre-trained head with a new one
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)

return model

# valid function
def valid_fn(val_data_loader, model, device):
model.eval()
outputs = []
ground_truths=[]

for images,targets in tqdm(val_data_loader):

images=list(img.to(device) for img in images)
targets = [{k: v.to(device) for k, v in t.items()} for t in targets]

output=model(images)


for out,target in zip(output,targets):
scores=out['scores'].detach().cpu().numpy()
boxes=out['boxes'].detach().cpu().numpy()
labels=out['labels'].detach().cpu().numpy()

keep_idx=nms(boxes,scores,iou_threshold=0.1)

boxes=boxes[keep_idx]
scores=scores[keep_idx]
labels=labels[keep_idx]


outputs.append({'boxes': boxes,
'scores': scores,
'labels': labels})

# ground truth 에 label 추가
gt_boxes=target['boxes'].cpu().numpy()
gt_labels=target['labels'].cpu().numpy()

ground_truths.append(list(zip(gt_labels,gt_boxes)))




return outputs,ground_truths


def validate_and_save_best_model(epoch, model, valid_dataloader, device, optimizer, lr_scheduler, score_threshold=0.2):
global best_recall
outputs, ground_truths = valid_fn(valid_dataloader, model, device)
predictions = []


for output in outputs:
valid_scores=output['scores']>score_threshold

valid_boxes = output['boxes'][output['scores'] > score_threshold]
valid_labels=output['labels'][output['scores']> score_threshold]


predictions.append(list(zip(valid_labels,valid_boxes)))



# utils 모듈에 있는 calculate_metrics 함수를 사용
metrics = utils.calculate_metrics(predictions, ground_truths)

# 전체 성능
total_recall=metrics['total']['recall']
total_precision=metrics['total']['precision']
total_f1_score= metrics['total']['f1_score']

class_result = {class_label: metrics_val for class_label, metrics_val in metrics['per_class'].items() if class_label != 0}

return_outputs=metrics['total']
return return_outputs,class_result

if __name__=='__main__':


if torch.cuda.is_available():
device=torch.device('cuda')


valid_df=pd.read_csv('/content/drive/MyDrive/data/annotations_v2/test_total.csv')
image_dir='/content/drive/MyDrive/data/Image'




valid_dataset=RT_Dataset(valid_df,image_dir,transforms=get_transform(train=False))



valid_dataloader=torch.utils.data.DataLoader(
valid_dataset,
batch_size=Config['VALID_BS'],
shuffle=False,
num_workers=Config['NUM_WORKERS'],
collate_fn=utils.collate_fn,

)


model=get_object_detection_model(Config['NUM_CLASSES'])


model_save_path = "/content/drive/MyDrive/models/fasterrcnn_resnet50_fpnv2_8_4.pth"
saved_state=torch.load(model_save_path,map_location=device)

model.load_state_dict(saved_state['model_state_dict'])

model.to(device)



params = [p for p in model.parameters() if p.requires_grad]

optimizer = torch.optim.SGD(params, lr=Config['LR'], momentum=0.9, weight_decay=Config['WEIGHT_DECAY'])

lr_scheduler=torch.optim.lr_scheduler.StepLR(optimizer,step_size=5,gamma=0.9)

# valid data
return_outputs,class_result = validate_and_save_best_model(0, model, valid_dataloader, device, optimizer, lr_scheduler)

print(f'test Total result : {return_outputs} , class result : {class_result} ')
Loading