【问题标题】:Automatic separation of two images that have been multiplied together自动分离已相乘的两个图像
【发布时间】:2012-08-15 05:47:10
【问题描述】:

我正在寻找一种算法或 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.图像的低通滤波

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

2。同态滤波

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

  1. S。 P. Banks,信号处理、图像处理和模式识别。纽约:Prentice Hall,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 的重建相除:

这是包含噪声的图像:

源代码

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

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

【问题讨论】:

  • 你在这里描述的是某种乘法干涉。您可能会发现 homomorphic filtering 适合您的任务。
  • @EitanT:谢谢,EitanT。您能否推荐一个关于同态过滤问题的好的参考资料(书籍、论文或算法)?
  • 嗯,没有什么比googling it 更简单的了(您会立即获得有关该主题的各种文章)。但请记住,您阅读的任何方法都只是一种估计,您永远无法始终如一地完全恢复您的图像。
  • @EitanT:是的,在搜索中使用“乘性噪声”确实为我指明了正确的方向。谢谢,EitanT。
  • 即使使用给定的算法,这也不是一件容易的事。它们中的大多数在各种图像上都不能很好地工作。无论如何,祝你好运:)

标签: c++ image matlab image-processing


【解决方案1】:

这将是一个困难且不可靠的过程,因为您从根本上试图提取已被破坏的信息(两个图像的分离)。完全恢复它是不可能的。你能做的最好的就是猜测。

如果第二张图像总是相对“平滑”,您可以通过对变换后的图像应用强低通滤波器来重建它(或者至少是它的近似值)。有了它,您可以反转乘法,或者等效地使用互补高通滤波器来获得第一张图像。不会完全一样,但至少会有所不同。

【讨论】:

  • 谢谢,黄昏;这是对这个问题的一个非常有趣的看法。第二张图像总是相对“平滑”并且总是看起来“相似”。我会进一步探索,然后再回复您。
【解决方案2】:

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

【讨论】:

  • 谢谢,塞尔格;这是一个有趣的建议。我可以定义一个生成“相似”噪声模式的多元模式。生成模式的函数f(a) 实际上依赖于单个变量a,但我不知道所有图像的a。但是假设我选择a 作为近似值,我生成噪声模式,然后在频域中执行二维相关。二维相关的输出也是矩阵吗?据我了解,fmincon 要求将目标函数输出作为实标量值最小化。
  • 从二维相关矩阵中,如何得到一个标量值?
  • 当我将trans 矩阵的一列与image2 的同一列相关联时,使用xcorr 函数的零滞后时的一维相关性似乎最大化,所以我认为作为相关性的目标函数可能运作良好。我会再探索一些,然后跟进。
  • 我会使用:c = corr(img1(:), img2(:)),其中img1 是噪声图像,img2 是生成的噪声模式。这将返回一个可用作目标的标量。 fmincon 最小化目标,因此您可以最小化 -c
  • 谢谢,塞尔格;我会试试看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多