Как использовать Tensorflow Dataset с предварительной обработкой OpenCV? - PullRequest
0 голосов
/ 10 апреля 2019

Я создаю конвейер для распознавания текста и хочу использовать наборы данных Tensorflow для загрузки данных через некоторую предварительную обработку с OpenCV

Я следовал этому руководству https://www.tensorflow.org/guide/datasets#applying_arbitrary_python_logic_with_tfpy_func, и у меня есть эта функция предварительной обработки:

def preprocess(path, imgSize=(1024, 64), dataAugmentation=False):

    img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

    kernel = np.ones((3, 3), np.uint8)
    th, img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV + 
    cv2.THRESH_OTSU)
    img = cv2.dilate(img, kernel, iterations=1)

    # create target image and copy sample image into it
    (wt, ht) = imgSize
    (h, w) = img.shape
    fx = w / wt
    fy = h / ht
    f = max(fx, fy)
    newSize = (max(min(wt, int(w / f)), 1),
               max(min(ht, int(h / f)), 1))  # scale according to f (result at 
    least 1 and at most wt or ht)
    img = cv2.resize(img, newSize)

    # add random padding to fit the target size if data augmentation is true
    # otherwise add padding to the right
    if newSize[1] == ht:
        if dataAugmentation:
            padding_width_left = np.random.random_integers(0, wt-newSize[0])
            img = cv2.copyMakeBorder(img, 0, 0, padding_width_left, wt-newSize[0]-padding_width_left, cv2.BORDER_CONSTANT, None, (0, 0))
        else:
            img = cv2.copyMakeBorder(img, 0, 0, 0, wt - newSize[0], cv2.BORDER_CONSTANT, None, (0, 0))
    else:
        img = cv2.copyMakeBorder(img, int(np.floor((ht - newSize[1])/2)), int(np.ceil((ht - newSize[1])/2)), 0, 0, cv2.BORDER_CONSTANT, None, (0, 0))

    # transpose for TF
    img = cv2.transpose(img)

    return img

Но если я использую это

list_images = os.listdir(images_path)
image_paths = []
for i in range(len(list_images)):
    image_paths.append("iam-database/images/" + list_images[i])

dataset = tf.data.Dataset.from_tensor_slices(image_paths)
dataset = dataset.map(lambda filename: tuple(tf.py_function(preprocess, [filename], [tf.uint8])))
print(dataset)

, я получаю неизвестную форму, и кажется, что функция предварительной обработки не анализируется.Что мне делать?

Ответы [ 2 ]

0 голосов
/ 10 апреля 2019

В вашем коде немало неправильных вещей (или отсутствующих в зависимости от предоставленного вами примера кода).Во-первых, вам нужно выполнить итерацию ваших данных, чтобы фактически вызвать функцию анализа.В активном режиме вы можете сделать что-то вроде:

for x in dataset:
    print(x)

Во-вторых, вы не можете напрямую вызвать ваш opencv imread на вашем пути, поскольку на этом этапе это tf.Tensor.Посмотрите на map docs, он принимает набор данных в качестве входных данных и возвращает другой набор данных.Поэтому, по крайней мере, вам нужно что-то вроде str(path.numpy()), чтобы преобразовать его обратно в строку, которую вы можете передать в imread.Лучшее предложение - использовать встроенную функцию tenorflow, чтобы прочитать ваш файл, декодировать изображение и затем преобразовать его в numpy.Проверьте tf.io.decode_jpeg

ПРИМЕЧАНИЕ: я использовал tensorflow 2-0-alpha, чтобы дать вам примеры, поэтому в зависимости от вашей версии tf API немного изменится, но идея та же

0 голосов
/ 10 апреля 2019

Чтобы запустить эту функцию предварительной обработки внутри конвейера API набора данных, вам нужно обернуть ее в tf.py_function Это преемник устаревшего py_func. Основное отличие состоит в том, что он может быть установлен на GPU и может работать с любыми тензорами Вы можете прочитать больше в документации.

def preprocess(path, imgSize = (1024, 64), dataAugmentation = False):
    path = path.numpy().decode("utf-8") # .numpy() retrieves data from eager tensor
    img = cv2.imread(path)
    ...
    return img

На данный момент img является. Остальная часть функции зависит от вас

Эта функция синтаксического анализа является оболочкой для конвейера набора данных. Он получает имя файла как тензор с байтовой строкой внутри.

def parse_func(filename):
    out = tf.py_function(preprocess, [filename], tf.uint8)
    return out


dataset = tf.data.Dataset.from_tensor_slices(path)
dataset = dataset.map(pf).batch(1)
iterator = dataset.make_one_shot_iterator()
sess = tf.Session()
print(sess.run(iterator.get_next()))

...