tlambert03 / LLSpy

Lattice light-sheet post-processing utility.
http://llspy.readthedocs.io
Other
27 stars 6 forks source link

Feature Request: Cropping of rotated data to coverslip #32

Closed bscott711 closed 8 months ago

bscott711 commented 3 years ago

Hi Talley,

I wrote the following simple yz cropping function (on rotated data), but I am really struggling to get it integrated into the gui, do you have any suggestions on the easiest way to do that?

Thanks, -Brandon

def coverslipbounds(im, sigma=2,pad=5):
    from llspy.arrayfun import threshold_li
    from scipy.ndimage.filters import gaussian_filter
    from scipy.ndimage.morphology import binary_erosion
    from scipy.ndimage import generate_binary_structure, iterate_structure

    def _diamond(n=4):
        struct = iterate_structure(generate_binary_structure(2,1) , n).astype(int)
        return struct

    if im.ndim == 3:
        im = np.squeeze(im.max(1)) #Uses the yz projection as this displays the full shape
    im = im.astype(np.float)
    mask = im > 0 #This gives the position of padded parallelogram
    maskErode = binary_erosion(mask, _diamond(15)) #Erode the sides to ensure edge artifacts are removed.

    im_gaus = gaussian_filter(im, sigma)
    coverslip = im_gaus > threshold_li(im_gaus)
    coverslipErode = binary_erosion(coverslip * maskErode, _diamond(4)) #Helps to clean up obj further
    lsum = np.sum(coverslipErode,-1)
    msum = np.sum(mask,-1)
    zMin = np.where(lsum > 0)[0][0] - pad # This represents the coverslip with padding
    zMax = np.where(msum > 0)[0][-1] # This is the top of the parallelogram

    # The following crops in y to the edge of the parallelogram at what is the coverslip.
    maskEdge=np.where(maskErode[zMin]==True)[0]
    yMin, yMax = maskEdge[0], maskEdge[-1]
    # Could also return [zMin, zMax, yMin, yMax]
    return {'zMin':zMin, 'zMax':zMax,'yMin':yMin,'yMax':yMax}

def cropYZ(im, croppingInfo={}):
    """  If we return croppingInfo as [] instead of {}
    zMin,zMax = croppingInfo[0],croppingInfo[1]
    yMin,yMax = croppingInfo[2],croppingInfo[3]
    """

    zMin,zMax = croppingInfo['zMin'], croppingInfo['zMax']
    yMin,yMax = croppingInfo['yMin'], croppingInfo['yMax']
    if im.ndim == 3:
        im = im[zMin:zMax, :, yMin:yMax]
    elif im.ndim > 3:
        im = im[..., zMin:zMax, :, yMin:yMax]
    return im
tlambert03 commented 3 years ago

oh man... you mean I have to remember how this thing works?? 😂 so, you want to apply that cropping to all images at the end of the processing chain before saving? and want like a checkbox and a couple inputs for sigma and pad maybe?

bscott711 commented 3 years ago

lol well you don't haaaaaave to, but I would be eternally grateful :)

And that is exactly the workflow envisioned

tlambert03 commented 3 years ago

can do. It's not going to be terribly performant: without adding it to the C code that gets run in the binary, we basically have to re-open crop and resave each file in the folder. but at least you'd be able to add it to your pipeline. that ok?

bscott711 commented 3 years ago

That would be totally fine! Having it done automatically, even if after is the real pickup since it's normally being done at night anyway.

tlambert03 commented 8 months ago

closing as this project is in maintenance mode, likely will not add new features