Ejemplo n.º 1
0
    def center_camera(self):
        '''Center the camera at whatever interesting thing this class displays
        '''

        transforms = _get_transforms(self.ImageTransformViewList)
        bbox = utils.FixedBoundingBox(transforms)
        bbox_rect = nornir_imageregistration.spatial.Rectangle.CreateFromBounds(
            bbox)
        self.camera.lookat(bbox_rect.Center)
        self.camera.scale = bbox_rect.Width
Ejemplo n.º 2
0
 def VolumeBounds(self):
     # Boundaries of the volume based on locations where sections will map points into the volume
     return tutils.FixedBoundingBox(self.SectionToVolumeTransforms.values())
def TilesToImage(transforms,
                 imagepaths,
                 TargetRegion=None,
                 target_space_scale=None,
                 source_space_scale=None):
    '''
    Generate an image of the TargetRegion.
    :param tuple TargetRegion: (MinX, MinY, Width, Height) or Rectangle class.  Specifies the SourceSpace to render from
    :param float target_space_scale: Scalar for the target space coordinates.  Used to downsample or upsample the output image.  Changes the coordinates of the target space control points of the transform. 
    :param float target_space_scale: Scalar for the source space coordinates.  Must match the change in scale of input images relative to the transform source space coordinates.  So if downsampled by
    4 images are used, this value should be 0.25.  Calculated to be correct if None.  Specifying is an optimization to reduce I/O of reading image files to calculate.
    '''

    assert (len(transforms) == len(imagepaths))

    # logger = logging.getLogger(__name__ + '.TilesToImage')
    if source_space_scale is None:
        source_space_scale = tiles.MostCommonScalar(transforms, imagepaths)

    if target_space_scale is None:
        target_space_scale = source_space_scale

    distanceImage = None
    original_fixed_rect_floats = None

    if not TargetRegion is None:
        if isinstance(TargetRegion, spatial.Rectangle):
            original_fixed_rect_floats = TargetRegion
        else:
            original_fixed_rect_floats = spatial.Rectangle.CreateFromPointAndArea(
                (TargetRegion[0], TargetRegion[1]),
                (TargetRegion[2] - TargetRegion[0],
                 TargetRegion[3] - TargetRegion[1]))
    else:
        original_fixed_rect_floats = tutils.FixedBoundingBox(transforms)

    scaled_targetRect = nornir_imageregistration.Rectangle.scale_on_origin(
        original_fixed_rect_floats, target_space_scale)
    scaled_targetRect = nornir_imageregistration.Rectangle.SafeRound(
        scaled_targetRect)
    targetRect = nornir_imageregistration.Rectangle.scale_on_origin(
        scaled_targetRect, 1.0 / target_space_scale)
    (fullImage,
     fullImageZbuffer) = __CreateOutputBufferForArea(scaled_targetRect.Height,
                                                     scaled_targetRect.Width,
                                                     target_space_scale)

    for i, transform in enumerate(transforms):
        regionToRender = None
        original_transform_fixed_rect = spatial.Rectangle(
            transform.FixedBoundingBox)
        transform_target_rect = nornir_imageregistration.Rectangle.SafeRound(
            original_transform_fixed_rect)

        regionToRender = nornir_imageregistration.Rectangle.Intersect(
            targetRect, transform_target_rect)
        if regionToRender is None:
            continue

        if regionToRender.Area == 0:
            continue

        scaled_region_rendered = nornir_imageregistration.Rectangle.scale_on_origin(
            regionToRender, target_space_scale)
        scaled_region_rendered = nornir_imageregistration.Rectangle.SafeRound(
            scaled_region_rendered)

        imagefullpath = imagepaths[i]

        distanceImage = __GetOrCreateDistanceImage(
            distanceImage,
            nornir_imageregistration.GetImageSize(imagefullpath))

        transformedImageData = TransformTile(
            transform,
            imagefullpath,
            distanceImage,
            target_space_scale=target_space_scale,
            TargetRegion=regionToRender,
            SingleThreadedInvoke=True)
        if transformedImageData.image is None:
            logger = logging.getLogger('TilesToImageParallel')
            logger.error('Convert task failed: ' + str(transformedImageData))
            if not transformedImageData.errormsg is None:
                logger.error(transformedImageData.errormsg)
                continue

        CompositeOffset = scaled_region_rendered.BottomLeft - scaled_targetRect.BottomLeft
        CompositeOffset = CompositeOffset.astype(np.int64)

        CompositeImageWithZBuffer(fullImage, fullImageZbuffer,
                                  transformedImageData.image,
                                  transformedImageData.centerDistanceImage,
                                  CompositeOffset)

        del transformedImageData

    mask = fullImageZbuffer < __MaxZBufferValue(fullImageZbuffer.dtype)
    del fullImageZbuffer

    fullImage[fullImage < 0] = 0
    # Checking for > 1.0 makes sense for floating point images.  During the DM4 migration
    # I was getting images which used 0-255 values, and the 1.0 check set them to entirely black
    # fullImage[fullImage > 1.0] = 1.0

    if isinstance(fullImage, np.memmap):
        fullImage.flush()

    return (fullImage, mask)
