@staticmethod
def add_feature_data(feature, input_df, proc_df, metadata, preprocessing_parameters, backend, skip_save_processed_input):
    in_memory = preprocessing_parameters['in_memory']
    if ((PREPROCESSING in feature) and ('in_memory' in feature[PREPROCESSING])):
        in_memory = feature[PREPROCESSING]['in_memory']
    num_processes = preprocessing_parameters['num_processes']
    if ((PREPROCESSING in feature) and ('num_processes' in feature[PREPROCESSING])):
        num_processes = feature[PREPROCESSING]['num_processes']
    src_path = None
    if (SRC in metadata):
        src_path = os.path.dirname(os.path.abspath(metadata.get(SRC)))
    num_images = len(input_df[feature[COLUMN]])
    if (num_images == 0):
        raise ValueError('There are no images in the dataset provided.')
    first_img_entry = next(iter(input_df[feature[COLUMN]]))
    logger.debug('Detected image feature type is {}'.format(type(first_img_entry)))
    if ((not isinstance(first_img_entry, str)) and (not isinstance(first_img_entry, np.ndarray))):
        raise ValueError('Invalid image feature data type.  Detected type is {}, expect either string for file path or numpy array.'.format(type(first_img_entry)))
    first_img_entry = get_image_from_path(src_path, first_img_entry)
    (should_resize, width, height, num_channels, user_specified_num_channels, first_image) = ImageFeatureMixin._finalize_preprocessing_parameters(preprocessing_parameters, first_img_entry, src_path, input_df[feature[COLUMN]])
    metadata[feature[NAME]][PREPROCESSING]['height'] = height
    metadata[feature[NAME]][PREPROCESSING]['width'] = width
    metadata[feature[NAME]][PREPROCESSING]['num_channels'] = num_channels
    read_image_and_resize = partial(ImageFeatureMixin._read_image_and_resize, img_width=width, img_height=height, should_resize=should_resize, num_channels=num_channels, resize_method=preprocessing_parameters['resize_method'], user_specified_num_channels=user_specified_num_channels)
    backend.check_lazy_load_supported(feature)
    if (in_memory or skip_save_processed_input):
        metadata[feature[NAME]][PREPROCESSING]['num_processes'] = num_processes
        metadata[feature[NAME]]['reshape'] = (height, width, num_channels)
        if (backend.supports_multiprocessing and ((num_processes > 1) or (num_images > 1))):
            all_img_entries = [(get_abs_path(src_path, img_entry) if isinstance(img_entry, str) else img_entry) for img_entry in input_df[feature[COLUMN]]]
            with Pool(num_processes) as pool:
                logger.debug('Using {} processes for preprocessing images'.format(num_processes))
                proc_df[feature[PROC_COLUMN]] = pool.map(read_image_and_resize, all_img_entries)
        else:
            logger.debug('No process pool initialized. Using internal process for preprocessing images')

            def _get_processed_image(img_store):
                if isinstance(img_store, str):
                    return read_image_and_resize(get_abs_path(src_path, img_store))
                else:
                    return read_image_and_resize(img_store)
            proc_df[feature[PROC_COLUMN]] = backend.df_engine.map_objects(input_df[feature[COLUMN]], _get_processed_image)
    else:
        all_img_entries = [(get_abs_path(src_path, img_entry) if isinstance(img_entry, str) else img_entry) for img_entry in input_df[feature[COLUMN]]]
        data_fp = backend.cache.get_cache_path(metadata.get(SRC), metadata.get(CHECKSUM), TRAINING)
        with upload_h5(data_fp) as h5_file:
            image_dataset = h5_file.create_dataset((feature[PROC_COLUMN] + '_data'), (num_images, height, width, num_channels), dtype=np.uint8)
            for (i, img_entry) in enumerate(all_img_entries):
                image_dataset[i, :height, :width, :] = read_image_and_resize(img_entry)
            h5_file.flush()
        proc_df[feature[PROC_COLUMN]] = np.arange(num_images)
    return proc_df
