Example #1
0
def load_slide(slide, fgpth, args):
    fgimg = cv2.imread(fgpth, 0)
    svs = Slide(slide_path=slide,
                background_speed='image',
                background_image=fgimg,
                process_mag=args.mag,
                process_size=args.input_dim,
                oversample_factor=1.5)
    print('loaded slide with {} tiles'.format(len(svs.tile_list)))
    svs.initialize_output('tiles', dim=3, mode='full')
    return svs
Example #2
0
def process_slide(slide_path, fg_path, model, sess, out_dir, process_mag,
                  process_size, oversample, batch_size, n_classes):
    """ Process a slide

  Args:
  slide_path: str
    absolute or relative path to svs formatted slide
  fb_path: str
    absolute or relative path to foreground png
  model: tfmodels.SegmentationBasemodel object
    model definition to use. Weights must be restored first, 
    i.e. call model.restore() before passing model
  sess: tf.Session
  out_dir: str
    path to use for output
  process_mag: int
    Usually one of: 5, 10, 20, 40.
    Other values may work but have not been tested
  process_size: int
    The input size required by model. 
  oversample: float. Usually in [1., 2.]
    How much to oversample between tiles. Larger values 
    will increase processing time.
  batch_size: int
    The batch size for inference. If the batch size is too 
    large given the model and process_size, then OOM errors
    will be raised
  n_classes: int
    The number of classes output by model. 
    i.e. shape(model.yhat) = (batch, h, w, n_classes)
  """

    print('Working {}'.format(slide_path))
    # print('Working {}'.format(fg_path))
    # fgimg = cv2.imread(fg_path, 0)
    # fgimg = cv2.morphologyEx(fgimg, cv2.MORPH_CLOSE,
    #                          cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7)))
    svs = Slide(
        slide_path=slide_path,
        background_speed='all',
        # background_image = fgimg,
        preprocess_fn=preprocess_fn,
        normalize_fn=lambda x: x,
        process_mag=process_mag,
        process_size=process_size,
        oversample=oversample,
        verbose=False,
    )
    svs.initialize_output('prob', dim=n_classes)
    svs.initialize_output('rgb', dim=3)
    PREFETCH = min(len(svs.place_list), 256)

    def wrapped_fn(idx):
        try:
            coords = svs.tile_list[idx]
            img = svs._read_tile(coords)
            return img, idx
        except:
            return 0

    def read_region_at_index(idx):
        return tf.py_func(func=wrapped_fn,
                          inp=[idx],
                          Tout=[tf.float32, tf.int64],
                          stateful=False)

    ds = tf.data.Dataset.from_generator(generator=svs.generate_index,
                                        output_types=tf.int64)
    ds = ds.map(read_region_at_index, num_parallel_calls=6)
    ds = ds.prefetch(PREFETCH)
    ds = ds.batch(batch_size)

    iterator = ds.make_one_shot_iterator()
    img, idx = iterator.get_next()

    print('Processing {} tiles'.format(len(svs.tile_list)))
    tstart = time.time()
    n_processed = 0
    while True:
        try:
            tile, idx_ = sess.run([img, idx])
            output = model.inference(tile)
            svs.place_batch(output, idx_, 'prob')
            svs.place_batch(tile, idx_, 'rgb')

            n_processed += BATCH_SIZE
            if n_processed % PRINT_ITER == 0:
                print('[{:06d}] elapsed time [{:3.3f}]'.format(
                    n_processed,
                    time.time() - tstart))

        except tf.errors.OutOfRangeError:
            print('Finished')
            dt = time.time() - tstart
            spt = dt / float(len(svs.tile_list))
            fps = len(svs.tile_list) / dt
            print('\nFinished. {:2.2f}min {:3.3f}s/tile\n'.format(
                dt / 60., spt))
            print('\t {:3.3f} fps\n'.format(fps))

            svs.make_outputs()
            prob_img = prob_output(svs)
            rgb_img = rgb_output(svs)
            break

        except Exception as e:
            print('Caught exception at tiles {}'.format(idx_))
            # print(e.__doc__)
            # print(e.message)
            prob_img = None
            rgb_img = None
            break

    svs.close()

    return prob_img, rgb_img, fps
Example #3
0
def dump_slide(slide_path, args, return_stack=False):
    basename = os.path.basename(slide_path)
    record_path = os.path.join(args.out_dir, basename.replace('.svs', '.npy'))
    if os.path.exists(record_path):
        print('{} exists'.format(record_path))
        return None

    fgpath = os.path.join(args.fgdir,
                          '{}_fg.png'.format(basename.replace('.svs', '')))
    print('Looking for fg image: {}'.format(fgpath))
    if os.path.exists(fgpath):
        fgimg = cv2.imread(fgpath, 0)
    else:
        print('Foreground image {} not found'.format(fgpath))
        return None

    tmp_path = transfer_to_ramdisk(slide_path)
    print('{} copied to {}'.format(slide_path, tmp_path))

    try:
        svs = Slide(slide_path=tmp_path,
                    background_speed='image',
                    background_image=fgimg,
                    preprocess_fn=lambda x: x,
                    normalize_fn=lambda x: x,
                    process_mag=args.magnification,
                    process_size=args.size,
                    oversample_factor=args.oversample)
        n_tiles = len(svs.tile_list)
        print(n_tiles)

        max_tiles = min(n_tiles, args.max)

        # Save the foreground image for reference
        fg = svs.foreground
        fg_fn = os.path.join(args.out_dir, basename.replace('.svs', '.jpg'))
        cv2.imwrite(fg_fn, fg * 255)

        # Dump tiles sequentially
        img_stack = np.zeros((max_tiles, args.size, args.size, 3),
                             dtype=np.uint8)
        insert_to = 0

        # choice_tiles = np.random.choice(svs.tile_list, max_tiles, replace=False)
        shuffled_tiles = svs.tile_list
        np.random.shuffle(shuffled_tiles)
        # for img, ix in svs.generator():
        for ix, coords in enumerate(shuffled_tiles):
            ## skip missed white space
            img = svs._read_tile(coords)
            img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
            white = (img_gray > 230).sum()
            if white > 0.75 * np.square(args.size):
                continue

            # Control for the skipped white tiles
            img_stack[insert_to, ...] = img
            insert_to += 1
            if insert_to % 250 == 0:
                print('Writing [{} / {}]'.format(insert_to, max_tiles))

            if insert_to + 1 == max_tiles:
                print('Done with {} tiles'.format(insert_to + 1))
                break

        print('Trimming stack : {} -- {}'.format(n_tiles, insert_to))
        img_stack = img_stack[:insert_to - 1, ...]

        if return_stack:
            return img_stack
        else:
            print('Stack size in memory: {}'.format(img_stack.nbytes))
            np.save(record_path, img_stack)
            img_stack = []  ## Clear the big array

    except Exception as e:
        print(e)
    finally:
        os.remove(tmp_path)
        print('Done. {} cleaned.'.format(tmp_path))

    return None
