Beispiel #1
0
    def test_warpedImageToFixedSpaceRotateTransform(self):
        WarpedImagePath = os.path.join(
            self.ImportedDataPath,
            "0017_TEM_Leveled_image__feabinary_Cel64_Mes8_sp4_Mes8.png")
        self.assertTrue(os.path.exists(WarpedImagePath), "Missing test input")

        angle = 30
        arecord = AlignmentRecord(peak=(0, 0), weight=100, angle=angle)

        fixedImage = nornir_imageregistration.LoadImage(WarpedImagePath)
        warpedImage = nornir_imageregistration.LoadImage(WarpedImagePath)

        transform = arecord.ToTransform(fixedImage.shape, warpedImage.shape)

        transformedImage = assemble.WarpedImageToFixedSpace(
            transform, fixedImage.shape, warpedImage)
        imsave("C:\\Temp\\17Rotate.png", transformedImage)

        rotatedWarped = interpolation.rotate(warpedImage.astype(numpy.float32),
                                             angle=angle)
        #
        self.assertTrue(
            ShowComparison(
                [fixedImage, rotatedWarped, transformedImage],
                title=
                "Rotate transform should match scipy.interpolate.rotate result",
                PassFail=True))
Beispiel #2
0
    def testBrightfieldShading(self):

        ReferenceImagePath = self.GetImagePath("400.png")
        ShadedImagePath = self.GetImagePath("400_Shaded.png")
        ShadingReferencePath = self.GetImagePath("BrightfieldShading.png")

        self.assertTrue(os.path.exists(ReferenceImagePath))
        self.assertTrue(os.path.exists(ShadedImagePath))
        self.assertTrue(os.path.exists(ShadingReferencePath))

        originalImage = nir.LoadImage(ReferenceImagePath)
        shadedImage = nir.LoadImage(ShadedImagePath)
        shadingMask = nir.LoadImage(ShadingReferencePath)

        shadedImageV2 = originalImage * shadingMask
        shadedImageV2Path = os.path.join(self.TestOutputPath,
                                         "TestGeneratedShadedImage.png")

        nir.SaveImage(shadedImageV2Path, shadedImageV2)

        OutputPaths = tiles.ShadeCorrect(
            [ShadedImagePath, shadedImageV2Path],
            shadingMask,
            self.TestOutputPath,
            correction_type=tiles.ShadeCorrectionTypes.BRIGHTFIELD)

        shownImages = [originalImage, shadedImage, shadingMask]

        for path in OutputPaths:
            correctedImage = nir.LoadImage(path)
            shownImages.append(correctedImage)

        # nir.ShowGrayscale(shownImages)

        pass
def __CompositeTiles(imagepaths, func):
    '''Takes two images, merges, and returns the max image
    
    :param list imagepaths: list of paths to images
    :param str outputpath: Path of output image
    :param function func: function taking two images as arguments.  Called on image pairs.
    '''

    stack = copy.copy(imagepaths)

    CompositeImage = nornir_imageregistration.LoadImage(stack.pop())

    while len(stack) > 0:

        imageA = nornir_imageregistration.LoadImage(stack.pop())
        CompositeImage = func(CompositeImage, imageA)

        del imageA

    return CompositeImage
Beispiel #4
0
    def test_warpedImageToFixedSpaceIdentityTransform(self):
        WarpedImagePath = os.path.join(
            self.ImportedDataPath,
            "0017_TEM_Leveled_image__feabinary_Cel64_Mes8_sp4_Mes8.png")
        self.assertTrue(os.path.exists(WarpedImagePath), "Missing test input")

        arecord = AlignmentRecord(peak=(0, 0), weight=100, angle=0.0)

        fixedImage = nornir_imageregistration.LoadImage(WarpedImagePath)
        warpedImage = nornir_imageregistration.LoadImage(WarpedImagePath)

        transform = arecord.ToTransform(fixedImage.shape, warpedImage.shape)

        transformedImage = assemble.WarpedImageToFixedSpace(
            transform, fixedImage.shape, warpedImage, (0, 0), (64, 64))
        # imsave("C:\\Temp\\17.png", transformedImage)

        delta = fixedImage[0:64, 0:64] - transformedImage

        # nornir_imageregistration.ShowGrayscale([fixedImage[0:64, 0:64], transformedImage, delta])
        self.assertTrue((delta < 0.01).all())
