Exemplo n.º 1
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
Exemplo n.º 2
0
    def test_16Bit_to_8Bit_ConvertImage(self):
        filename = '10001_RPC2_590.tif'
        self.FixedImagePath = os.path.join(self.ImportedDataPath, '16-bit',
                                           filename)
        basename = os.path.basename(filename)
        output_path = os.path.join(self.TestOutputPath,
                                   basename + '_converted.tif')

        self.assertTrue(os.path.exists(self.FixedImagePath),
                        "Missing test input: {0}".format(self.FixedImagePath))
        output = self.RunConvertImageTest(self.FixedImagePath)

        nornir_imageregistration.SaveImage(output_path, output)
Exemplo n.º 3
0
    def RunSaveLoadImageTest_BppOnly(self, input_image, output_fullpath,
                                     expected_bpp):

        wrong_input_bpp_error_msg = "Expected {0}-bit image".format(
            expected_bpp)
        wrong_output_bpp_error_msg = "Expected {0}-bit image".format(
            expected_bpp)

        bpp = nornir_imageregistration.ImageBpp(input_image)
        self.assertEqual(bpp, expected_bpp, wrong_input_bpp_error_msg)

        nornir_imageregistration.SaveImage(output_fullpath,
                                           input_image,
                                           bpp=expected_bpp)
        reloaded_image = nornir_imageregistration.ImageParamToImageArray(
            output_fullpath)
        MagickBpp = nornir_shared.images.GetImageBpp(output_fullpath)
        self.assertEqual(MagickBpp, expected_bpp, wrong_output_bpp_error_msg)

        reloaded_bpp = nornir_imageregistration.ImageBpp(reloaded_image)
        self.assertEqual(reloaded_bpp, expected_bpp,
                         wrong_output_bpp_error_msg)
Exemplo n.º 4
0
    def RunSaveLoadImageTest(self, input_image_fullpath,
                             expected_input_properties,
                             expected_output_properties):
        self.assertTrue(isinstance(expected_input_properties, ImageProperties))
        self.assertTrue(isinstance(expected_output_properties,
                                   ImageProperties))

        self.assertTrue(os.path.exists(input_image_fullpath),
                        "Missing test input: {0}".format(input_image_fullpath))
        input_image = nornir_imageregistration.ImageParamToImageArray(
            input_image_fullpath)

        output_path = os.path.join(
            self.TestOutputPath,
            expected_output_properties.GenFilename(input_image_fullpath))

        wrong_input_bpp_error_msg = "Expected {0}-bit image".format(
            expected_input_properties.bpp)
        wrong_output_bpp_error_msg = "Expected {0}-bit image".format(
            expected_output_properties.bpp)

        bpp = nornir_imageregistration.ImageBpp(input_image)
        self.assertEqual(bpp, expected_input_properties.bpp,
                         wrong_input_bpp_error_msg)

        nornir_imageregistration.SaveImage(output_path,
                                           input_image,
                                           bpp=expected_output_properties.bpp)
        reloaded_image = nornir_imageregistration.ImageParamToImageArray(
            output_path)
        MagickBpp = nornir_shared.images.GetImageBpp(output_path)
        self.assertEqual(MagickBpp, expected_output_properties.bpp,
                         wrong_output_bpp_error_msg)

        reloaded_bpp = nornir_imageregistration.ImageBpp(reloaded_image)
        self.assertEqual(reloaded_bpp, expected_output_properties.bpp,
                         wrong_output_bpp_error_msg)