Example #4
0
def main(sess, ramdisk_path, image_op, predict_op):
    input_size = image_op.get_shape().as_list()
    print(input_size)
    x_size, y_size = input_size[1:3]

    PAD = int((x_size - INPUT_SIZE) / 2)

    print('Working {}'.format(ramdisk_path))
    svs = Slide(slide_path=ramdisk_path,
                preprocess_fn=preprocess_fn,
                background_speed='fast',
                process_mag=PROCESS_MAG,
                process_size=INPUT_SIZE,
                oversample_factor=OVERSAMPLE,
                verbose=True)
    print('calculated foregroud: ', svs.foreground.shape)
    print('calculated ds_tile_map: ', svs.ds_tile_map.shape)

    svs.initialize_output('prob', dim=2, mode='tile')
    PREFETCH = min(len(svs.tile_list), 1024)

    def wrapped_fn(idx):
        coords = svs.tile_list[idx]
        img = svs._read_tile(coords)  # (h, w, 3)
        img = np.pad(img,
                     pad_width=((PAD, PAD), (PAD, PAD), (0, 0)),
                     mode='constant',
                     constant_values=0.)
        return img, idx

    def read_region_at_index(idx):
        return tf.py_func(func=wrapped_fn,
                          inp=[idx],
                          Tout=[tf.float32, tf.int64],
                          stateful=False)

    ds = tf.data.Dataset.from_generator(generator=svs.generate_index,
                                        output_types=tf.int64)
    ds = ds.map(read_region_at_index, num_parallel_calls=12)
    ds = ds.prefetch(PREFETCH)
    ds = ds.batch(BATCH_SIZE)

    iterator = ds.make_one_shot_iterator()
    img, idx = iterator.get_next()

    print('Processing {} tiles'.format(len(svs.tile_list)))
    tstart = time.time()
    n_processed = 0
    while True:
        try:
            tile, idx_ = sess.run([img, idx])
            output = sess.run(predict_op, {image_op: tile})
            svs.place_batch(output, idx_, 'prob', mode='tile')

            n_processed += BATCH_SIZE
            if n_processed % PRINT_ITER == 0:
                print('[{:06d}] elapsed time [{:3.3f}] ({})'.format(
                    n_processed,
                    time.time() - tstart, tile.shape))

        except tf.errors.OutOfRangeError:
            print('Finished')
            break
        except Exception as e:
            print(e)
            break

    dt = time.time() - tstart
    spt = dt / float(len(svs.tile_list))
    fps = len(svs.tile_list) / dt
    print('\nFinished. {:2.2f}min {:3.3f}s/tile\n'.format(dt / 60., spt))
    print('\t {:3.3f} fps\n'.format(fps))

    prob_img = prob_output(svs)
    svs.close()

    return prob_img, fps
Example #5
0
        if os.path.exists(v_):
            slide_list.append(v_)
print('Slide list: {}'.format(len(slide_list)))

for i, src in enumerate(slide_list):
    print('\nSlide {}'.format(i))
    basename = os.path.basename(src).replace('.svs', '')
    fgpth = os.path.join(OUTDIR, '{}_fg.png'.format(basename))
    if os.path.exists(fgpth):
        print('{} exists'.format(fgpth))
        continue

    ramdisk_path = transfer_to_ramdisk(src)  # never use the original src
    print('Using fg image at : {}'.format(fgpth))
    try:
        svs = Slide(
            slide_path=ramdisk_path,
            # background_speed  = 'accurate',
            background_speed='accurate',
            preprocess_fn=lambda x: (x / 255.).astype(np.float32),
            process_mag=5,
            process_size=96,
            oversample_factor=1.5,
            verbose=True)
        print('calculated foregroud: ', svs.foreground.shape)
        print('calculated ds_tile_map: ', svs.ds_tile_map.shape)
        cv2.imwrite(fgpth, (svs.ds_tile_map > 0).astype(np.uint8) * 255)
    except:
        print('Slide error')
    finally:
        os.remove(ramdisk_path)