Beispiel #5
0
    def test_warpedImageToFixedSpace(self):
        WarpedImagePath = os.path.join(
            self.ImportedDataPath,
            "0017_TEM_Leveled_image__feabinary_Cel64_Mes8_sp4_Mes8.png")
        self.assertTrue(os.path.exists(WarpedImagePath), "Missing test input")
        FixedImagePath = os.path.join(
            self.ImportedDataPath,
            "mini_TEM_Leveled_image__feabinary_Cel64_Mes8_sp4_Mes8.png")
        self.assertTrue(os.path.exists(FixedImagePath), "Missing test input")

        arecord = AlignmentRecord(peak=(22, -4), weight=100, angle=-132.0)

        fixedImage = nornir_imageregistration.LoadImage(FixedImagePath)
        warpedImage = nornir_imageregistration.LoadImage(WarpedImagePath)

        transform = arecord.ToTransform(fixedImage.shape, warpedImage.shape)

        transformedImage = assemble.WarpedImageToFixedSpace(
            transform, fixedImage.shape, warpedImage)
        imsave(
            os.path.join(self.VolumeDir, "test_warpedImageToFixedSpace.png"),
            transformedImage)
Beispiel #6
0
    def ExamineBrightfieldShading(self, ShadedImagePath, ShadingReferencePath):

        self.assertTrue(os.path.exists(ShadedImagePath))
        self.assertTrue(os.path.exists(ShadingReferencePath))

        shadedImage = nir.LoadImage(ShadedImagePath)
        shadingMask = nir.LoadImage(ShadingReferencePath)

        OutputPaths = tiles.ShadeCorrect(
            [ShadedImagePath],
            shadingMask,
            self.TestOutputPath,
            correction_type=tiles.ShadeCorrectionTypes.BRIGHTFIELD)

        shownImages = [shadedImage, shadingMask]

        for path in OutputPaths:
            correctedImage = nir.LoadImage(path)
            shownImages.append(correctedImage)

        # nir.ShowGrayscale(shownImages)

        pass
def __CorrectBrightfieldShadingOneImage(input_fullpath, output_fullpath,
                                        imagescalar, bpp):
    max_pixel_value = ((1 << bpp) - 1)
    image = nornir_imageregistration.LoadImage(input_fullpath)
    image = image.astype(np.float16) / max_pixel_value

    correctedimage = image / imagescalar
    del image

    correctedimage[np.isinf(correctedimage)] = 0
    np.clip(correctedimage, a_min=0, a_max=1.0, out=correctedimage)
    correctedimage = correctedimage * max_pixel_value

    nornir_imageregistration.SaveImage(output_fullpath,
                                       correctedimage,
                                       bpp=bpp)
    del correctedimage
def __CorrectDarkfieldShading(imagepaths, shadeimage, outputpath, bpp=None):

    outputPaths = []
    if bpp is None:
        bpp = nornir_shared.images.GetImageBpp(imagepaths[0])

    for imagepath in imagepaths:
        image = nornir_imageregistration.LoadImage(imagepath)

        imageFilename = os.path.basename(imagepath)
        outputFilename = os.path.join(outputpath, imageFilename)

        correctedimage = image - shadeimage
        nornir_imageregistration.SaveImage(outputFilename,
                                           correctedimage,
                                           bpp=bpp)

        outputPaths.append(outputFilename)

        del image
        del correctedimage

    return outputPaths
