【问题标题】:Matlab - Scale down an image using an average of four pixelsMatlab - 使用平均四个像素缩小图像
【发布时间】:2017-02-19 21:43:00
【问题描述】:

我刚刚开始学习图像处理和 Matlab,我正在尝试使用平均 4 个像素来缩小图像。这意味着对于每 4 个原始像素,我计算平均值并产生 1 个输出像素。 到目前为止,我有以下代码:

img = imread('bird.jpg');
row_size = size(img, 1);
col_size = size(img, 2);
res = zeros(floor(row_size/2), floor(col_size/2));
figure, imshow(img);
for i = 1:2:row_size
    for j = 1:2:col_size
        num = mean([img(i, j), img(i, j+1), img(i+1, j), img(i+1, j+1)]);
        res(round(i/2), round(j/2)) = num;
    end
end
figure, imshow(uint8(res));

此代码设法缩小图像,但将其转换为灰度。 我知道我可能必须计算输出像素的 RGB 分量的平均值,但我不知道如何访问它们、计算平均值并将它们插入结果矩阵。

【问题讨论】:

  • 查看工作空间并查看变量 img。它应该至少是一个 NxMx3 矩阵,其中 N 和 M 是图像的尺寸。您可以像以往一样访问 Matlab 中每个矩阵的每个元素。尝试同时使用命令“who”和“whos”
  • 如果你做A=size(img),你能写出你得到的东西吗? A 中有哪些值?

标签: image matlab image-processing rgb image-scaling


【解决方案1】:

另一种可能的解决方案是使用this link 中提到的函数blockproc。这也将避免 for 循环。

【讨论】:

    【解决方案2】:

    在 Matlab 中,RGB 图像被视为 3D 数组。您可以通过以下方式进行检查:

    depth_size = size(img, 3)
    
    depth_size =
    
         3
    

    正如您所做的那样,循环解决方案在Sardar_Usama's answer 中进行了说明。但是,在 Matlab 中,建议您在想要提高速度时避免循环。

    这是一种矢量化解决方案,可将 RGB 图像按比例缩小n

    img = imread('bird.jpg');
    n = 2; % n can only be integer
    [row_size, col_size] = size(img(:, :, 1));
    
    % getting rid of extra rows and columns that won't be counted in averaging:
    I = img(1:n*floor(row_size / n), 1:n*floor(col_size / n), :);
    [r, ~] = size(I(:, :, 1));
    
    % separating and re-ordering the three colors of image in a way ...
    % that averaging could be done with a single 'mean' command:
    R = reshape(permute(reshape(I(:, :, 1), r, n, []), [2, 1, 3]), n*n, [], 1);
    G = reshape(permute(reshape(I(:, :, 2), r, n, []), [2, 1, 3]), n*n, [], 1);
    B = reshape(permute(reshape(I(:, :, 3), r, n, []), [2, 1, 3]), n*n, [], 1);
    
    % averaging and reshaping the colors back to the image form:
    R_avg = reshape(mean(R), r / n, []);
    G_avg = reshape(mean(G), r / n, []);
    B_avg = reshape(mean(B), r / n, []);
    
    % concatenating the three colors together:
    scaled_img = cat(3, R_avg, G_avg, B_avg); 
    
    % casting the result to the class of original image
    scaled_img = cast(scaled_img, 'like', img); 
    

    基准测试:

    如果您想知道为什么矢量化解决方案更受欢迎,请查看使用这两种方法处理 RGB 768 x 1024 图像需要多长时间:

    ------------------- With vectorized solution:
    Elapsed time is 0.024690 seconds.
    
    ------------------- With nested loop solution:
    Elapsed time is 6.127933 seconds.
    

    所以这两种方案的速度相差超过2个数量级。

    【讨论】:

      【解决方案3】:

      您可以使用以下修改后的代码来解决这个问题:

      img = imread('bird.jpg');
      row_size = size(img, 1);
      col_size = size(img, 2);
      figure, imshow(img);
      
      res = zeros(floor(row_size/2), floor(col_size/2), 3); %Pre-allocation
      for p = 1:2:row_size
          for q = 1:2:col_size
              num = mean([img(p, q,:), img(p, q+1,:), img(p+1, q,:), img(p+1, q+1,:)]);
              res(round(p/2), round(q/2),:) = num;
          end
      end
      figure, imshow(uint8(res));
      

      我拍摄了1200x1600x3 uint8 的示例图像,上面的代码将其转换为600x800x3 uint8,这是正确的,因为(1200*1600)/4 = 480000600*800 = 480000

      PS:我将变量名ij分别更改为pq,因为ij是为imaginary numbers保留的。

      【讨论】:

      • 你可以使用:跳过第三个for循环,我的意思是使用' num = mean([img(p, q,:), img(p, q+1,:, img(p+1, q,:), img(p+1, q+1,:)]); res(round(p/2), round(q/2),:) = num;
      • 谢谢@itzikBenShabat!
      • @itzikBenShabat 你的方法给了我这个错误“分配的非单件右轴尺寸比非单件下标更多。在行 res(round(i/2), round(j/2), :) = 数量;"。你知道为什么吗?
      • @formap 您是否使用与我的答案完全相同的代码?
      • 我打错了。对于那个很抱歉。谢谢你们俩! @itzikBenShabat
      猜你喜欢
      • 2012-08-03
      • 1970-01-01
      • 2018-06-08
      • 2013-11-16
      • 2014-04-24
      • 2012-04-21
      • 1970-01-01
      • 1970-01-01
      • 2016-10-31
      相关资源
      最近更新 更多