Example #6
0
def process_slide(slide_path, sess, out_dir, process_mag, process_size,
                  oversample, batch_size, n_classes, fgspeed, fgimg):
    """ Process a slide
  # Pytoch - compatible mode: uses sess only for the loading pipeline

  Args:
  slide_path: str
    absolute or relative path to svs formatted slide
  model: tfmodels.SegmentationBasemodel object
    model definition to use. Weights must be restored first, 
    i.e. call model.restore() before passing model
  sess: tf.Session
  out_dir: str
    path to use for output
  process_mag: int
    Usually one of: 5, 10, 20, 40.
    Other values may work but have not been tested
  process_size: int
    The input size required by model. 
  oversample: float. Usually in [1., 2.]
    How much to oversample between tiles. Larger values 
    will increase processing time.
  batch_size: int
    The batch size for inference. If the batch size is too 
    large given the model and process_size, then OOM errors
    will be raised
  n_classes: int
    The number of classes output by model. 
    i.e. shape(model.yhat) = (batch, h, w, n_classes)
  """

    try:
        print('Working {}'.format(slide_path))
        svs = Slide(
            slide_path=slide_path,
            preprocess_fn=lambda x: x.astype(np.float32),
            normalize_fn=lambda x: x,
            process_mag=process_mag,
            process_size=process_size,
            oversample=oversample,
            background_speed=fgspeed,
            background_img=fgimg,
            verbose=False,
        )
        # svs.initialize_output('prob', dim=n_classes)
        svs.initialize_output('rgb', dim=3)
        svs.initialize_output('prob', dim=n_classes, mode='tile')
        PREFETCH = min(len(svs.place_list), 1024)
    except Exception as e:
        print(e)
        print("Error loading slide at {}".format(slide_path))
        return None, None, None

    def wrapped_fn(idx):
        try:
            coords = svs.tile_list[idx]
            img = svs._read_tile(coords)
            return img, idx
        except:
            return 0

    def read_region_at_index(idx):
        return tf.py_func(func=wrapped_fn,
                          inp=[idx],
                          Tout=[tf.float32, tf.int64],
                          stateful=False)

    ds = tf.data.Dataset.from_generator(generator=svs.generate_index,
                                        output_types=tf.int64)
    ds = ds.map(read_region_at_index, num_parallel_calls=8)
    ds = ds.prefetch(PREFETCH)
    ds = ds.batch(batch_size)

    iterator = ds.make_one_shot_iterator()
    img, idx = iterator.get_next()

    print('Processing {} tiles'.format(len(svs.tile_list)))
    tstart = time.time()
    n_processed = 0
    while True:
        try:
            tile, idx_ = sess.run([img, idx])
            svs.place_batch(tile, idx_, 'rgb', clobber=True)

            n_processed += BATCH_SIZE
            if n_processed % PRINT_ITER == 0:
                print('[{:06d}] elapsed time [{:3.3f}]'.format(
                    n_processed,
                    time.time() - tstart))

        except tf.errors.OutOfRangeError:
            dt = time.time() - tstart
            spt = dt / float(len(svs.tile_list))
            fps = len(svs.tile_list) / dt
            print('\nFinished. {:2.2f}min {:3.3f}s/tile\n'.format(
                dt / 60., spt))
            print('{:3.3f} fps\n'.format(fps))

            # svs.make_outputs()
            rgb_img = rgb_output(svs)
            break

        except Exception as e:
            print('Caught exception at tiles {}'.format(idx_))
            # print(e.__doc__)
            print(e)
            rgb_img = None
            break

    svs.close()

    # Replace pure black with white
    bwimg = np.mean(rgb_img, axis=-1)
    img_b = bwimg < 10
    rgb_img[img_b, :] = 255
    return rgb_img, fps
Example #7
0
def main(args):
    # Translate obfuscated file names to paths if necessary
    slide_list = read_list(args.f)
    print('Found {} slides'.format(len(slide_list)))

    encoder_args = get_encoder_args(args.encoder)
    model = MilkEager(encoder_args=encoder_args,
                      mil_type=args.mil,
                      batch_size=args.batch_size,
                      temperature=args.temperature,
                      deep_classifier=args.deep_classifier)

    x_pl = np.zeros((1, args.batch_size, args.input_dim, args.input_dim, 3),
                    dtype=np.float32)
    yhat = model(tf.constant(x_pl), verbose=True)
    print('yhat:', yhat.shape)

    print('setting model weights')
    model.load_weights(args.s, by_name=True)

    ## Loop over found slides:
    yhats = []
    for i, src in enumerate(slide_list):
        print('\nSlide {}'.format(i))
        basename = os.path.basename(src).replace('.svs', '')
        fgpth = os.path.join(args.fg, '{}_fg.png'.format(basename))
        if os.path.exists(fgpth):
            ramdisk_path = transfer_to_ramdisk(
                src, args.ramdisk)  # never use the original src
            print('Using fg image at : {}'.format(fgpth))
            fgimg = cv2.imread(fgpth, 0)
            try:
                svs = Slide(
                    slide_path=ramdisk_path,
                    # background_speed  = 'accurate',
                    background_speed='image',
                    background_image=fgimg,
                    preprocess_fn=lambda x: (x / 255.).astype(np.float32),
                    normalize_fn=lambda x: x,
                    process_mag=args.mag,
                    process_size=args.input_dim,
                    oversample_factor=args.oversample,
                    verbose=False)
            except Exception as e:
                print(e)
                print(
                    'Caught SVS related error. Cleaning ramdisk and continuing.'
                )
                print('Cleaning file: {}'.format(ramdisk_path))
                os.remove(ramdisk_path)
                continue
        else:
            print(fgpth)
            continue

        svs.initialize_output(name='attention', dim=1, mode='tile')
        yhat, att, indices = process_slide(svs, model, args)

        yhats.append(yhat)
        print('\tSlide predicted: {}'.format(yhat))

        if args.mil == 'average':
            print('Average MIL; continuing')
        elif args.mil in ['attention', 'instance']:
            print('Placing values ranged {:3.3f} - {:3.3f}'.format(
                att.min(), att.max()))
            print('Visualizing mean {:3.5f}'.format(np.mean(att)))
            print('Visualizing std {:3.5f}'.format(np.std(att)))
            svs.place_batch(att, indices, 'attention', mode='tile')
            attention_img = np.squeeze(svs.output_imgs['attention'])
            attention_img_raw = np.squeeze(svs.output_imgs['attention'])

            attention_img = attention_img * (1. / attention_img.max())
            attention_img = draw_attention(attention_img, n_bins=50)
            print('attention image:', attention_img.shape, attention_img.dtype,
                  attention_img.min(), attention_img.max())

            dst = os.path.join(args.o, '{}_att.npy'.format(basename))
            np.save(dst, attention_img_raw)
            dst = os.path.join(args.o, '{}_img.png'.format(basename))
            cv2.imwrite(dst, attention_img)

        yhat_dst = os.path.join(args.o, '{}_ypred.npy'.format(basename))
        np.save(yhat_dst, yhat)

        try:
            svs.close()
            os.remove(ramdisk_path)
            del svs
        except:
            print('{} already removed'.format(ramdisk_path))
