【问题标题】:Scale image object to match another object's scale缩放图像对象以匹配另一个对象的比例
【发布时间】:2016-03-02 00:37:15
【问题描述】:

我有两组不同大小的图像,每组。第一组是具有真实图片对象的 400x400 像素的图像。

第二组是 319x319,图像轮廓与真实图片对象的比例不同。

我想要实现的,基本上是将剪影替换为第一组的真实图片对象(即海狸)。所以最终结果将是具有真实图片对象的 319x319 分辨率图像。这是一个例子:

第一组图像不能简单地调整为 319x319,因为海狸与轮廓不匹配。大约有 100 张图像具有不同的“海狸尺寸到海狸的轮廓尺寸”关系。有没有办法自动化这个过程?

到目前为止,我已经尝试了@cxw 建议直到第 2 步。这是我使用的EllipseDirectFit 的代码。这是我的code,用椭圆拟合绘制图像。我不知道如何进行步骤 3-5。我认为 EllipseDirectFit 函数 -> 2*abs(A(1)) 应该是椭圆的主轴。 (注意:'a1.bmp' 是真实图像,'b1.bmp' 是剪影)。

【问题讨论】:

  • 在真实图像或轮廓之外,您是否总是有像问题中所示的纯色背景?
  • 是的,真实图像和剪影的背景总是纯色

标签: image matlab image-processing


【解决方案1】:

如果其他人遇到与我相同的问题,我会发布解决我问题的代码。我实际上遵循cxw 的建议,为真实图片和剪影图片拟合了一个椭圆,然后根据剪影椭圆的长轴与真实椭圆长轴的比率调整了真实图片的大小。这使得图像对象的大小与剪影图像对象(即海狸)相匹配。然后我要么裁剪,要么添加边框像素以匹配我需要的分辨率(即 319x319)。

% fetching the images
realList = getAllFiles('./real_images'); % getAllFiles => StackOverflow function
silhList = getAllFiles('./silhouettes');

for qq = 1:numel(realList)
    % Name of the file to save
    str = realList{qq}(15:end);

    a = imread(realList{qq});   % assign real image
    background_Ra = a(1,1,1);   % getting the background colors
    background_Ga = a(1,1,2);
    background_Ba = a(1,1,3);
    % finding the points (x,y) to pass to fit_ellipse
    [x1,y1]=find(a(:,:,1)~=background_Ra | a(:,:,2)~=background_Ga | a(:,:,3)~=background_Ba);
    % fitting an ellipse to these points
    z1 = fit_ellipse(x1,y1); % Mathworks file exchange function

    b = imread(silhList{qq});   % assign silhouette image
    background_R2b = b(1,1,1);  % getting the background colors
    background_G2b = b(1,1,2);
    background_B2b = b(1,1,3);
    % finding the points (x,y) to pass to fit_ellipse
    [x2,y2]=find(b(:,:,1)~=background_R2b & b(:,:,2)~=background_G2b & b(:,:,3)~=background_B2b);
    % fitting an ellipse to these points
    z2 = fit_ellipse(x2,y2);

    % ratio of silhouette's ellipse major axis to real image's ellipse
    % major axis
    ellaxratio = z2.long_axis/z1.long_axis;
    % resizing based on ellaxratio, so that the real image object size will
    % now fit the silhouette's image object size
    c = imresize(a,ellaxratio); c = rgb2gray(c);
    bordercolor = c(end,end); 

    % if the resulting image is smaller, add pixels around it until they
    % match with the silhouette image resolution
    if size(c) < 319
        while size(c) < 319
            % 'addborder' is a Mathworks file exchange function
            c = addborder(c(:,:,1),1, bordercolor ,'outer'); 
        end
    % if the resulting image is larger, crop pixels until they match
    else size(c) > 319
        while size(c) > 319
            c = c(2:end-1,2:end-1);
        end
    end

    % in a few cases, the resulting resolution is 318x318, instead of
    % 319x319, so a small adjustment won't hurt.
    if size(c) ~= 319
        c = imresize(c,[319 319]);
    end
    % saving..
    imwrite(c,['./good_fits/' str '.bmp'])
