What's the best way to stitch multiple images together into one mosaic image with Python?

159 Views Asked by At

I have data that gives a diffraction pattern according to a moving motor. I need to stitch them together to a one mosaic iamge but I can't figure out how to do it. Here is the code:

import numpy as np
import cv2
import silx.io.h5py_utils
from PIL import Image

class BlissPath(object):
    def __init__(self, path_to_session=None, sample_dir_name=None, dataset_dir_name=None, detector_name=None):
        self.path_to_session = path_to_session
        self.sample_dir_name = sample_dir_name
        self.dataset_dir_name = dataset_dir_name
        self.detector_name = detector_name

class Scan(object):
    def __init__(self):
        self._motors = {}
        self._counters = {}
        self._det_images = None
        self.scanning_motors = []
        self._metadata = None
        self._default_scan_path = None
        self.scan = None

    def set_default_scan_path(self, value):
        self._default_scan_path = value

    def _load_from_bliss(self, scan_number, scan_path):
        file_name = f"{scan_path.path_to_session}/{scan_path.sample_dir_name}/{scan_path.sample_dir_name}_{scan_path.dataset_dir_name}/{scan_path.sample_dir_name}_{scan_path.dataset_dir_name}.h5"
        print(file_name)
        with silx.io.h5py_utils.File(file_name) as fp:
            scan_key = str(scan_number) + '.1'
            scan = fp[scan_key]
            print(scan_key)
            motors = list(fp[scan_key + '/instrument/positioners'].keys())
            for motor in motors:
                self._motors[motor] = fp[scan_key + '/instrument/positioners/' + motor][()]
            counters = list(fp[scan_key + '/measurement'].keys())
            for counter in counters:
                self._counters[counter] = fp[scan_key + '/measurement/' + counter][()]
            self._det_images = fp[scan_key + '/measurement/' + scan_path.detector_name][()]

    def load(self, scan_number, scan_path=None):
        if isinstance(scan_path, BlissPath):
            print(scan_path)
            self._load_from_bliss(scan_number, scan_path)

bliss_path = BlissPath(
    path_to_session="/home/nosu/summer23",
    sample_dir_name="CeO2_nist_2",
    dataset_dir_name="0001",
    detector_name="minipix1"
)

scan = Scan()
scan.load(3, scan_path=bliss_path)

# Stitching the images together as a mosaic
image_shape = scan._det_images.shape[1:]  # Assuming all images have the same shape
num_images = scan._det_images.shape[0]
num_columns = int(np.sqrt(num_images))
num_rows = int(np.ceil(num_images / num_columns))
reference_image = np.zeros((num_rows * image_shape[0], num_columns * image_shape[1]))
overlap_count = np.zeros_like(reference_image)

for i, image in enumerate(scan._det_images):
    row = i // num_columns
    col = i % num_columns
    start_row = row * image_shape[0]
    start_col = col * image_shape[1]
    reference_image[start_row: start_row + image_shape[0], start_col: start_col + image_shape[1]] += image
    overlap_count[start_row: start_row + image_shape[0], start_col: start_col + image_shape[1]] += (image > 0).astype(np.float32)

reference_image /= overlap_count  # Divide by the overlap count instead of the number of images

# Convert the reference image to PIL Image
reference_image = Image.fromarray(reference_image)

# Display the reference image
reference_image.show()

This gives the following image:

image

I have tried to make it recognize the arcs but it didnt work. I have tried to make it read maximum values but that didnt work either. Any ideas are welcome, I want it to look like this image

Edit: this seems to take to a powerpoint, the image that I am after is the one on dia 13.

0

There are 0 best solutions below