Example #8
0
def main(args):
    # Translate obfuscated file names to paths if necessary
    test_list = os.path.join(args.testdir, '{}.txt'.format(args.timestamp))
    test_list = read_test_list(test_list)
    test_unique_ids = [
        os.path.basename(x).replace('.npy', '') for x in test_list
    ]
    if args.randomize:
        np.random.shuffle(test_unique_ids)

    if args.max_slides:
        test_unique_ids = test_unique_ids[:args.max_slides]

    slide_list, slide_labels = get_slidelist_from_uids(test_unique_ids)

    print('Found {} slides'.format(len(slide_list)))

    snapshot = os.path.join(args.savedir, '{}.h5'.format(args.timestamp))
    # trained_model = load_model(snapshot)
    # if args.mcdropout:
    #   encoder_args['mcdropout'] = True

    encoder_args = get_encoder_args(args.encoder)
    model = MilkEager(encoder_args=encoder_args,
                      mil_type=args.mil,
                      batch_size=args.batch_size,
                      deep_classifier=args.deep_classifier,
                      temperature=args.temperature)

    x_pl = np.zeros((1, args.batch_size, args.input_dim, args.input_dim, 3),
                    dtype=np.float32)
    yhat = model(tf.constant(x_pl), verbose=True)
    print('yhat:', yhat.shape)

    print('setting model weights')
    model.load_weights(snapshot, by_name=True)

    ## Loop over found slides:
    yhats = []
    ytrues = []
    for i, (src, lab) in enumerate(zip(slide_list, slide_labels)):
        print('\nSlide {}'.format(i))
        basename = os.path.basename(src).replace('.svs', '')
        fgpth = os.path.join(args.fgdir, '{}_fg.png'.format(basename))
        if os.path.exists(fgpth):
            ramdisk_path = transfer_to_ramdisk(
                src, args.ramdisk)  # never use the original src
            print('Using fg image at : {}'.format(fgpth))
            fgimg = cv2.imread(fgpth, 0)
            svs = Slide(
                slide_path=ramdisk_path,
                # background_speed  = 'accurate',
                background_speed='image',
                background_image=fgimg,
                # preprocess_fn     = lambda x: (reinhard(x)/255.).astype(np.float32),
                preprocess_fn=lambda x: (x / 255.).astype(np.float32),
                process_mag=args.mag,
                process_size=args.input_dim,
                oversample_factor=args.oversample,
                verbose=False)
        else:
            ## require precomputed background; Exit.
            print('Required foreground image not found ({})'.format(fgpth))
            continue

        svs.initialize_output(name='attention', dim=1, mode='tile')
        n_tiles = len(svs.tile_list)

        yhat, att, indices = process_slide(svs, model, args)
        print('returned attention:', np.min(att), np.max(att), att.shape)

        yhat = yhat.numpy()
        yhats.append(yhat)
        ytrues.append(lab)
        print('\tSlide label: {} predicted: {}'.format(lab, yhat))

        svs.place_batch(att, indices, 'attention', mode='tile')
        attention_img = np.squeeze(svs.output_imgs['attention'])
        attention_img = attention_img * (1. / attention_img.max())
        attention_img = draw_attention(attention_img, n_bins=25)
        print('attention image:', attention_img.shape, attention_img.dtype,
              attention_img.min(), attention_img.max())

        dst = os.path.join(
            args.odir, args.timestamp,
            '{}_{}_{:3.3f}_att.npy'.format(basename, lab, yhat[0, 1]))
        np.save(dst, att)

        dst = os.path.join(
            args.odir, args.timestamp,
            '{}_{}_{:3.3f}_img.png'.format(basename, lab, yhat[0, 1]))
        cv2.imwrite(dst, attention_img)

        try:
            svs.close()
            os.remove(ramdisk_path)
        except:
            print('{} already removed'.format(ramdisk_path))

    yhats = np.concatenate(yhats, axis=0)
    ytrues = np.array(ytrues)
    acc = (np.argmax(yhats, axis=-1) == ytrues).mean()
    print(acc)
Example #9
0
import numpy as np
import time

from svs_reader import Slide
slide_path = '/home/ing/tmp_svs.svs'

svs = Slide(slide_path = slide_path,
            oversample_factor = 2.0)

def blue_content(tile):
    blue_channel = tile[:,:,1]
    return np.mean(blue_channel)

svs.initialize_output(name='blue', dim=1, mode='tile')
print(svs.output_imgs['blue'].shape)

tstart = time.time()
for img, idx in svs.generator():
    blue_result = blue_content(img)
    
    # place the result into the output image we just initialized
    svs.place(x=blue_result, idx=idx, name='blue', mode='tile')

tend = time.time()