def TilesToImageParallel(transforms,
                         imagepaths,
                         TargetRegion=None,
                         target_space_scale=None,
                         source_space_scale=None,
                         pool=None):
    '''Assembles a set of transforms and imagepaths to a single image using parallel techniques.
    :param tuple TargetRegion: (MinX, MinY, Width, Height) or Rectangle class.  Specifies the SourceSpace to render from
    :param float target_space_scale: Scalar for the target space coordinates.  Used to downsample or upsample the output image.  Changes the coordinates of the target space control points of the transform. 
    :param float target_space_scale: Scalar for the source space coordinates.  Must match the change in scale of input images relative to the transform source space coordinates.  So if downsampled by
    4 images are used, this value should be 0.25.  Calculated to be correct if None.  Specifying is an optimization to reduce I/O of reading image files to calculate.
    '''

    assert (len(transforms) == len(imagepaths))

    logger = logging.getLogger('TilesToImageParallel')

    if pool is None:
        pool = nornir_pools.GetGlobalMultithreadingPool()

    # pool = nornir_pools.GetGlobalSerialPool()

    tasks = []
    if source_space_scale is None:
        source_space_scale = tiles.MostCommonScalar(transforms, imagepaths)

    if target_space_scale is None:
        target_space_scale = source_space_scale

    original_fixed_rect_floats = None

    if not TargetRegion is None:
        if isinstance(TargetRegion, spatial.Rectangle):
            original_fixed_rect_floats = TargetRegion
        else:
            original_fixed_rect_floats = spatial.Rectangle.CreateFromPointAndArea(
                (TargetRegion[0], TargetRegion[1]),
                (TargetRegion[2] - TargetRegion[0],
                 TargetRegion[3] - TargetRegion[1]))
    else:
        original_fixed_rect_floats = tutils.FixedBoundingBox(transforms)

    scaled_targetRect = nornir_imageregistration.Rectangle.scale_on_origin(
        original_fixed_rect_floats, target_space_scale)
    scaled_targetRect = nornir_imageregistration.Rectangle.SafeRound(
        scaled_targetRect)
    targetRect = nornir_imageregistration.Rectangle.scale_on_origin(
        scaled_targetRect, 1.0 / target_space_scale)
    (fullImage,
     fullImageZbuffer) = __CreateOutputBufferForArea(scaled_targetRect.Height,
                                                     scaled_targetRect.Width,
                                                     target_space_scale)

    CheckTaskInterval = 16

    for i, transform in enumerate(transforms):
        regionToRender = None
        original_transform_target_rect = spatial.Rectangle(
            transform.FixedBoundingBox)
        transform_target_rect = nornir_imageregistration.Rectangle.SafeRound(
            original_transform_target_rect)

        regionToRender = nornir_imageregistration.Rectangle.Intersect(
            targetRect, transform_target_rect)
        if regionToRender is None:
            continue

        if regionToRender.Area == 0:
            continue

        scaled_region_rendered = nornir_imageregistration.Rectangle.scale_on_origin(
            regionToRender, target_space_scale)
        scaled_region_rendered = nornir_imageregistration.Rectangle.SafeRound(
            scaled_region_rendered)

        imagefullpath = imagepaths[i]

        task = pool.add_task("TransformTile" + imagefullpath,
                             TransformTile,
                             transform=transform,
                             imagefullpath=imagefullpath,
                             distanceImage=None,
                             target_space_scale=target_space_scale,
                             TargetRegion=regionToRender,
                             SingleThreadedInvoke=False)
        task.transform = transform
        task.regionToRender = regionToRender
        task.scaled_region_rendered = scaled_region_rendered
        task.transform_fixed_rect = transform_target_rect
        tasks.append(task)

        if not i % CheckTaskInterval == 0:
            continue

        if len(tasks) > multiprocessing.cpu_count():
            iTask = len(tasks) - 1
            while iTask >= 0:
                t = tasks[iTask]
                if t.iscompleted:
                    transformedImageData = t.wait_return()
                    __AddTransformedTileTaskToComposite(
                        t, transformedImageData, fullImage, fullImageZbuffer,
                        scaled_targetRect)
                    del transformedImageData
                    del tasks[iTask]

                iTask -= 1

    logger.info('All warps queued, integrating results into final image')

    while len(tasks) > 0:
        t = tasks.pop(0)
        transformedImageData = t.wait_return()
        __AddTransformedTileTaskToComposite(t, transformedImageData, fullImage,
                                            fullImageZbuffer,
                                            scaled_targetRect)
        del transformedImageData
        del t

        # Pass through the entire loop and eliminate completed tasks in case any finished out of order
        iTask = len(tasks) - 1
        while iTask >= 0:
            t = tasks[iTask]
            if t.iscompleted:
                transformedImageData = t.wait_return()
                __AddTransformedTileTaskToComposite(t, transformedImageData,
                                                    fullImage,
                                                    fullImageZbuffer,
                                                    scaled_targetRect)
                del transformedImageData
                del tasks[iTask]

            iTask -= 1

    logger.info('Final image complete, building mask')

    mask = fullImageZbuffer < __MaxZBufferValue(fullImageZbuffer.dtype)
    del fullImageZbuffer

    fullImage[fullImage < 0] = 0
    # Checking for > 1.0 makes sense for floating point images.  During the DM4 migration
    # I was getting images which used 0-255 values, and the 1.0 check set them to entirely black
    # fullImage[fullImage > 1.0] = 1.0

    logger.info('Assemble complete')

    if isinstance(fullImage, np.memmap):
        fullImage.flush()

    return (fullImage, mask)
Ejemplo n.º 5
0
    def FixedBoundingBox(self):
        '''Calculate the bounding box of the warped position for a set of transforms
           (minX, minY, maxX, maxY)'''

        return tutils.FixedBoundingBox(list(self.ImageToTransform.values()))