-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcoco_dataset.py
More file actions
115 lines (100 loc) · 3.69 KB
/
Copy pathcoco_dataset.py
File metadata and controls
115 lines (100 loc) · 3.69 KB
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
import json
import os
import nltk
import numpy as np
import torch
from PIL import Image
from pycocotools.coco import COCO
from torch.utils import data as data
from tqdm import tqdm
from vocabulary import Vocabulary
class CoCoDataset(data.Dataset):
def __init__(
self,
transform,
mode,
batch_size,
vocab_threshold,
vocab_file,
start_word,
end_word,
unk_word,
annotations_file,
vocab_from_file,
img_folder,
):
self.transform = transform
self.mode = mode
self.batch_size = batch_size
self.img_folder = img_folder
# create vocabulary from the captions
self.vocab = Vocabulary(
vocab_threshold,
vocab_file,
start_word,
end_word,
unk_word,
annotations_file,
vocab_from_file,
)
if self.mode == "train":
self.coco = COCO(annotations_file)
self.ids = list(self.coco.anns.keys())
print("Obtaining caption lengths...")
# get list of tokens for each caption
tokenized_captions = [
nltk.tokenize.word_tokenize(
str(self.coco.anns[self.ids[index]]["caption"]).lower()
)
for index in tqdm(np.arange(len(self.ids)))
]
# get len of each caption
self.caption_lengths = [len(token) for token in tokenized_captions]
else:
test_info = json.loads(open(annotations_file).read())
self.paths = [item["file_name"] for item in test_info["images"]]
def __getitem__(self, index):
# obtain image and caption if in training mode
if self.mode == "train":
ann_id = self.ids[index]
caption = self.coco.anns[ann_id]["caption"]
img_id = self.coco.anns[ann_id]["image_id"]
path = self.coco.loadImgs(img_id)[0]["file_name"]
# Convert image to tensor and pre-process using transform
image = Image.open(os.path.join(self.img_folder, path)).convert("RGB")
image = self.transform(image)
# Convert caption to tensor of word ids.
tokens = nltk.tokenize.word_tokenize(str(caption).lower())
caption = [self.vocab(self.vocab.start_word)]
caption.extend([self.vocab(token) for token in tokens])
caption.append(self.vocab(self.vocab.end_word))
caption = torch.Tensor(caption).long()
# return pre-processed image and caption tensors
return image, caption
# obtain image if in test mode
else:
path = self.paths[index]
# Convert image to tensor and pre-process using transform
pil_image = Image.open(os.path.join(self.img_folder, path)).convert("RGB")
orig_image = np.array(pil_image)
image = self.transform(pil_image)
# return original image and pre-processed image tensor
return orig_image, image
def get_train_indices(self):
# select random len
sel_length = np.random.choice(self.caption_lengths)
# find indices of captions having specific length
all_indices = np.where(
[
self.caption_lengths[i] == sel_length
for i in np.arange(len(self.caption_lengths))
]
)[0]
# select only limited (batch size) number of them
indices = list(np.random.choice(all_indices, size=self.batch_size))
return indices
def __len__(self):
if self.mode == "train":
return len(self.ids)
else:
return len(self.paths)