def RefineTransform(stosTransform,
                    target_image,
                    source_image,
                    target_mask=None,
                    source_mask=None,
                    num_iterations=None,
                    cell_size=None,
                    grid_spacing=None,
                    angles_to_search=None,
                    min_travel_for_finalization=None,
                    min_alignment_overlap=None,
                    SaveImages=False,
                    SavePlots=False,
                    outputDir=None):
    '''
    Refines a transform and returns a grid transform produced by the refinement algorithm.
    
    Places a regular grid of control points across the target image.  These corresponding points on the
    source image are then adjusted to create a mapping from Source To Fixed Space for the source image. 
    :param stosTransform: The transform to refine
    :param target_image: ndarray or path to file, fixed space image
    :param source_image: ndarray or path to file, source space image
    :param target_mask: ndarray or path to file, fixed space image mask
    :param source_mask: ndarray or path to file, source space image mask
    :param int num_iterations: The maximum number of iterations to perform
    :param tuple cell_size: (width, height) area of image around control points to use for registration
    :param tuple grid_spacing: (width, height) of separation between control points on the grid
    :param array angles_to_search: An array of floats or None.  Images are rotated by the degrees indicated in the array.  The single best alignment across all angles is selected.
    :param float min_alighment_overlap: Limits how far control points can be translated.  The cells from fixed and target space must overlap by this minimum amount.
    :param bool SaveImages: Saves registered images of each iteration in the output path for debugging purposes
    :param bool SavePlots: Saves histograms and vector plots of each iteration in the output path for debugging purposes     
    :param str outputDir: Directory to save images and plots if requested.  Must not be null if SaveImages or SavePlots are true   
    '''

    if cell_size is None:
        cell_size = (256, 256)

    if grid_spacing is None:
        grid_spacing = (256, 256)

    if angles_to_search is None:
        angles_to_search = [0]

    if num_iterations is None:
        num_iterations = 10

    if min_travel_for_finalization is None:
        min_travel_for_finalization = 0.333

    if min_alignment_overlap is None:
        min_alignment_overlap = 0.5

    if SavePlots or SaveImages:
        assert (outputDir is not None)

    # Convert inputs to numpy arrays

    cell_size = np.asarray(
        cell_size,
        dtype=np.int32) * 2.0  # Double size of cell area for first pass only
    grid_spacing = np.asarray(grid_spacing, dtype=np.int32)

    target_image = nornir_imageregistration.ImageParamToImageArray(
        target_image, dtype=np.float32)
    source_image = nornir_imageregistration.ImageParamToImageArray(
        source_image, dtype=np.float32)

    if target_mask is not None:
        target_mask = nornir_imageregistration.ImageParamToImageArray(
            target_mask, dtype=np.bool)

    if source_mask is not None:
        source_mask = nornir_imageregistration.ImageParamToImageArray(
            source_mask, dtype=np.bool)

    final_pass = False  # True if this is the last iteration the loop will perform
    final_pass_angles = np.linspace(
        -7.5, 7.5, 11
    )  # The last registration we perform on a cell is a bit more thorough

    finalized_points = {}

    CutoffPercentilePerIteration = 10.0

    i = 1

    while i <= num_iterations:
        alignment_points = _RunRefineTwoImagesIteration(
            stosTransform,
            target_image,
            source_image,
            target_mask,
            source_mask,
            cell_size=cell_size,
            grid_spacing=grid_spacing,
            finalized=finalized_points,
            angles_to_search=angles_to_search,
            min_alignment_overlap=min_alignment_overlap)

        print("Pass {0} aligned {1} points".format(i, len(alignment_points)))

        # For the first pass we use a larger cell to help get some initial registration points
        if i == 1:
            cell_size = cell_size / 2.0

        combined_alignment_points = alignment_points + list(
            finalized_points.values())

        percentile = 100.0 - (CutoffPercentilePerIteration * i)
        if percentile < 10.0:
            percentile = 10.0
        elif percentile > 100:
            percentile = 100


