如何使用Octave和矩阵操作来平均多个图像以降低噪声?

时间:2014-06-13 17:57:43

标签: image algorithm matlab image-processing octave

UPDATE 这是我的代码,用于将两个矩阵相加并逐个元素地使用,然后除以二。

function [ finish ] = stackAndMeanImage (initFrame, finalFrame)

cd 'C:\Users\Disc-1119\Desktop\Internships\Tracking\Octave\highway\highway (6-13-2014 11-13-41 AM)';

pkg load image; 

i = initFrame;
f = finalFrame;

astr = num2str(i);

tmp = imread(astr, 'jpg');

d = f - i

for a = 1:d

        a

        astr = num2str(i + 1);

        read_tmp = imread(astr, 'jpg');

        read_tmp = rgb2gray(read_tmp);

        tmp = tmp  :+ read_tmp; 

        tmp = tmp / 2; 


end 

imwrite(tmp, 'meanimage.JPG');

finish = 'done';
end

以下是两个示例输入图像

http://imgur.com/5DR1ccS,AWBEI0d#1

这是一个输出图像

http://imgur.com/aX6b0kj

我对发生的事情感到很困惑。我还没有实现其他答案所说的内容。

OLD

我正在开发一个图像处理项目,我现在手动选择“空”或只有背景的图像,这样我的算法就可以计算差异,然后做更多的分析,我有一个简单的部分计算两个图像的平均值的代码,我已经将其转换为灰度矩阵,但这仅适用于两个图像,因为当我找到两个平均值时,取这个均值并找到这个与下一个图像的平均值,反复这样做,我最终得到了一张完全无用的褪色白色图像。你甚至看不到任何东西。

我发现Matlab中有一个名为imFuse的函数可以对图像进行平均。我想知道是否有人知道imFuse用来组合图像的过程,我很高兴将其实现到Octave,或者如果有人知道或已经编写了一段代码来实现类似的东西。再一次,我不是要求任何人为我编写代码,只是想知道这个过程是什么,以及是否已经存在预先存在的函数,我在研究后没有找到。

谢谢,

AeroVTP

2 个答案:

答案 0 :(得分:2)

你不应该得到一张褪色的图像。相反,你应该得到一个图像,从技术上讲,它是暂时低通滤波的。这意味着一半的信息内容是最后一张图片,四分之一来自最后一张图片,一张八张来自最后一张图片,等等。

实际上,运动图像中的效果类似于响应时间慢的显示。

如果你最终得到一张白色图片,那么你做错了什么。 nkjt对类型挑战的猜测很好。另一种可能性是你在将两张图像相加后忘记除以二。

还有一件事......如果您对图像进行线性操作(例如平均),则图像强度比例应为线性。如果您只是使用RGB值或一些简单的灰度值,您可能会被图像的非线性所困扰。此属性称为伽马校正。 (不可否认,大多数图像处理程序都忽略了这个问题,因为它并不总是一个很大的挑战。)

当您的项目计算图像的差异时,您应该考虑到这一点。我建议使用线性化的浮点值。不幸的是,线性化取决于图像数据的来源。

另一方面,平均通常是降低噪音的最有效方法。因此,假设图像足够相似,那么您就在正确的轨道上。


然而,在看了一下你的图像后,你似乎真的想要做一些其他事情,而不是平均图像。如果我理解你的意图正确,你想摆脱你的公路凸轮中的汽车,只给你无车的背景,然后你可以从图像中减去汽车。

如果这是你想要做的,你应该考虑使用中值滤波器而不是平均值。这意味着您需要连续11帧。然后,对于每个像素,您有11个不同的值。现在您订购(排序)这些值并将中间(第6个)作为背景像素值。

如果您的道路在大多数时间都是空的(至少6帧,共11帧),那么第6个样本将代表道路,无论通过相机的汽车的颜色如何。

如果您有一条空路,则中值滤波的结果接近平均值。 (高斯白噪声的平均值更好,但差异不是很大。)但是你的平均值会受到白车或黑车的影响,而中值滤波则不会。

中值滤波的问题在于它是计算密集型的。我很遗憾我说的是非常破碎和古老的Octave,所以我不能给你任何有用的代码。在MatLab或PyLab中,您可以将11个图像堆叠到M x N x 11阵列,然后沿深度轴使用单个中值命令。 (当我说密集时,我并不是说它不能用你的数据实时完成。它可以,但它比平均要复杂得多。)


如果你真的有很多交通,那么在不到一半的时间里,车辆后面的道路是可见的。那么中间技巧将失败。您将需要采取更多样本,然后找到最典型的值,因为它可能是道路(除非所有车辆都有相似的颜色)。在那里使用彩色图像会有很大帮助,因为汽车在RGB或HSV中看起来彼此之间的差异比灰度级要大。

不幸的是,如果您需要采用这种类型的处理方式,路径会稍微滑溜而且很崎岖。平均值非常简单快速,中位数很容易(但不是那么快),但事情往往变得相当复杂。


另一个BTW进入我的脑海。如果你想要一个滚动平均值,有一个非常简单有效的方法来计算它具有任意长度(任意帧数平均):

# N is the number of images to average
# P[i] are the input frames
# S is a sum accumulator (sum of N frames)

# calculate the sum of the first N frames
S <- 0
I <- 0
while I < N
    S <- S + P[I]
    I <- I + 1

# save_img() saves an averaged image
while there are images to process
    save_img(S / N)
    S <- -P[I-N] + S + P[I]
    I <- I + 1

当然,你可能想要使用for循环,+ =和 - =运算符,但仍然有想法。对于每个帧,您只需要一个减法,一个加法和一个除以常量(如果您赶时间,可以将其修改为乘法或甚至按位移位)。

答案 1 :(得分:2)

我可能误解了你的问题,但我认为你要做的是以下几点。基本上,将所有图像读入矩阵,然后使用mean()。这提供了你能够将它们全部放在内存中。

function [finish] = stackAndMeanImage (ini_frame, final_frame)
  pkg load image;

  dir_path = 'C:\Users\Disc-1119\Desktop\Internships\Tracking\Octave\highway\highway (6-13-2014 11-13-41 AM)';

  imgs = cell (1, 1, d);

  ## read all images into a cell array
  current_frame = ini_frame;
  for n = 1:(final_frame - ini_frame)
    fname = fullfile (dir_path, sprintf ("%i", current_frame++));
    imgs{n} = rgb2gray (imread (fname, "jpg"));
  endfor

  ## create 3D matrix out of all frames and calculate mean across 3rd dimension
  imgs = cell2mat (imgs);
  avg = mean (imgs, 3);

  ## mean returns double precision so we cast it back to uint8 after
  ## rescaling it to range [0 1]. This assumes that images were all
  ## originally uint8, but since they are jpgs, that's a safe assumption
  avg = im2uint8 (avg ./255);

  imwrite (avg, fullfile (dir_path, "meanimage.jpg"));
  finish = "done";

endfunction