def __tile_offset_remote(A_Filename, B_Filename,
                         scaled_overlapping_source_rect_A,
                         scaled_overlapping_source_rect_B, OffsetAdjustment,
                         excess_scalar):
    '''
    :param A_Filename: Path to tile A
    :param B_Filename: Path to tile B
    :param scaled_overlapping_source_rect_A: Region of overlap on tile A with tile B
    :param scaled_overlapping_source_rect_B: Region of overlap on tile B with tile A
    :param OffsetAdjustment: scaled_offset to account for the (center) position of tile B relative to tile A.  If the overlapping rectangles are perfectly aligned the reported offset would be (0,0).  OffsetAdjustment would be added to that (0,0) result to ensure Tile B remained in the same position. 
    :param float excess_scalar: How much additional area should we pad the overlapping rectangles with.
    Return the offset required to align to image files.
    This function exists to minimize the inter-process communication
    '''

    ShowImages = False
    A = nornir_imageregistration.LoadImage(A_Filename)
    B = nornir_imageregistration.LoadImage(B_Filename)

    # I had to add the .astype call above for DM4 support, but I recall it broke PMG input.  Leave this comment here until the tests are passing
    #    A = nornir_imageregistration.LoadImage(A_Filename) #.astype(dtype=np.float16)
    #    B = nornir_imageregistration.LoadImage(B_Filename) #.astype(dtype=np.float16)

    # I tried a 1.0 overlap.  It works better for light microscopy where the reported stage position is more precise
    # For TEM the stage position can be less reliable and the 1.5 scalar produces better results
    # For the latest version of the code that uses only the overlapping region 3 is appropriate because it allows the alignment point to be anywhere on the image without ambiguity
    OverlappingRegionA = __get_overlapping_image(
        A, scaled_overlapping_source_rect_A, excess_scalar=excess_scalar)
    OverlappingRegionB = __get_overlapping_image(
        B, scaled_overlapping_source_rect_B, excess_scalar=excess_scalar)

    if ShowImages:
        o_a = __get_overlapping_image(A,
                                      scaled_overlapping_source_rect_A,
                                      excess_scalar=1.0,
                                      cval=0)
        o_b = __get_overlapping_image(B,
                                      scaled_overlapping_source_rect_B,
                                      excess_scalar=1.0,
                                      cval=0)

    #nornir_imageregistration.ShowGrayscale([[OverlappingRegionA, OverlappingRegionB],[o_a,o_b]])
    OverlappingRegionA = OverlappingRegionA.astype(np.float32)
    OverlappingRegionB = OverlappingRegionB.astype(np.float32)

    # It is fairly common to underflow when dividing float16 images, so just warn and move on.
    # I spent a day debugging why a mosaic was not building correctly to find the underflow
    # issue, so don't remove it.  The underflow error removes one of the ties between a tile
    # and its neighbors.

    # Note error levelshould now be set in nornir_imageregistration.__init__
    # old_float_err_settings = np.seterr(under='warn')

    # If the entire region is a solid color, then return an alignment record with no offset and a weight of zero
    if (OverlappingRegionA.min() == OverlappingRegionA.max()) or \
        (OverlappingRegionA.max() == 0) or \
        (OverlappingRegionB.min() == OverlappingRegionB.max()) or \
        (OverlappingRegionB.max() == 0):
        return nornir_imageregistration.AlignmentRecord(peak=OffsetAdjustment,
                                                        weight=0)

    OverlappingRegionA -= OverlappingRegionA.min()
    OverlappingRegionA /= OverlappingRegionA.max()

    OverlappingRegionB -= OverlappingRegionB.min()
    OverlappingRegionB /= OverlappingRegionB.max()

    # nornir_imageregistration.ShowGrayscale([OverlappingRegionA, OverlappingRegionB]) nornir_imageregistration.ShowGrayscale([[o_a, o_b],[OverlappingRegionA, OverlappingRegionB]])

    record = nornir_imageregistration.FindOffset(
        OverlappingRegionA, OverlappingRegionB, FFT_Required=True
    )  #, FixedImageShape=scaled_overlapping_source_rect_A.shape, MovingImageShape=scaled_overlapping_source_rect_B.shape)

    #overlapping_rect_B_AdjustedToPeak = nornir_imageregistration.Rectangle.translate(scaled_overlapping_source_rect_B, -record.peak)
    #overlapping_rect_B_AdjustedToPeak = nornir_imageregistration.Rectangle.change_area(overlapping_rect_B_AdjustedToPeak, scaled_overlapping_source_rect_A.Size)
    #median_diff = __AlignmentScoreRemote(A, B, scaled_overlapping_source_rect_A, overlapping_rect_B_AdjustedToPeak)
    #nornir_imageregistration.ShowGrayscale([[OverlappingRegionA, OverlappingRegionB], [overlapping_rect_B_AdjustedToPeak, median_diff]])
    #diff_weight = 1.0 - median_diff
    #np.seterr(**old_float_err_settings)

    #nornir_imageregistration.views.plot_aligned_images(record, o_a, o_b)
    adjusted_record = nornir_imageregistration.AlignmentRecord(
        np.array(record.peak) + OffsetAdjustment, record.weight)

    if ShowImages:
        nornir_imageregistration.views.plot_aligned_images(record, o_a, o_b)
        del o_a
        del o_b

    del A
    del B
    del OverlappingRegionA
    del OverlappingRegionB

    return adjusted_record
