在 Matlab 中删除图像偏移(2D 基线)

nol*_*its 6 matlab image-processing curve-fitting offset baseline

我有一张与此类似的图像:

在此处输入图片说明

并希望删除其底层基线,使其看起来像:

在此处输入图片说明

图像总是不同的,通常有一些峰值,并且具有总绝对偏移和倾斜/弯曲/非线性的基面。

我正在考虑对常见信号光谱使用 1D 基线拟合和减法技术,并创建一个 2D 基线图像,然后从数字上减去每个图像。但是在 2D 中无法完全理解它。

这是我之前问过的一个改进的问题,但这个问题应该更清楚。

fla*_*awr 6

在我看来,我们可以应用某种高通滤波器来解决您的问题。一种方法是使用模糊过滤器(某种低通过滤器),并从原始部分中减去模糊部分(称为“非锐化遮罩”)。因此,对于低通滤波,您可以使用带有高斯的卷积或仅使用普通盒式滤波器。或者,您也可以使用中值滤波器,这就是我在这里所做的:

在此处输入图片说明

%% setup
v = 0:0.01:1;
[x,y] = meshgrid(v, v);
z0 = cos(pi*x).*cos(pi*y);z = z0; % "baseline" surface

pks = [1,1; 3,3; 7,5; 2,8; 7, 3]/10;% add 5 peaks
for p=pks';
   z = z + exp(-((x-p(1)).^2 + (y-p(2)).^2)/0.02.^2);
end

subplot(221);mesh(x,y,z);title('data');
%% recover "baseline"
z0_ = medfilt2(z, [1,1]*20, 'symmetric'); % low pass filter of your choice

subplot(222);mesh(x,y,z0_);title('recovered baseline');
subplot(223);mesh(x,y,z0_-z0);title('error');

%% subtract recovered baseline
subplot(224);mesh(x,y,z-z0_);title('recovered baseline removed');
Run Code Online (Sandbox Code Playgroud)


mik*_*ski 3

我有一个 Python 解决方案,但我想将其转移到 MATLAB 不会太复杂。

它适用于一堆峰。不过,我做了一些假设,比如有几个峰值。它适用于一个,但如果有几个峰值则更好。峰值可能会重叠。主要假设当然是背景的形状,但如果存在其他模型,则可以对其进行修改。
主要思想是减去一个函数但禁止负值。这是通过额外的成本函数来完成的,为了最小化,我将其保持可微分。因此,接近零的值可能会出现问题。这种情况可以通过迭代额外成本的急剧程度来处理。可以从大约 1 的中等斜率开始,然后使用更陡的斜率和上一次拟合的起始值重新进行拟合。我已经在类似问题上这样做过并且效果很好。从技术上讲,不排除在减去拟合解后存在小的负值,因此对于图像数据,需要额外的步骤来解决这个问题。

这是代码

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy.optimize import least_squares

def peak( x,y, a, x0, y0, s):
    """
    Just a symmetric peak for testing
    """
    return a * np.exp( -( (x - x0 )**2 + ( y - y0 )**2 ) / 2 / s**2 )

def second_order( xx, yy, aa, bb, cc, dd, ee, ff ):
    """
    Assuming that the base can be approximated by a second order equation
    generalization to higher orders should be straight forward
    """
    out = aa * xx**2 + 2 * bb * xx * yy + cc * yy**2 + dd * xx + ee * yy + ff
    return out


def residual_function( params, xa, ya, za, extracost, slope ):
    """
    cost function. Calculates difference from zero-plane
    with ultra high cost for negative values.
    previous solutions to similar problems have shown that sometimes 
    the optimization process has to be iterated with increasing 
    parameter slope ( and maybe extracost )
    """
    aa, bb, cc, dd, ee, ff = params
    ###subtract such that values become as small as possible
    ###
    diffarray = za - second_order( xa, ya, aa, bb, cc, dd, ee, ff )
    diffarray = diffarray.flatten( )
    ### BUT high costs for negative values
    cost = np.fromiter( (  -extracost * ( np.tanh( slope * x ) - 1 ) / 2.0 for x in diffarray ), np.float )
    return np.abs( cost ) + np.abs( diffarray )


### some test data
xl = np.linspace( -3, 5, 50 )
yl = np.linspace( -1, 7, 60 )

XX, YY = np.meshgrid( xl, yl )
 

VV = second_order( XX, YY, 0.1, 0.2, 0.08, 0.28, 1.9, 1.3 ) 
VV = VV + peak( XX, YY, 65, 1, 2, 0.3 )
# ~VV = VV + peak( XX, YY, 55, 3, 4, 0.5 )
# ~VV = VV + peak( XX, YY, 55, -1, 0, 0.4 )
# ~VV = VV + peak( XX, YY, 55, -3, 6, 0.7 )

### the optimization
result = least_squares(residual_function,  x0=( 0.0, 0.0, 0.00, 0.0, 0.0, 0 ), args=( XX, YY, VV, 1e4, 50 ) )
print result
print result.x
subtractme = second_order( XX, YY, *(result.x) ) 
nobase = VV - subtractme

### plotting
fig = plt.figure()
ax = fig.add_subplot( 1, 2, 1, projection='3d' )
ax.plot_surface( XX, YY, VV)
bx = fig.add_subplot( 1, 2, 2, projection='3d' )
bx.plot_surface( XX, YY, nobase)
plt.show()
Run Code Online (Sandbox Code Playgroud)

提供

<< [0.092135 0.18974991 0.06144773 0.37054049 2.05096262 0.88314363]
Run Code Online (Sandbox Code Playgroud)

原始数据和修正数据