|
|
|
|
|
"""Classes for feeding data during training.""" |
|
|
import numpy as np |
|
|
import pandas as pd |
|
|
from .helpers import img_extend |
|
|
from .datahelpers import sequences_to_sparse |
|
|
|
|
|
|
|
|
class BucketDataIterator(): |
|
|
"""Iterator for feeding CTC model during training.""" |
|
|
def __init__(self, |
|
|
images, |
|
|
targets, |
|
|
num_buckets=5, |
|
|
slider=(60, 30), |
|
|
augmentation=None, |
|
|
dropout=0.0, |
|
|
train=True): |
|
|
|
|
|
self.train = train |
|
|
self.slider = slider |
|
|
self.augmentation = augmentation |
|
|
self.dropout = dropout |
|
|
for i in range(len(images)): |
|
|
images[i] = img_extend( |
|
|
images[i], |
|
|
(self.slider[0], |
|
|
max(images[i].shape[1], self.slider[1]))) |
|
|
in_length = [image.shape[1] for image in images] |
|
|
|
|
|
|
|
|
self.dataFrame = pd.DataFrame({ |
|
|
'in_length': in_length, |
|
|
'images': images, |
|
|
'targets': targets}).sort_values('in_length').reset_index(drop=True) |
|
|
|
|
|
bsize = int(len(images) / num_buckets) |
|
|
self.num_buckets = num_buckets |
|
|
self.buckets = [] |
|
|
for bucket in range(num_buckets-1): |
|
|
self.buckets.append( |
|
|
self.dataFrame.iloc[bucket * bsize: (bucket+1) * bsize]) |
|
|
self.buckets.append(self.dataFrame.iloc[(num_buckets-1) * bsize:]) |
|
|
|
|
|
self.buckets_size = [len(bucket) for bucket in self.buckets] |
|
|
self.cursor = np.array([0] * num_buckets) |
|
|
self.bucket_order = np.random.permutation(num_buckets) |
|
|
self.bucket_cursor = 0 |
|
|
self.shuffle() |
|
|
print("Iterator created.") |
|
|
|
|
|
|
|
|
def shuffle(self, idx=None): |
|
|
"""Shuffle idx bucket or each bucket separately.""" |
|
|
for i in [idx] if idx is not None else range(self.num_buckets): |
|
|
self.buckets[i] = self.buckets[i].sample(frac=1).reset_index(drop=True) |
|
|
self.cursor[i] = 0 |
|
|
|
|
|
|
|
|
def next_batch(self, batch_size): |
|
|
"""Creates next training batch of size. |
|
|
Args: |
|
|
batch_size: size of next batch |
|
|
Retruns: |
|
|
(images, labels, images lengths, labels lengths) |
|
|
""" |
|
|
i_bucket = self.bucket_order[self.bucket_cursor] |
|
|
|
|
|
self.bucket_cursor = (self.bucket_cursor + 1) % self.num_buckets |
|
|
if self.bucket_cursor == 0: |
|
|
self.bucket_order = np.random.permutation(self.num_buckets) |
|
|
|
|
|
if self.cursor[i_bucket] + batch_size > self.buckets_size[i_bucket]: |
|
|
self.shuffle(i_bucket) |
|
|
|
|
|
|
|
|
if (batch_size > self.buckets_size[i_bucket]): |
|
|
batch_size = self.buckets_size[i_bucket] |
|
|
|
|
|
res = self.buckets[i_bucket].iloc[self.cursor[i_bucket]: |
|
|
self.cursor[i_bucket]+batch_size] |
|
|
self.cursor[i_bucket] += batch_size |
|
|
|
|
|
|
|
|
input_max = max(res['in_length']) |
|
|
|
|
|
input_imgs = np.zeros( |
|
|
(batch_size, self.slider[0], input_max, 1), dtype=np.uint8) |
|
|
for i, img in enumerate(res['images']): |
|
|
input_imgs[i][:, :res['in_length'].values[i], 0] = img |
|
|
|
|
|
if self.train: |
|
|
input_imgs = self.augmentation.augment_images(input_imgs) |
|
|
input_imgs = input_imgs.astype(np.float32) |
|
|
|
|
|
targets = sequences_to_sparse(res['targets'].values) |
|
|
return input_imgs, targets, res['in_length'].values |
|
|
|
|
|
|