7

我正在寻找一种算法或 C++/Matlab 库,可用于分离两个相乘的图像。下面给出了这个问题的可视化示例。

图像 1 可以是任何东西(例如相对复杂的场景)。图 2 非常简单,可以用数学方法生成。图像 2 总是具有相似的形态(即下降趋势)。通过将图像 1 乘以图像 2(使用逐点乘法),我们得到转换后的图像。

只给定转换后的图像,我想估计图像 1 或图像 2。有没有算法可以做到这一点?

以下是 Matlab 代码和图像:

load('trans.mat');
imageA = imread('room.jpg');
imageB = abs(response);  % loaded from MAT file

[m,n] = size(imageA);
image1 = rgb2gray( imresize(im2double(imageA), [m n]) );
image2 = imresize(im2double(imageB), [m n]);

figure; imagesc(image1); colormap gray; title('Image 1 of Room')
colorbar

figure; imagesc(image2); colormap gray; title('Image 2 of Response')
colorbar

% This is image1 and image2 multiplied together (point-by-point)
trans = image1 .* image2;
figure; imagesc(trans); colormap gray; title('Transformed Image')
colorbar

图 1 图 2 转换后的图像

更新

有很多方法可以解决这个问题。这是我的实验结果。感谢所有回答我问题的人!

1、图像的低通滤波

正如duskwuff 所指出的,对变换后的图像进行低通滤波器会返回图像2 的近似值。在这种情况下,低通滤波器是高斯的。您可以看到使用低通滤波器可以识别图像中的乘性噪声。

原始图像 高斯低通滤波图像

2.同态滤波

正如 EitenT 所建议的,我检查了同态滤波。知道这种类型的图像过滤的名称后,我设法找到了一些我认为有助于解决类似问题的参考资料。

  1. SP 银行、信号处理、图像处理和模式识别。纽约:普伦蒂斯霍尔,1990 年。

  2. A. Oppenheim, R. Schafer 和 J. Stockham, T.,“乘法和卷积信号的非线性滤波”,IEEE Transactions on Audio and Electroacoustics,第一卷。16,没有。3,第 437 – 466 页,1968 年 9 月。

  3. 盲图像反卷积:理论与应用。博卡拉顿:CRC 出版社,2007 年。

Blind image deconvolution一书的第5章特别好,里面有很多同态滤波的参考资料。这可能是最通用的方法,可以在许多不同的应用程序中很好地工作。

3.优化使用fminsearch

正如 Serg 所建议的,我使用了一个目标函数fminsearch。由于我知道噪声的数学模型,因此我能够将其用作优化算法的输入。 这种方法完全是针对特定问题的,并且可能并不总是在所有情况下都有用。

这是图像2的重建:

重构图像

这是图像 1 的重建,通过除以图像 2 的重建形成:

图 1

这是包含噪声的图像:

包含噪声的图像

源代码

这是我的问题的源代码。如代码所示,这是一个非常具体的应用程序,并非在所有情况下都能正常工作。

N = 1001;
q = zeros(N, 1);
q(1:200) = 55;
q(201:300) = 120;
q(301:400) = 70;
q(401:600) = 40;
q(601:800) = 100;
q(801:1001) = 70;
dt = 0.0042;
fs = 1 / dt;
wSize = 101;
Glim = 20;
ginv = 0;
[R, ~, ~] = get_response(N, q, dt, wSize, Glim, ginv);
rows = wSize;
cols = N;
cut_val = 200;

figure; imagesc(abs(R)); title('Matrix output of algorithm')
colorbar

figure;
imagesc(abs(R)); title('abs(response)')

figure;
imagesc(imag(R)); title('imag(response)')

imageA = imread('room.jpg');

% images should be of the same size
[m,n] = size(R);
image1 =  rgb2gray( imresize(im2double(imageA), [m n]) );


% here is the multiplication (with the image in complex space)
trans = ((image1.*1i)) .* (R(end:-1:1, :));


figure;
imagesc(abs(trans)); colormap(gray);


% take the imaginary part of the response
imagLogR = imag(log(trans)); 


% The beginning and end points are not usable
Mderiv = zeros(rows, cols-2);
for k = 1:rows
   val = deriv_3pt(imagLogR(k,:), dt);
   val(val > cut_val) = 0;
   Mderiv(k,:) = val(1:end-1);
end