print('processed {} tiles'.format(len(svs.tile_list)))
print('tdelta = {:3.5f}'.format(tend-tstart))
Example #10
0
def main(args):
    ## Search for slides
    # slide_list = sorted(glob.glob(os.path.join(args.slide_dir, '*.svs')))
    slide_list = read_list(args.slide_list)
    print('Found {} slides'.format(len(slide_list)))
    if args.shuffle:
        np.random.shuffle(slide_list)

    encoder_args = get_encoder_args(args.encoder)
    model = ClassifierEager(encoder_args=encoder_args,
                            deep_classifier=True,
                            n_classes=args.n_classes)
    fake_data = tf.constant(
        np.zeros((1, args.input_dim, args.input_dim, 3), dtype=np.float32))
    yhat_ = model(fake_data)
    model.load_weights(args.snapshot)
    model.summary()
    if not os.path.exists(args.save_dir):
        # shutil.rmtree(args.save_dir)
        os.makedirs(args.save_dir)

    ## Loop over found slides:
    for src in slide_list:
        basename = os.path.basename(src).replace('.svs', '')
        dst = os.path.join(args.save_dir, '{}.npy'.format(basename))
        if os.path.exists(dst):
            print('{} exists. Skipping'.format(dst))
            continue

        ramdisk_path = transfer_to_ramdisk(
            src, args.ramdisk)  # never use the original src
        try:
            fgpth = os.path.join(args.fgdir, '{}_fg.png'.format(basename))
            fgimg = cv2.imread(fgpth, 0)
            fgimg = fill_fg(fgimg)
            svs = Slide(slide_path=ramdisk_path,
                        preprocess_fn=lambda x: (x / 255.).astype(np.float32),
                        normalize_fn=lambda x: x,
                        background_speed='image',
                        background_image=fgimg,
                        process_mag=args.mag,
                        process_size=args.input_dim,
                        oversample_factor=1.1)
            svs.initialize_output(name='prob', dim=args.n_classes, mode='full')
            svs.initialize_output(name='rgb', dim=3, mode='full')
            n_tiles = len(svs.tile_list)
            prefetch = min(512, n_tiles)
            # Get tensors for image an index
            iterator = get_img_idx(svs, args.batch_size, prefetch)
            batches = 0
            for img_, idx_ in iterator:
                batches += 1
                yhat = model(img_, training=False)
                yhat = yhat.numpy()
                idx_ = idx_.numpy()
                img_ = img_.numpy()
                yhat = vect_to_tile(yhat, args.input_dim)
                svs.place_batch(yhat, idx_, 'prob', mode='full')
                svs.place_batch(img_, idx_, 'rgb', mode='full')
                if batches % 50 == 0:
                    print('\tbatch {:04d}'.format(batches))

            svs.make_outputs(reference='prob')
            prob_img = svs.output_imgs['prob']
            rgb_img = svs.output_imgs['rgb'] * 255
            color_img = colorize(rgb_img, prob_img)
            dst = os.path.join(args.save_dir, '{}.npy'.format(basename))
            np.save(dst, (prob_img * 255).astype(np.uint8))
            dst = os.path.join(args.save_dir, '{}.jpg'.format(basename))
            cv2.imwrite(dst, rgb_img[:, :, ::-1])
            dst = os.path.join(args.save_dir, '{}_c.jpg'.format(basename))
            cv2.imwrite(dst, color_img[:, :, ::-1])
        except Exception as e:
            print(e)
        finally:
            try:
                print('Closing SVS')
                svs.close()
            except:
                print('No SVS to close')

            os.remove(ramdisk_path)
Example #11
0
def main(args, sess):
    ## Search for slides
    slide_list = sorted(glob.glob(os.path.join(args.slide_dir, '*.svs')))
    print('Found {} slides'.format(len(slide_list)))

    if args.shuffle:
        np.random.shuffle(slide_list)

    model = load_model(args.snapshot)

    ## Loop over found slides:
    for src in slide_list[:5]:

        ramdisk_path = transfer_to_ramdisk(
            src, args.ramdisk)  # never use the original src
        svs = Slide(slide_path=ramdisk_path,
                    preprocess_fn=lambda x: (x / 255.).astype(np.float32),
                    process_mag=args.mag,
                    process_size=args.input_dim,
                    oversample_factor=1.5)
        svs.initialize_output(name='prob', dim=args.n_classes, mode='full')
        svs.initialize_output(name='rgb', dim=3, mode='full')

        n_tiles = len(svs.tile_list)
        prefetch = min(512, n_tiles)

        # Get tensors for image an index
        img, idx = get_img_idx(svs, args.batch_size, prefetch)
        yhat_op = model(img)

        batches = 0
        while True:
            try:
                batches += 1
                yhat, img_, idx_ = sess.run([yhat_op, img, idx])
                yhat = vect_to_tile(yhat, args.input_dim)
                svs.place_batch(yhat, idx_, 'prob', mode='full')
                svs.place_batch(img_, idx_, 'rgb', mode='full')
                if batches % 50 == 0:
                    print('batch {:04d}'.format(batches))
            except tf.errors.OutOfRangeError:
                print('Done')
                break

        svs.make_outputs(reference='prob')
        prob_img = svs.output_imgs['prob']
        rgb_img = svs.output_imgs['rgb'] * 255
        color_img = colorize(rgb_img, prob_img)

        basename = os.path.basename(src).replace('.svs', '')
        dst = os.path.join(args.save_dir, '{}.npy'.format(basename))
        np.save(dst, (prob_img * 255).astype(np.uint8))
        dst = os.path.join(args.save_dir, '{}.jpg'.format(basename))
        cv2.imwrite(dst, rgb_img[:, :, ::-1])
        dst = os.path.join(args.save_dir, '{}_c.jpg'.format(basename))
        cv2.imwrite(dst, color_img[:, :, ::-1])

        os.remove(ramdisk_path)
