LaboratoireMecaniqueLille / crappy

Command and Real-time Acquisition Parallelized in Python
https://crappy.readthedocs.io/en/stable/
GNU General Public License v2.0
78 stars 16 forks source link

User fields for DIS_Correl and GPU_Correl projection #97

Closed jeffwitz closed 6 months ago

jeffwitz commented 6 months ago

Dear @WeisLeDocto,

In this file, the fields defined here, are used in order to define a projection that can be directly used in crappy.

It seems not possible for the user to define his own fields in order to tune the projection. @Dad0u in his code GPUCorrel allows one to une customs fields that can be used with existing one, here is an example that I think is relevant and that I would love to be able to use this in CRAPPY for both dis_correl and gpu_correl :

 # This example shows how to create a simple example field
y,x = 480,640
lx = np.linspace(-1,1,x)
ly = np.linspace(-1,1,y)
# A field to identify Z-axis rigid body motion (equivalent to exx+eyy)
xv,yv = np.meshgrid(lx,ly)

my_field = np.empty((y,x,2),dtype=np.float32)
my_field[:,:,0] = xv
my_field[:,:,1] = yv

correl = GPUCorrel((y,x),fields=['x','y',my_field])
WeisLeDocto commented 6 months ago

Hi,

I took the liberty to fix your two first links that were broken.

Seems like a reasonable enough feature request, should not be difficult to implement nor break existing code. I'm adding it to the Project section, planned for release in version 2.0.5 (next to come).

jeffwitz commented 6 months ago

I just think about it, but we don't know the shape of the image when we define the fields inside crappy, it could be interesting to define a class that build the shape functions and passing the class ?

import numpy as np

class QuadraticDeformationField:
    def __init__(self, x_range, y_range, resolution):
        """
        Initialise the coordinate space and calculate the quadratic deformation fields.

        Args:
        x_range (tuple): The tuple (min, max) defining the range of x values.
        y_range (tuple): The tuple (min, max) defining the range of y values.
        resolution (int): The number of points in each dimension.
        """
        self.x_values = np.linspace(x_range[0], x_range[1], resolution)
        self.y_values = np.linspace(y_range[0], y_range[1], resolution)
        self.X, self.Y = np.meshgrid(self.x_values, self.y_values)
        self.calculate_quadratic_fields()

    def calculate_quadratic_fields(self):
        """
        Calculates the quadratic deformation fields for the defined coordinates.
        """
        self.quad_x = self.X**2
        self.quad_y = self.Y**2
        self.quad_xy = self.X * self.Y

    def get_fields(self):
        """
        Returns the calculated quadratic deformation fields.

        Returns:
        tuple: A tuple containing the quadratic fields in x, y and xy.
        """
        return self.quad_x, self.quad_y, self.quad_xy

I think I don't quite well understand where the image is acquired but I think it is at the prepare step.

WeisLeDocto commented 6 months ago

I just think about it, but we don't know the shape of the image when we define the fields inside crappy

What I had in mind for a first step was to perform a check in the set_box method, to make sure that the fields provided as numpy arrays by the user have the same shape as the patch to track. Would be implemented here: https://github.com/LaboratoireMecaniqueLille/crappy/blob/f7ceb73e95cc42737005649b843c01a9859873d3/src/crappy/tool/image_processing/dis_correl.py#L123-L128

it could be interesting to define a class that build the shape functions and passing the class

An option could be to allow passing to the DISCorrel Block a Callable that takes the image shape as an input, and returns the desired field. But for anything more advanced (parametrize field instantiation, update field at runtime) we would need to improve the overall architecture and handling of the correlation fields in Crappy. There is certainly room for improvements, but we need to carefully think it through.

I think I don't quite well understand where the image is acquired but I think it is at the prepare step

No image is passed to the DISCorrelTool before the first loop of the DISCorrel Block.

WeisLeDocto commented 6 months ago

Simplest use-case covered in #106, with the possibility for users to pass fields as numpy arrays to the DISCorrel and GPUCorrel Blocks. See the newly add example. Will be available on PyPI in release 2.0.5.

Closing this issue now, please open a new one for discussing more advanced custom correlation field options.