@staticmethod
def add_feature_data(feature, input_df, proc_df, metadata, preprocessing_parameters, backend, skip_save_processed_input):
    in_memory = preprocessing_parameters['in_memory']
    if ((PREPROCESSING in feature) and ('in_memory' in feature[PREPROCESSING])):
        in_memory = feature[PREPROCESSING]['in_memory']
    num_processes = preprocessing_parameters['num_processes']
    if ((PREPROCESSING in feature) and ('num_processes' in feature[PREPROCESSING])):
        num_processes = feature[PREPROCESSING]['num_processes']
    src_path = None
    if (SRC in metadata):
        src_path = os.path.dirname(os.path.abspath(metadata.get(SRC)))
    num_images = len(input_df[feature[COLUMN]])
    if (num_images == 0):
        raise ValueError('There are no images in the dataset provided.')
    first_img_entry = next(iter(input_df[feature[COLUMN]]))
    logger.debug('Detected image feature type is {}'.format(type(first_img_entry)))
    if ((not isinstance(first_img_entry, str)) and (not isinstance(first_img_entry, np.ndarray))):
        raise ValueError('Invalid image feature data type.  Detected type is {}, expect either string for file path or numpy array.'.format(type(first_img_entry)))
    first_img_entry = get_image_from_path(src_path, first_img_entry)
    (should_resize, width, height, num_channels, user_specified_num_channels, first_image) = ImageFeatureMixin._finalize_preprocessing_parameters(preprocessing_parameters, first_img_entry, src_path, input_df[feature[COLUMN]])
    metadata[feature[NAME]][PREPROCESSING]['height'] = height
    metadata[feature[NAME]][PREPROCESSING]['width'] = width
    metadata[feature[NAME]][PREPROCESSING]['num_channels'] = num_channels
    read_image_and_resize = partial(ImageFeatureMixin._read_image_and_resize, img_width=width, img_height=height, should_resize=should_resize, num_channels=num_channels, resize_method=preprocessing_parameters['resize_method'], user_specified_num_channels=user_specified_num_channels)
    backend.check_lazy_load_supported(feature)
    if (in_memory or skip_save_processed_input):
        metadata[feature[NAME]][PREPROCESSING]['num_processes'] = num_processes
        metadata[feature[NAME]]['reshape'] = (height, width, num_channels)
        if (backend.supports_multiprocessing and ((num_processes > 1) or (num_images > 1))):
            all_img_entries = [(get_abs_path(src_path, img_entry) if isinstance(img_entry, str) else img_entry) for img_entry in input_df[feature[COLUMN]]]
            with Pool(num_processes) as pool:
                logger.debug('Using {} processes for preprocessing images'.format(num_processes))
                proc_df[feature[PROC_COLUMN]] = pool.map(read_image_and_resize, all_img_entries)
        else:
            logger.debug('No process pool initialized. Using internal process for preprocessing images')

            def _get_processed_image(img_store):
                if isinstance(img_store, str):
                    return read_image_and_resize(get_abs_path(src_path, img_store))
                else:
                    return read_image_and_resize(img_store)
            proc_df[feature[PROC_COLUMN]] = backend.df_engine.map_objects(input_df[feature[COLUMN]], _get_processed_image)
    else:
        all_img_entries = [(get_abs_path(src_path, img_entry) if isinstance(img_entry, str) else img_entry) for img_entry in input_df[feature[COLUMN]]]
        data_fp = backend.cache.get_cache_path(metadata.get(SRC), metadata.get(CHECKSUM), TRAINING)
        with upload_h5(data_fp) as h5_file:
            image_dataset = h5_file.create_dataset((feature[PROC_COLUMN] + '_data'), (num_images, height, width, num_channels), dtype=np.uint8)
            for (i, img_entry) in enumerate(all_img_entries):
                image_dataset[i, :height, :width, :] = read_image_and_resize(img_entry)
            h5_file.flush()
        proc_df[feature[PROC_COLUMN]] = np.arange(num_images)
    return proc_df