Source code for tfds_defect_detection.utils

import random
import shutil
from pathlib import Path
from typing import Tuple, List

import cv2
import numpy as np
import tensorflow as tf
from tqdm import tqdm


import os, sys


class _HiddenPrints:
    def __enter__(self):
        self._original_stdout = sys.stdout
        sys.stdout = open(os.devnull, 'w')

    def __exit__(self, exc_type, exc_val, exc_tb):
        sys.stdout.close()
        sys.stdout = self._original_stdout

[docs]def mask_by_color(img: tf.Tensor, col: Tuple[int, int, int]) -> tf.Tensor: img = tf.cast(img == col, dtype=tf.uint8) img = tf.reduce_sum(img, axis=-1) == 3 return tf.cast(img, dtype=tf.float32)
[docs]def masking( img: tf.Tensor, class_colors: List[Tuple[int, int, int]], stack_axis=-1 ) -> tf.Tensor: img = tf.image.convert_image_dtype(img, tf.uint8, saturate=True) img = tf.stack([ mask_by_color(img, col) for col in class_colors ], axis=stack_axis) return img
[docs]def rgb_to_onehot(rgb_arr): color_dict = { 0: (0, 0, 0), 1: (255, 255, 255) } num_classes = len(color_dict) shape = rgb_arr.shape[:2] + (num_classes,) arr = np.zeros(shape, dtype=np.int8) for i, cls in enumerate(color_dict): arr[:, :, i] = np.all(rgb_arr.reshape((-1, 3)) == color_dict[i], axis=1).reshape(shape[:2]) return arr
[docs]def onehot_to_rgb(onehot, color_dict): single_layer = np.argmax(onehot, axis=-1) output = np.zeros(onehot.shape[:2] + (3,)) for k in color_dict.keys(): output[single_layer == k] = color_dict[k] return np.uint8(output)
[docs]def sample_more_likely_in_the_middle(range_length): epsilon = 0.000001 percentage = np.clip( random.betavariate(5, 5), a_min=0, a_max=1 - epsilon ) return int(percentage * range_length)
[docs]def random_slice(np_img, width, height=None): if height is None: height = width mask_width, mask_height = np_img.shape[:2] x_min = sample_more_likely_in_the_middle(mask_width - width) y_min = sample_more_likely_in_the_middle(mask_height - height) # x_min = np.clip(x_min, 0, mask_width - width) # y_min = np.clip(y_min, 0, mask_height - height) x_max = x_min + width y_max = y_min + height return np.s_[y_min: y_max, x_min: x_max, ...]
[docs]def combine_binary_masks(mask_1, mask_2): tf.assert_equal(tf.reduce_sum(mask_1), mask_1.shape[0] * mask_1.shape[1] * 1., message="first assertion") tf.assert_equal(tf.reduce_sum(mask_2), mask_2.shape[0] * mask_2.shape[1] * 1., message="second assertion") foreground = mask_1[..., 1] + mask_2[..., 1] foreground = tf.clip_by_value(foreground, 0, 1) ones = tf.ones_like(mask_1[..., 0]) background = ones - foreground result = tf.stack((background, foreground), axis=-1) tf.assert_equal(tf.reduce_sum(result), result.shape[0] * result.shape[1] * 1., message="thirdasserstion") return result
[docs]def blend_merge(foreground, background, mask): mask = cv2.GaussianBlur( np.array(mask * 255, dtype=np.uint8), tuple([3] * 2), 0 # mask.shape[0] // 16 + 1 ) mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) mask = mask.astype('float32') / 255 foreground = cv2.multiply(foreground, mask, dtype=cv2.CV_8U) background = cv2.multiply(background, (1 - mask), dtype=cv2.CV_8U) output = cv2.add(foreground, background) return output
[docs]def validate_images(path: Path): print("Validating files in", path) for path in tqdm(list(path.rglob("*.*"))): try: img = tf.io.read_file(str(path)) # convert the compressed string to a 3D uint8 tensor tf.image.decode_image(img) except: print("could not open", path)
[docs]def copy_to_folder(src: Path, target): target.parent.mkdir(exist_ok=True, parents=True) shutil.copy(src, target)