#         if final_pass:
#             percentile = 0

        if SavePlots:
            histogram_filename = os.path.join(
                outputDir, 'weight_histogram_pass{0}.png'.format(i))
            nornir_imageregistration.views.PlotWeightHistogram(
                alignment_points,
                histogram_filename,
                cutoff=percentile / 100.0)
            vector_field_filename = os.path.join(
                outputDir, 'Vector_field_pass{0}.png'.format(i))
            nornir_imageregistration.views.PlotPeakList(
                alignment_points,
                list(finalized_points.values()),
                vector_field_filename,
                ylim=(0, target_image.shape[1]),
                xlim=(0, target_image.shape[0]))
            vector_field_filename = os.path.join(
                outputDir, 'Vector_field_pass_delta{0}.png'.format(i))
            nornir_imageregistration.views.PlotPeakList(
                alignment_points,
                list(finalized_points.values()),
                vector_field_filename,
                ylim=(0, target_image.shape[1]),
                xlim=(0, target_image.shape[0]),
                attrib='PSDDelta')

        updatedTransform = _PeakListToTransform(combined_alignment_points,
                                                percentile)

        new_finalized_points = CalculateFinalizedAlignmentPointsMask(
            combined_alignment_points,
            percentile=percentile,
            min_travel_distance=min_travel_for_finalization)

        new_finalizations = 0
        for (ir, record) in enumerate(alignment_points):
            if not new_finalized_points[ir]:
                continue

            key = tuple(record.SourcePoint)
            if key in finalized_points:
                continue

            # See if we can improve the final alignment
            refined_align_record = nornir_imageregistration.stos_brute.SliceToSliceBruteForce(
                record.TargetROI,
                record.SourceROI,
                AngleSearchRange=final_pass_angles,
                MinOverlap=min_alignment_overlap,
                SingleThread=True,
                Cluster=False,
                TestFlip=False)

            if refined_align_record.weight > record.weight:
                oldPSDDelta = record.PSDDelta
                record = nornir_imageregistration.EnhancedAlignmentRecord(
                    ID=record.ID,
                    TargetPoint=record.TargetPoint,
                    SourcePoint=record.SourcePoint,
                    peak=refined_align_record.peak,
                    weight=refined_align_record.weight,
                    angle=refined_align_record.angle,
                    flipped_ud=refined_align_record.flippedud)
                record.PSDDelta = oldPSDDelta

            # Create a record that is unmoving
            finalized_points[
                key] = nornir_imageregistration.EnhancedAlignmentRecord(
                    record.ID,
                    TargetPoint=record.AdjustedTargetPoint,
                    SourcePoint=record.SourcePoint,
                    peak=np.asarray((0, 0), dtype=np.float32),
                    weight=record.weight,
                    angle=0,
                    flipped_ud=record.flippedud)

            finalized_points[key].PSDDelta = record.PSDDelta

            new_finalizations += 1

        print(
            "Pass {0} has locked {1} new points, {2} of {3} are locked".format(
                i, new_finalizations, len(finalized_points),
                len(combined_alignment_points)))
        stosTransform = updatedTransform

        if SaveImages:
            #InputStos.Save(os.path.join(outputDir, "UpdatedTransform_pass{0}.stos".format(i)))

            warpedToFixedImage = nornir_imageregistration.assemble.TransformStos(
                updatedTransform,
                fixedImage=target_image,
                warpedImage=source_image)

            Delta = warpedToFixedImage - target_image
            ComparisonImage = np.abs(Delta)
            ComparisonImage = ComparisonImage / ComparisonImage.max()

            nornir_imageregistration.SaveImage(os.path.join(
                outputDir, 'delta_pass{0}.png'.format(i)),
                                               ComparisonImage,
                                               bpp=8)
            nornir_imageregistration.SaveImage(os.path.join(
                outputDir, 'image_pass{0}.png'.format(i)),
                                               warpedToFixedImage,
                                               bpp=8)

        i = i + 1

        if final_pass:
            break

        if i == num_iterations:
            final_pass = True
            angles_to_search = final_pass_angles

        # If we've locked 10% of the points and have not locked any new ones we are done
        if len(finalized_points) > len(
                combined_alignment_points) * 0.1 and new_finalizations == 0:
            final_pass = True
            angles_to_search = final_pass_angles

        # If we've locked 90% of the points we are done
        if len(finalized_points) > len(combined_alignment_points) * 0.9:
            final_pass = True
            angles_to_search = final_pass_angles

    # Convert the transform to a grid transform and persist to disk

    return stosTransform