double类型的帧必须在0到1的范围内:MATLAB

时间:2016-08-14 17:36:10

标签: matlab image-processing matlab-cvst

我有一个视频,我在MATLAB上为它制作了一个Sobel模板。现在,我必须通过for循环读取每一帧,在视频的每一帧上应用Sobel掩码。这个过程就像:

  • 第1步:阅读框架。
  • 第2步:使用rgb2gray将其转换为灰度。
  • 第3步:将其转换为双倍。

这里,当我尝试在生成的video.avi文件上写入帧时应用掩码后,出现以下错误:

  

"类型double的帧必须在0到1和#34之间;

我的代码出了什么问题?我写的代码如下所示:

vid = VideoReader('me.mp4');
frames = read(vid);
total = get(vid, 'NumberOfFrames');
write = VideoWriter('me.avi');
open(write);
mask1 = [-1 -2 -1; 0 0 0; 1 2 1]; % Horizontal mask
mask2 = [-1 0 1; -2 0 2; -1 0 1]; %Vertical Mask
for k = 1 : 125
    image = frames(:,:,:,k);
    obj = image;
    obj1 = rgb2gray(obj);
    obj2=double(obj1);
    for row = 2 : size(obj2, 1) - 1
        for col = 2 : size(obj2, 2) - 1
            c1 = obj2(row - 1, col - 1) * mask1(1 ,1);
            c2 = obj2(row - 1, col) * mask1(1 ,2);
            c3 = obj2(row - 1, col + 1) * mask1(1 ,3);
            c4 = obj2(row, col - 1)*mask1(2, 1);
            c5 = obj2(row, col)*mask1(2, 2);
            c6 = obj2(row, col + 1)*mask1(2, 3);
            c7 = obj2(row + 1, col - 1)*mask1(3,1);
            c8 = obj2(row + 1, col)*mask1(3,2);
            c9 = obj2(row + 1, col + 1)*mask1(3,3);
            c11 = obj2(row - 1, col - 1)*mask2(1 , 1);
            c22 = obj2(row, col - 1)*mask2(2, 1);
            c33 = obj2(row + 1, col - 1)*mask2(3, 1);
            c44 = obj2(row -1, col)*mask2(1, 2);
            c55 = obj2(row, col)*mask2(2 , 2);
            c66 = obj2(row +1, col)*mask2(2 , 3);
            c77 = obj2(row - 1, col + 1)*mask2(1 , 3);
            c88 = obj2(row, col +1)*mask2(2 , 3);
            c99 = obj2(row + 1, col + 1)*mask2(3 , 3);
            result = c1 + c2 + c3 +c4 +c5+ c6+ c7+ c8 +c9;
            result2 = c11 + c22 + c33 + c44 + c55 + c66 + c77 + c88 + c99;
            %result = double(result);
            %result2 = double(result2);
            rim1(row, col) = ((result^2+result2^2) *1/2);
            rim2(row, col) = atan(result/result2);
        end
    end
    writeVideo(write, rim2); %This line has the problem with rim2 as rim2 is the frame i'm trying to write on the video file.
end
close(write);

2 个答案:

答案 0 :(得分:2)

rim2循环中的for行正在使用atan,它将生成正数和负数值 - 从-pi / 2到+ pi / 2 。 rim2的值必须介于[0,1]之间。我无法弄清楚你究竟在做什么,但看起来你正在计算每个像素位置的幅度和渐变角度。如果要计算幅度,则必须取结果的平方根,而不是简单地乘以1/2。梯度的计算(......甚至整个Sobel滤波器计算......)非常有趣。

我只是假设这是为了你的目的而工作,所以我不确定如何更改rim2的输出以获得合适的显示,但也许你可以将其缩放到[0,1]的范围之前你写这个视频,使它在这个范围内。

在你编写框架之前,这样的东西会起作用:

rim2 = (rim2 - min(rim2(:))) / (max(rim2(:)) - min(rim2(:)));
writeVideo(write, rim2);

以上是您在实践中看到的典型最小 - 最大标准化。具体而言,上述将确保最小值为0,而最大值为每帧1。如果您希望在所有框架上保持一致,只需添加pi/2,然后除以pi。这假设最小值为-1,最大值为+1 ,但。。

rim2 = (rim2 + pi/2) / pi;
writeVideo(write, rim2);

但是,我怀疑你想要将幅度写入文件,而不是角度。因此,请将rim1替换为rim2而不是rim1(row, col) = ((result^2+result2^2)^(1/2)); % or use sqrt: % rim1(row, col) = sqrt(result^2 + result2^2); 替换视频写入,然后进行标准化。确保您的渐变计算正确:

rim1 = (rim1 - min(rim1(:))) / (max(rim1(:)) - min(rim1(:)));
writeVideo(write, rim1);

现在写入文件:

for

但是,如果我可以提供效率方法,请不要使用'same循环来计算渐变和角度。使用conv2并确保使用图片处理工具箱中的VideoWriter'标记或imfilter为您执行过滤,然后计算渐变和角度矢量化。此外,转换为灰度并在主循环中一次性投射帧。我假设你有图像处理工具箱,因为你拥有计算机视觉工具箱(当你使用vid = VideoReader('me.mp4'); frames = read(vid); total = get(vid, 'NumberOfFrames'); write = VideoWriter('me.avi'); open(write); mask1 = [-1 -2 -1; 0 0 0; 1 2 1]; % Horizontal mask mask2 = [-1 0 1; -2 0 2; -1 0 1]; %Vertical Mask for k = 1 : 125 obj2 = double(rgb2gray(frames(:,:,:,k))); % New grad1 = imfilter(obj2, mask1); % New grad2 = imfilter(obj2, mask2); % New rim1 = sqrt(grad1.^2 + grad2.^2); % New rim2 = atan2(grad1, grad2); % New % Normalize rim2 = (rim2 - min(rim2(:))) / (max(rim2(:)) - min(rim2(:))); writeVideo(write, rim2); end close(write); 对象时,你有这个)以及图像处理工具箱是大多数人拥有的:

{{1}}

答案 1 :(得分:2)

rim2最后有[-pi/2, pi/2]范围,与期望[0,1]范围的写函数不兼容。 使用[0,1]函数将其转换为mat2gray范围,即

writeVideo(write, mat2gray(rim2));

您的代码将按预期工作(在我的机器上确认)。

顺便说一句,这不会影响您的代码,但可能您的意思是im2double(A)而不是double(A)。前者产生了一个适当的" [0,1]范围内的灰度图像,而后者只是将[{0,255]范围内的uint8图像转换为double格式(即[0.0,255.0])。