import os import json import random from PIL import Image import torch from torch.utils.data import Dataset from data.utils import pre_question from torchvision.datasets.utils import download_url class vqa_dataset(Dataset): def __init__(self, transform, ann_root, vqa_root, vg_root, train_files=[], split="train"): self.split = split self.transform = transform self.vqa_root = vqa_root self.vg_root = vg_root if split=='train': urls = {'vqa_train':'https://storage.googleapis.com/sfr-vision-language-research/datasets/vqa_train.json', 'vqa_val':'https://storage.googleapis.com/sfr-vision-language-research/datasets/vqa_val.json', 'vg_qa':'https://storage.googleapis.com/sfr-vision-language-research/datasets/vg_qa.json'} self.annotation = [] for f in train_files: download_url(urls[f],ann_root) self.annotation += json.load(open(os.path.join(ann_root,'%s.json'%f),'r')) else: download_url('https://storage.googleapis.com/sfr-vision-language-research/datasets/vqa_test.json',ann_root) self.annotation = json.load(open(os.path.join(ann_root,'vqa_test.json'),'r')) download_url('https://storage.googleapis.com/sfr-vision-language-research/datasets/answer_list.json',ann_root) self.answer_list = json.load(open(os.path.join(ann_root,'answer_list.json'),'r')) def __len__(self): return len(self.annotation) def __getitem__(self, index): ann = self.annotation[index] if ann['dataset']=='vqa': image_path = os.path.join(self.vqa_root,ann['image']) elif ann['dataset']=='vg': image_path = os.path.join(self.vg_root,ann['image']) image = Image.open(image_path).convert('RGB') image = self.transform(image) if self.split == 'test': question = pre_question(ann['question']) question_id = ann['question_id'] return image, question, question_id elif self.split=='train': question = pre_question(ann['question']) if ann['dataset']=='vqa': answer_weight = {} for answer in ann['answer']: if answer in answer_weight.keys(): answer_weight[answer] += 1/len(ann['answer']) else: answer_weight[answer] = 1/len(ann['answer']) answers = list(answer_weight.keys()) weights = list(answer_weight.values()) elif ann['dataset']=='vg': answers = [ann['answer']] weights = [0.2] return image, question, answers, weights def vqa_collate_fn(batch): image_list, question_list, answer_list, weight_list, n = [], [], [], [], [] for image, question, answer, weights in batch: image_list.append(image) question_list.append(question) weight_list += weights answer_list += answer n.append(len(answer)) return torch.stack(image_list,dim=0), question_list, answer_list, torch.Tensor(weight_list), n