% This is the derivative of the imaginary part of R
% d/dtau(imag((log(R)))
% Do we need to remove spurious values from the matrix?
figure; 
imagesc(abs(log(Mderiv)));


disp('Running iteration');
% Apply curve-fitting to get back the values
% by cycling over the cols
q0 = 10;
q1 = 500;
NN = cols - 2;
qout = zeros(NN, 1);
for k = 1:NN
    data = Mderiv(:,k); 
    qout(k) = fminbnd(@(q) curve_fit_to_get_q(q, dt, rows, data),q0,q1);
end


figure; plot(q); title('q value input as vector'); 
ylim([0 200]); xlim([0 1001])

figure;
plot(qout); title('Reconstructed q')
ylim([0 200]); xlim([0 1001])

% make the vector the same size as the other
qout2 = [qout(1); qout; qout(end)];

% get the reconstructed response
[RR, ~, ~] = get_response(N, qout2, dt, wSize, Glim, ginv);
RR = RR(end:-1:1,:);

figure; imagesc(abs(RR)); colormap gray 
title('Reconstructed Image 2')
colorbar; 

% here is the reconstructed image of the room
% NOTE the division in the imagesc function
check0 = image1 .* abs(R(end:-1:1, :));
figure; imagesc(check0./abs(RR)); colormap gray
title('Reconstructed Image 1')
colorbar; 

figure; imagesc(check0); colormap gray
title('Original image with noise pattern')
colorbar; 

function [response, L, inte] = get_response(N, Q, dt, wSize, Glim, ginv)

fs = 1 / dt; 
Npad = wSize - 1; 
N1 = wSize + Npad;
N2 = floor(N1 / 2 + 1);
f = (fs/2)*linspace(0,1,N2);
omega = 2 * pi .* f';
omegah = 2 * pi * f(end);
sigma2 = exp(-(0.23*Glim + 1.63));

sign = 1;
if(ginv == 1)
    sign = -1;
end

ratio = omega ./ omegah;
rs_r = zeros(N2, 1);  
rs_i = zeros(N2, 1);   
termr = zeros(N2, 1);
termi = zeros(N2, 1);
termr_sub1 = zeros(N2, 1);
termi_sub1 = zeros(N2, 1);
response = zeros(N2, N);
L = zeros(N2, N);
inte = zeros(N2, N);

 % cycle over cols of matrix
for ti = 1:N               

    term0 = omega ./ (2 .* Q(ti));
    gamma = 1 / (pi * Q(ti));

    % calculate for the real part
    if(ti == 1)
        Lambda = ones(N2, 1);
        termr_sub1(1) = 0;  
        termr_sub1(2:end) = term0(2:end) .* (ratio(2:end).^-gamma);  
    else
        termr(1) = 0; 
        termr(2:end) = term0(2:end) .* (ratio(2:end).^-gamma); 
        rs_r = rs_r - dt.*(termr + termr_sub1);
        termr_sub1 = termr;
        Beta = exp( -1 .* -0.5 .* rs_r );

        Lambda = (Beta + sigma2) ./ (Beta.^2 + sigma2);  % vector
    end 

    % calculate for the complex part  
    if(ginv == 1)  
        termi(1) = 0;
        termi(2:end) = (ratio(2:end).^(sign .* gamma) - 1) .* omega(2:end);
    else
        termi = (ratio.^(sign .* gamma) - 1) .* omega;
    end
    rs_i = rs_i - dt.*(termi + termi_sub1);
    termi_sub1 = termi;
    integrand = exp( 1i .* -0.5 .* rs_i );

    L(:,ti) = Lambda;
    inte(:,ti) = integrand;

    if(ginv == 1) 
        response(:,ti) = Lambda .* integrand;
    else        
        response(:,ti) = (1 ./ Lambda) .* integrand;
    end  
end % ti loop

function sse = curve_fit_to_get_q(q, dt, rows, data)

% q = trial q value
% dt = timestep
% rows = number of rows
% data = actual dataset

fs = 1 / dt;
N2 = rows;
f = (fs/2)*linspace(0,1,N2);  % vector for frequency along cols
omega = 2 * pi .* f';
omegah = 2 * pi * f(end);
ratio = omega ./ omegah;

gamma = 1 / (pi * q);

% calculate for the complex part  
termi = ((ratio.^(gamma)) - 1) .* omega;

% for now, just reverse termi 
termi = termi(end:-1:1);
% 

% Do non-linear curve-fitting

% termi is a column-vector with the generated noise pattern 
% data is the log-transformed image
% sse is the value that is returned to fminsearchbnd
Error_Vector =  termi - data;
sse = sum(Error_Vector.^2);

function output = deriv_3pt(x, dt)

N = length(x);
N0 = N - 1;
output = zeros(N0, 1);
denom = 2 * dt;

for k = 2:N0 
   output(k - 1) = (x(k+1) - x(k-1)) / denom;  
end
4

2 回答 2

5

This is going to be a difficult, unreliable process, as you're fundamentally trying to extract information (the separation of the two images) which has been destroyed. Bringing it back perfectly is impossible; the best you can do is guess.

If the second image is always going to be relatively "smooth", you may be able to reconstruct it (or, at least, an approximation of it) by applying a strong low-pass filter to the transformed image. With that in hand, you can invert the multiplication, or equivalently use a complementary high-pass filter to get the first image. It won't be quite the same, but it'll at least be something.

于 2012-08-19T17:46:46.967 回答
3

我会尝试约束优化(fmincon在 Matlab 中)。如果您了解第二张图像的来源/性质,您可能可以定义一个生成相似噪声模式的多元函数。目标函数可以是生成的噪声图像和最后一个图像之间的相关性。

于 2012-08-20T12:31:51.540 回答