N-dimension flatten

Python

Flatten the TIFF image data using a n-order Legendre polynomial function. [dependency] - numpy - matplotlib - pspylib

main 1 file
N-dimension flatten..py
n_d_flatten.py 3.5 KB
N-dimension flatten..py 3612 bytes
import os
import numpy as np
import matplotlib.pyplot as plt
from pspylib.tiff.reader import TiffReader

def n_d_legendre_flatten(array_tiff, scope='line_x',degree = 2 ,region=None):
    assert scope in ['line_x', 'whole_x', 'line_y', 'whole_y']
    if region is not None:
        assert (np.array(array_tiff.shape) == np.array(region.shape)).all() # shape should match
    else:
        region = np.ones_like(array_tiff, dtype=np.bool_)

    image = array_tiff.copy()
    H, W = image.shape
    match scope:
        case 'line_x' | 'whole_x':
            A = np.zeros((W, degree + 1))
            for i in range(degree + 1):
                A[:, i] = __legendre_polynomial(i, np.arange(1, W + 1) )
            results = []
            for i in range(H):
                img_row, reg_row = image[i, :], region[i, :]
                valid_n = np.sum(reg_row)
                coef, _, _ , _ = np.linalg.lstsq(A[reg_row,:], img_row[reg_row], rcond=None)
                result_row = img_row - np.dot(A, coef) 
                results.append(result_row)
            result_image = np.stack(results, axis=0)
            line_image = image - result_image
            
            if scope == 'whole_x':
                avg_line = np.mean(line_image, axis=0, keepdims=True)
                result_image = image - avg_line

        case 'line_y' | 'whole_y':
            A = np.zeros((H, degree + 1))
            for i in range(degree + 1):
                A[:, i] = __legendre_polynomial(i, np.arange(1, H + 1))
            results = []
            for i in range(W):
                img_column, reg_column = image[:, i], region[:, i]
                valid_n = np.sum(reg_column)
                if valid_n <= 2: # no region selected
                    bias = np.mean(img_column)
                    result_column = img_column - bias
                else:
                    coef, resids, rank, s = np.linalg.lstsq(A[reg_column, :], img_column[reg_column], rcond=None)
                    result_column = img_column - np.dot(A, coef)
                results.append(result_column)
            result_image = np.stack(results, axis=1)
            line_image = image - result_image
            
            if scope == 'whole_y':
                avg_line = np.mean(line_image, axis=1, keepdims=True)
                result_image = image - avg_line
    return result_image

def __legendre_polynomial(n, x):
    if n == 0:
        return np.ones_like(x)
    elif n == 1:
        return x
    else:
        P_n_minus_2 = np.ones_like(x)
        P_n_minus_1 = x
        for k in range(2, n+1):
            P_n = ((2*k - 1) * x * P_n_minus_1 - (k - 1) * P_n_minus_2) / k
            P_n_minus_2 = P_n_minus_1
            P_n_minus_1 = P_n
        return P_n

if __name__ == "__main__":
    samples_path = r"C:\Park Systems\SmartScan\samples"
    tiff_path = os.path.join(samples_path, "Image", "Cheese.tiff")
    tiff = TiffReader(tiff_path)
    Zdata = tiff.data.scanData.ZData
    header = tiff.data.scanHeader.scanHeader
    dshape = (int(header['height'][0]), int(header['width'][0]))
    tiff_image = np.reshape(Zdata,dshape)
    tiff_image = np.flipud(tiff_image)


    flattened_image = n_d_legendre_flatten(tiff_image, scope='line_x', degree=3)

    plt.subplot(1, 2, 1)
    plt.title('Original Image')
    plt.imshow(tiff_image, cmap='gray')
    plt.axis('off')

    plt.subplot(1, 2, 2)
    plt.title('Flattened Image')
    plt.imshow(flattened_image, cmap='gray')
    plt.axis('off')
    plt.tight_layout()
    plt.show()
Comments (0)

No comments yet. Be the first to comment!

Snippet Information
Author: jungyu.lee
Language: Python
Created: Oct 23, 2025
Updated: 0 minutes ago
Views: 48
Stars: 1

Links & Files

Additional Files (1):