Beispiel #10
0
def _ShrinkNumpyImageFile(InFile, OutFile, Scalar):
    image = nornir_imageregistration.LoadImage(InFile)
    resized_image = nornir_imageregistration.ResizeImage(image, Scalar)
    nornir_imageregistration.SaveImage(OutFile, resized_image)
Beispiel #11
0
    def Image(self):
        if self._image is None:
            self._image = nornir_imageregistration.LoadImage(self._imagepath)

        return self._image
def SliceToSliceBruteForce(FixedImageInput,
                           WarpedImageInput,
                           FixedImageMaskPath=None,
                           WarpedImageMaskPath=None,
                           LargestDimension=None,
                           AngleSearchRange=None,
                           MinOverlap=0.75,
                           SingleThread=False,
                           Cluster=False,
                           TestFlip=True):
    '''Given two images this function returns the rotation angle which best aligns them
       Largest dimension determines how large the images used for alignment should be'''

    logger = logging.getLogger(__name__ + '.SliceToSliceBruteForce')

    imFixed = None
    if isinstance(FixedImageInput, str):
        imFixed = nornir_imageregistration.LoadImage(FixedImageInput,
                                                     FixedImageMaskPath,
                                                     dtype=np.float32)
    else:
        imFixed = FixedImageInput

    imWarped = None
    if isinstance(WarpedImageInput, str):
        imWarped = nornir_imageregistration.LoadImage(WarpedImageInput,
                                                      WarpedImageMaskPath,
                                                      dtype=np.float32)
    else:
        imWarped = WarpedImageInput

    scalar = 1.0
    if not LargestDimension is None:
        scalar = nornir_imageregistration.ScalarForMaxDimension(
            LargestDimension, [imFixed.shape, imWarped.shape])

    if scalar < 1.0:
        imFixed = nornir_imageregistration.ReduceImage(imFixed, scalar)
        imWarped = nornir_imageregistration.ReduceImage(imWarped, scalar)

    # Replace extrema with noise
    imFixed = nornir_imageregistration.ReplaceImageExtramaWithNoise(
        imFixed, ImageMedian=0.5, ImageStdDev=0.25)
    imWarped = nornir_imageregistration.ReplaceImageExtramaWithNoise(
        imWarped, ImageMedian=0.5, ImageStdDev=0.25)

    UserDefinedAngleSearchRange = not AngleSearchRange is None
    if not UserDefinedAngleSearchRange:
        AngleSearchRange = list(range(-180, 180, 2))

    BestMatch = FindBestAngle(imFixed,
                              imWarped,
                              AngleSearchRange,
                              MinOverlap=MinOverlap,
                              SingleThread=SingleThread,
                              Cluster=Cluster)

    IsFlipped = False
    if TestFlip:
        imWarpedFlipped = np.copy(imWarped)
        imWarpedFlipped = np.flipud(imWarpedFlipped)

        BestMatchFlipped = FindBestAngle(imFixed,
                                         imWarpedFlipped,
                                         AngleSearchRange,
                                         MinOverlap=MinOverlap,
                                         SingleThread=SingleThread,
                                         Cluster=Cluster)
        BestMatchFlipped.flippedud = True

        # Determine if the best match is flipped or not
        IsFlipped = BestMatchFlipped.weight > BestMatch.weight

    if IsFlipped:
        imWarped = imWarpedFlipped
        BestMatch = BestMatchFlipped

    if not UserDefinedAngleSearchRange:
        BestRefinedMatch = FindBestAngle(imFixed,
                                         imWarped,
                                         [(x * 0.1) + BestMatch.angle - 1
                                          for x in range(0, 20)],
                                         MinOverlap=MinOverlap,
                                         SingleThread=SingleThread)
        BestRefinedMatch.flippedud = IsFlipped
    else:
        BestRefinedMatch = BestMatch

    if scalar > 1.0:
        AdjustedPeak = (BestRefinedMatch.peak[0] * scalar,
                        BestRefinedMatch.peak[1] * scalar)
        BestRefinedMatch = nornir_imageregistration.AlignmentRecord(
            AdjustedPeak, BestRefinedMatch.weight, BestRefinedMatch.angle,
            IsFlipped)

# BestRefinedMatch.CorrectPeakForOriginalImageSize(imFixed.shape, imWarped.shape)

    return BestRefinedMatch