end

【讨论】:

    【解决方案2】:

    我没有这方面的代码,但这是我将如何进行的,只是临时的。几乎可以肯定有更好的方法:)。

    1. 对于真实图像和剪影图像中的每一个:

      1. 获取不是背景的像素的X、Y坐标。 编辑 在 Octave 中测试的示例:

        background_R = img(1,1,1)
        background_G = img(1,1,2)
        background_B = img(1,1,3)
        
        [xs,ys]=find(img(:,:,1)~=background_R | img(:,:,2)~=background_G | img(:,:,3)~=background_B)
        

        逻辑 OR 是因为图像在任何颜色成分中都可能与背景不同。

      2. 将椭圆拟合到您找到的 X、Y 坐标对。例如,使用来自 File Exchange 的 this routine。 (实际上,我想您可以使用圆形拟合或任何其他您想要的形状拟合,只要大小和位置是图像的非背景部分之间的唯一区别。)
    2. 现在您有了真实图像和剪影图像的椭圆参数。假设纵横比相同,这些椭圆应该只在中心和比例上有所不同。
    3. 根据轮廓椭圆长轴长度与真实图像椭圆长轴长度的比率调整真实图像 (imresize) 的大小。现在它们的大小应该相同了。
    4. 找到中心。使用上面的 fit 例程,

      A=EllipseDirectFit(...)
      % switch to Mathworld notation from http://mathworld.wolfram.com/Ellipse.html
      ma=A(1); mb=A(2)/2; mc=A(3); md=A(4)/2; mf=A(5)/2; mg=A(6);
      center_x = (mc*md-mb*mf)/(mb**2-ma*mc)
      center_y = (ma*mf-mb*md)/(mb**2-ma*mc)
      
    5. 将真实图像数据移动到 3-d 矩阵中,使椭圆居中 重合。例如,

      cx_silhouette = ... (as above, for the silhouette image)
      cy_silhouette = ...
      cx_real = ... (as above, for the *resized* real image)
      cy_real = ...
      shifted = zeros(size(silhouette_image)) % where we're going to put the real image
      deltax = cx_silhouette - cx_real
      deltay = cy_silhouette - cy_real
      % if deltax==deltay==0, you're done with this step.  If not:
      portion = resized_real_image(max(deltay,0):319-abs(deltay), max(deltax,0):319-abs(deltax), :);  % or something like that - grab the overlapping part of the resized real image
      shifted(max(deltay,0):min(deltay+319,319), max(deltax,0):min(deltax+319,319), :) = portion; % or something like that - slide the portion of the resized real image in x and y.  Now _shifted_ should line up with the silhouette image.
      
    6. 使用背景颜色(或黑色剪影 - 相同的差异)作为蒙版,将像素从调整大小、移动的真实图像复制到剪影图像中。

    希望这会有所帮助!

    【讨论】:

    • 我尝试拟合椭圆或圆形,但它们总是捕获图像的内部部分(即使对于内部纯色的轮廓).. :/
    • 当然,这是有道理的。问题是它们是否捕捉到图像的相同内部部分。由于拟合只涉及 X 和 Y 值,而不涉及像素值,因此无论图像大小或哪个图像,您得到的椭圆都应该覆盖轮廓的相同部分(不一定是整个东西)。那有意义吗?我很乐意进一步了解 --- 如果您愿意,请更新问题以包含到目前为止的代码以及叠加在图像上的拟合椭圆的一些屏幕截图。
    • 这里是我使用的EllipseDirectFit的代码。这是我的code,用椭圆拟合绘制图像。我不知道如何继续您的步骤 3-5。我认为 EllipseDirectFit 函数 -> 2*abs(A(1)) 应该是椭圆的主轴。那是对的吗?顺便说一句,a1.bmp 是真实图像,b1.bmp 是轮廓,就像我的原始帖子一样。
    • 根据您的实际测试代码片段更新了 xs/ys 选择:)。
    • hmmm...但是,这个我已经实现了..它有什么帮助?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    相关资源
    最近更新 更多