Example #12
0
def main(args):
    ## Search for slides
    slide_list = sorted(glob.glob(os.path.join(args.slide_dir, '*.svs')))
    print('Found {} slides'.format(len(slide_list)))

    if args.shuffle:
        np.random.shuffle(slide_list)

    model = ClassifierEager(encoder_args=encoder_args,
                            n_classes=args.n_classes)
    xdummy = tf.constant(
        np.zeros((args.batch_size, args.input_dim, args.input_dim, 3),
                 dtype=np.float32))
    yhat_op = model(xdummy, verbose=True)
    model.load_weights(args.snapshot, by_name=True)

    # model = tf.keras.models.load_model(args.snapshot, compile=False)
    model.summary()

    ## Loop over found slides:
    for src in slide_list:
        basename = os.path.basename(src).replace('.svs', '')
        dst = os.path.join(args.save_dir, '{}.npy'.format(basename))

        if os.path.exists(dst):
            print('{} exists. continuing'.format(dst))
            continue

        fgpth = os.path.join(args.fgdir, '{}_fg.png'.format(basename))
        if os.path.exists(fgpth):
            print('fg image found:', fgpth)
            fgimg = cv2.imread(fgpth, 0)
            speed = 'image'
        else:
            speed = 'fast'
            fgimg = None

        ramdisk_path = transfer_to_ramdisk(
            src, args.ramdisk)  # never use the original src
        try:
            svs = Slide(slide_path=ramdisk_path,
                        preprocess_fn=lambda x:
                        (reinhard(x) / 255.).astype(np.float32),
                        background_speed=speed,
                        background_image=fgimg,
                        process_mag=args.mag,
                        process_size=args.input_dim,
                        oversample_factor=1.75)

            svs.initialize_output(name='prob', dim=args.n_classes, mode='full')
            svs.initialize_output(name='rgb', dim=3, mode='full')

            n_tiles = len(svs.tile_list)
            prefetch = min(128, n_tiles)
            print('Tiles:', n_tiles)

            # Get tensors for image an index
            # img, idx = get_img_idx(svs, args.batch_size, prefetch)
            iterator = get_iterator(svs, args.batch_size, prefetch)

            batches = 0
            for img_, idx_ in iterator:
                batches += 1
                # img_, idx_ = next(iterator)

                yhat = model(img_, training=False)
                yhat = yhat.numpy()
                idx_ = idx_.numpy()

                yhat = vect_to_tile(yhat, args.input_dim)
                svs.place_batch(yhat, idx_, 'prob', mode='full')
                svs.place_batch(img_.numpy(), idx_, 'rgb', mode='full')
                if batches % 50 == 0:
                    print('batch {:04d}'.format(batches))

            print('Making outputs')
            svs.make_outputs(reference='prob')
            prob_img = svs.output_imgs['prob']
            print('prob img', prob_img.shape)

            rgb_img = svs.output_imgs['rgb'] * 255
            print('rgb img', rgb_img.shape)

            color_img = colorize(rgb_img, prob_img)
            print('color img', color_img.shape)

            dst = os.path.join(args.save_dir, '{}.npy'.format(basename))
            np.save(dst, (prob_img * 255).astype(np.uint8))
            dst = os.path.join(args.save_dir, '{}.jpg'.format(basename))
            cv2.imwrite(dst, rgb_img[:, :, ::-1])
            dst = os.path.join(args.save_dir, '{}_c.jpg'.format(basename))
            cv2.imwrite(dst, color_img[:, :, ::-1])

            svs.close()
            svs = []

        except Exception as e:
            print(e)

        finally:
            print('Removing {}'.format(ramdisk_path))
            os.remove(ramdisk_path)
Example #13
0
def main(args, sess):
    # Translate obfuscated file names to paths if necessary
    test_list = os.path.join(args.testdir, '{}.txt'.format(args.timestamp))
    test_list = read_test_list(test_list)
    test_unique_ids = [
        os.path.basename(x).replace('.npy', '') for x in test_list
    ]
    if args.randomize:
        np.random.shuffle(test_unique_ids)
    slide_list, slide_labels = get_slidelist_from_uids(test_unique_ids)

    print('Found {} slides'.format(len(slide_list)))

    snapshot = os.path.join(args.savedir, '{}.h5'.format(args.timestamp))
    # trained_model = load_model(snapshot)
    # if args.mcdropout:
    #   encoder_args['mcdropout'] = True

    encode_model = MilkEncode(input_shape=(args.input_dim, args.input_dim, 3),
                              encoder_args=encoder_args,
                              deep_classifier=args.deep_classifier)

    x_pl = tf.placeholder(shape=(None, args.input_dim, args.input_dim, 3),
                          dtype=tf.float32)
    z_op = encode_model(x_pl)

    input_shape = z_op.shape[-1]
    predict_model = MilkPredict(input_shape=[input_shape],
                                mode=args.mil,
                                use_gate=args.gated_attention,
                                deep_classifier=args.deep_classifier)
    attention_model = MilkAttention(input_shape=[input_shape],
                                    use_gate=args.gated_attention)

    print('setting encoder weights')
    encode_model.load_weights(snapshot, by_name=True)
    print('setting predict weights')
    predict_model.load_weights(snapshot, by_name=True)
    print('setting attention weights')
    attention_model.load_weights(snapshot, by_name=True)

    z_pl = tf.placeholder(shape=(None, input_shape), dtype=tf.float32)
    y_op = predict_model(z_pl)
    att_op = attention_model(z_pl)

    # fig = plt.figure(figsize=(2,2), dpi=180)

    ## Loop over found slides:
    yhats = []
    ytrues = []
    for i, (src, lab) in enumerate(zip(slide_list, slide_labels)):
        print('\nSlide {}'.format(i))
        basename = os.path.basename(src).replace('.svs', '')
        fgpth = os.path.join(args.fgdir, '{}_fg.png'.format(basename))
        if os.path.exists(fgpth):
            ramdisk_path = transfer_to_ramdisk(
                src, args.ramdisk)  # never use the original src
            print('Using fg image at : {}'.format(fgpth))
            fgimg = cv2.imread(fgpth, 0)
            svs = Slide(
                slide_path=ramdisk_path,
                # background_speed  = 'accurate',
                background_speed='image',
                background_image=fgimg,
                preprocess_fn=lambda x: (x / 255.).astype(np.float32),
                process_mag=args.mag,
                process_size=args.input_dim,
                oversample_factor=args.oversample,
                verbose=False)
        else:
            ## require precomputed background; Exit.
            print('Required foreground image not found ({})'.format(fgpth))
            continue

        svs.initialize_output(name='attention', dim=1, mode='tile')
        n_tiles = len(svs.tile_list)

        if not args.mcdropout:
            yhat, att, indices = process_slide(svs, encode_model, y_op, att_op,
                                               z_pl, args)
        else:
            yhat, att, yhat_sd, att_sd, indices = process_slide_mcdropout(
                svs, encode_model, y_op, att_op, z_pl, args)

        yhats.append(yhat)
        ytrues.append(lab)
        print('\tSlide label: {} predicted: {}'.format(lab, yhat))

        svs.place_batch(att, indices, 'attention', mode='tile')
        attention_img = np.squeeze(svs.output_imgs['attention'])
        attention_img = attention_img * (1. / attention_img.max())
        attention_img = draw_attention(attention_img, n_bins=50)
        print('attention image:', attention_img.shape, attention_img.dtype,
              attention_img.min(), attention_img.max())

        dst = os.path.join(args.odir, args.timestamp,
                           '{}_att.npy'.format(basename))
        np.save(dst, att)

        dst = os.path.join(args.odir, args.timestamp,
                           '{}_img.png'.format(basename))
        cv2.imwrite(dst, attention_img)

        # dst = os.path.join(args.odir, args.timestamp, '{}_hist.png'.format(basename))
        # fig.clf()
        # plt.hist(att, bins=100);
        # plt.title('Attention distribution\n{} ({} tiles)'.format(basename, n_tiles))
        # plt.xlabel('Attention score')
        # plt.ylabel('Tile count')
        # plt.savefig(dst, bbox_inches='tight')

        try:
            svs.close()
            os.remove(ramdisk_path)
        except:
            print('{} already removed'.format(ramdisk_path))
Example #14
0
def main(args, sess):
    dst = os.path.join(args.odir, 'auc_{}.png'.format(args.timestamp))
    if os.path.exists(dst):
        print('{} exists. Exiting.'.format(dst))
        return

    # Translate obfuscated file names to paths if necessary
    test_list = os.path.join(args.testdir, '{}.txt'.format(args.timestamp))
    test_list = read_test_list(test_list)
    test_unique_ids = [
        os.path.basename(x).replace('.npy', '') for x in test_list
    ]
    slide_list, slide_labels = get_slidelist_from_uids(test_unique_ids)

    print('Found {} slides'.format(len(slide_list)))

    snapshot = os.path.join(args.savedir, '{}.h5'.format(args.timestamp))
    trained_model = load_model(snapshot)
    if args.mcdropout:
        encoder_args['mcdropout'] = True

    encode_model = MilkEncode(input_shape=(args.input_dim, args.input_dim, 3),
                              encoder_args=encoder_args)
    encode_shape = list(encode_model.output.shape)
    predict_model = MilkPredict(input_shape=[512],
                                mode=args.mil,
                                use_gate=args.gated_attention)
    # attention_model = MilkAttention(input_shape=[512], use_gate=args.gated_attention)

    models = model_utils.make_inference_functions(
        encode_model,
        predict_model,
        trained_model,
    )
    encode_model, predict_model = models

    z_pl = tf.placeholder(shape=(None, 512), dtype=tf.float32)
    y_op = predict_model(z_pl)

    fig = plt.figure(figsize=(2, 2), dpi=180)

    ## Loop over found slides:
    yhats = []
    ytrues = []
    for i, (src, lab) in enumerate(zip(slide_list, slide_labels)):
        print('\nSlide {}'.format(i))
        basename = os.path.basename(src).replace('.svs', '')
        fgpth = os.path.join(args.fgdir, '{}_fg.png'.format(basename))
        if os.path.exists(fgpth):
            ramdisk_path = transfer_to_ramdisk(
                src, args.ramdisk)  # never use the original src
            print('Using fg image at : {}'.format(fgpth))
            fgimg = cv2.imread(fgpth, 0)
            print('fgimg shape: ', fgimg.shape)
            svs = Slide(
                slide_path=ramdisk_path,
                # background_speed  = 'accurate',
                background_speed='image',
                background_image=fgimg,
                preprocess_fn=lambda x: (x / 255.).astype(np.float32),
                process_mag=args.mag,
                process_size=args.input_dim,
                oversample_factor=1.5,
                verbose=True)
            print('calculated foregroud: ', svs.foreground.shape)
            print('calculated ds_tile_map: ', svs.ds_tile_map.shape)
        else:
            ## Require precomputed background
            print('No fg image found ({})'.format(fgpth))
            continue

        n_tiles = len(svs.tile_list)

        if not args.mcdropout:
            yhat, indices = process_slide(svs, sess, encode_model, y_op, z_pl,
                                          args)
        else:
            yhat, yhat_sd, indices = process_slide_mcdropout(
                svs, sess, encode_model, y_op, z_pl, args)

        yhats.append(yhat)
        ytrues.append(lab)
        print('\tSlide label: {} predicted: {}'.format(lab, yhat))
        os.remove(ramdisk_path)
        svs.close()
        del svs

    yhats = np.concatenate(yhats, axis=0)
    ytrue = np.array(ytrues)
    for i, yt in enumerate(ytrue):
        print(yt, yhats[i, :])

    auc_curve(ytrue, yhats, savepath=dst)
    del encode_model
    del predict_model
Example #15
0
import numpy as np
import tensorflow as tf
import time

from svs_reader import Slide

slide_path = '/home/ing/tmp_svs.svs'

# Set up a new slide that returns images in float32, via preprocess_fn
preprocess_fn = lambda x: (x / 255.).astype(np.float32)
svs = Slide(slide_path = slide_path,
            oversample_factor = 2.0,
            preprocess_fn = preprocess_fn)

# This function looks up coordinates then loads image content
def wrapped_fn(idx):
    coords = svs.tile_list[idx]
    img = svs._read_tile(coords)
    return img, idx

# mapped function produces image and index tuple. 
# the image is float, the index is int
def read_region_at_index(idx):
    return tf.py_func(func     = wrapped_fn,
                      inp      = [idx],
                      Tout     = [tf.float32, tf.int64],
                      stateful = False)

# The generator produces indices
ds = tf.data.Dataset.from_generator(generator=svs.generate_index,
    output_types=tf.int64)
Example #16
0
def main(args, sess):
    # Translate obfuscated file names to paths if necessary
    test_list = os.path.join(args.testdir, '{}.txt'.format(args.timestamp))
    test_list = read_test_list(test_list)
    test_unique_ids = [
        os.path.basename(x).replace('.npy', '') for x in test_list
    ]
    slide_list, slide_labels = get_slidelist_from_uids(test_unique_ids)

    print('Found {} slides'.format(len(slide_list)))

    snapshot = os.path.join(args.savedir, '{}.h5'.format(args.timestamp))
    trained_model = load_model(snapshot)
    encoder_args = {
        'depth_of_model': 32,
        'growth_rate': 64,
        'num_of_blocks': 4,
        'output_classes': 2,
        'num_layers_in_each_block': 8,
    }
    if args.mcdropout:
        encoder_args['mcdropout'] = True

    encode_model = MilkEncode(input_shape=(args.input_dim, args.input_dim, 3),
                              encoder_args=encoder_args)
    encode_shape = list(encode_model.output.shape)
    predict_model = MilkPredict(input_shape=[512],
                                mode=args.mil,
                                use_gate=args.gated_attention)
    attention_model = MilkAttention(input_shape=[512],
                                    use_gate=args.gated_attention)

    models = model_utils.make_inference_functions(
        encode_model,
        predict_model,
        trained_model,
        attention_model=attention_model)
    encode_model, predict_model, attention_model = models

    z_pl = tf.placeholder(shape=(None, 512), dtype=tf.float32)
    y_op = predict_model(z_pl)
    att_op = attention_model(z_pl)

    fig = plt.figure(figsize=(2, 2), dpi=180)

    ## Loop over found slides:
    yhats = []
    ytrues = []
    for i, (src, lab) in enumerate(zip(slide_list, slide_labels)):
        print('\nSlide {}'.format(i))
        basename = os.path.basename(src).replace('.svs', '')
        fgpth = os.path.join(args.fgdir, '{}_fg.png'.format(basename))
        if os.path.exists(fgpth):
            ramdisk_path = transfer_to_ramdisk(
                src, args.ramdisk)  # never use the original src
            print('Using fg image at : {}'.format(fgpth))
            fgimg = cv2.imread(fgpth, 0)
            print('fgimg shape: ', fgimg.shape)
            svs = Slide(
                slide_path=ramdisk_path,
                # background_speed  = 'accurate',
                background_speed='image',
                background_image=fgimg,
                preprocess_fn=lambda x: (x / 255.).astype(np.float32),
                process_mag=args.mag,
                process_size=args.input_dim,
                oversample_factor=1.5,
                verbose=True)
            print('calculated foregroud: ', svs.foreground.shape)
            print('calculated ds_tile_map: ', svs.ds_tile_map.shape)
        else:
            ## Require precomputed background
            print('No fg image found ({})'.format(fgpth))
            continue

        svs.initialize_output(name='attention', dim=1, mode='tile')
        n_tiles = len(svs.tile_list)

        if not args.mcdropout:
            yhat, att, indices = process_slide(svs, encode_model, y_op, att_op,
                                               z_pl, args)
        else:
            yhat, att, yhat_sd, att_sd, indices = process_slide_mcdropout(
                svs, encode_model, y_op, att_op, z_pl, args)
            # svs.initialize_output(name='attention_std', dim=1, mode='tile')
            # svs.place_batch(att_sd, indices, 'attention_std', mode='tile')
            # attention_sd_img = svs.output_imgs['attention_std']
            # attention_sd_img = attention_sd_img * (255. / attention_sd_img.max())
            # dst = os.path.join(args.odir, '{}_{}_{}_attsd.png'.format(basename, args.timestamp, args.suffix))
            # cv2.imwrite(dst, attention_sd_img)

        yhats.append(yhat)
        ytrues.append(lab)
        print('\tSlide label: {} predicted: {}'.format(lab, yhat))

        svs.place_batch(att, indices, 'attention', mode='tile')
        attention_img = svs.output_imgs['attention']
        print('attention image:', attention_img.shape, attention_img.dtype,
              attention_img.min(), attention_img.max())
        attention_img = attention_img * (255. / attention_img.max())

        dst = os.path.join(args.odir, args.timestamp,
                           '{}_att.png'.format(basename))
        cv2.imwrite(dst, attention_img)

        dst = os.path.join(args.odir, args.timestamp,
                           '{}_hist.png'.format(basename))
        fig.clf()
        plt.hist(att, bins=100)
        plt.title('Attention distribution\n{} ({} tiles)'.format(
            basename, n_tiles))
        plt.xlabel('Attention score')
        plt.ylabel('Tile count')
        plt.savefig(dst, bbox_inches='tight')

        os.remove(ramdisk_path)