【问题标题】:Approximating a fitting image size近似合适的图像大小
【发布时间】:2013-02-20 13:24:57
【问题描述】:

我的目标是从给定数量的尺寸中选择最合适的图像尺寸。

考虑到一些相当随机的分辨率,我想找到一个尺寸尽可能接近我首选尺寸的图像。

假设我想使用大小为宽 x 高 (preferredImageSize) 的图像。

示例:320x200

假设我可以使用以下图像尺寸 (availableImageSize) width1 x height1, width2 x height2, ...(可能多达 10 种不同的尺寸)。

示例:474x272、474x310、264x150、226x128、640x365、474x410、480x276、256x144、160x90、320x182、640x365、192x108、240x137、480

为了开发一些通用的方法来制作preferredImageSize 变量,我正在尝试找到一个很好的解决方案,它计算得相当快,但也能产生在屏幕上看起来不错的东西。

我将在屏幕上看起来不错定义为如下图像:

  1. 几乎没有升级
  2. 尽可能接近给定的纵横比 (preferredImageSize.width / preferredImageSize.height)
  3. 可能会大幅缩减
  4. 可能会被剪裁/拉伸的量非常小

我最初的(相当琐碎的)方法:

遍历可用的图像尺寸一次,找到最小的宽度增量 (abs(preferredImageSize.width - availableImageSize.width))。然后选择具有最小增量的图像 (bestFitWidth)。

这当然是解决问题的一种方法,但绝对不符合我在屏幕上看起来不错的希望。

任何提示,无论是文本、来源还是链接都很棒。哦,如果您认为我的要求(也就是希望)已经导致错误的方向,请继续,让我知道...


编辑:添加了裁剪和拉伸选项 - 恐怕这会使问题更难解决。因此,如果需要,请将其排除在等式之外。

【问题讨论】:

  • 不知道为什么人们不赞成你的问题...我觉得很好...+1
  • 我同意。我认为这是一个不错的问题。

标签: java c image algorithm pseudocode


【解决方案1】:

简单的“如果/那么”方法:

我会做两件事:

  1. 由于您不希望放大,但可以接受缩小(我认为这是一个不错的选择),因此切勿使用小于目标的源图像,除非没有可用的图像。
  2. 由于“大量”缩小是可以的,因此我会尝试找到与纵横比尽可能匹配的图像,从可接受的最小图像开始,然后逐渐变大。

为了把它放在一起,首先从列表中丢弃所有小于目标的图像。然后,从剩下的最小图像开始,检查其与目标的纵横比。如果不匹配是可以接受的(您需要量化),请使用图像,否则转到下一个更大的图像。如果您没有找到任何可接受的,请使用最匹配的那个。

如果您已经丢弃了所有小于目标的图像,那么无论哪种方式,您最终都可能会得到一个看起来很糟糕的图像,但是您应该尝试使用需要更多放大的图像是否更糟糕,或者使用更糟糕的纵横比匹配的图像是否更糟糕。

您需要考虑的另一件事是是否要拉伸或裁剪图像以匹配您的目标纵横比。

更复杂的定量方法:

不过,最灵活的方法是为自己定义一个“惩罚”函数,该函数取决于大小不匹配和纵横比不匹配,然后找到给您最低“惩罚”的源图像。这就是您当前所做的,您已将惩罚函数定义为abs(preferredImageSize.width - availableImageSize.width)。您可以使用更复杂的东西,例如:

width_diff  = preferredImageSize.width  - availableImageSize.width
height_diff = preferredImageSize.height - availableImageSize.height
if (width_diff > 0) width_penalty = upscale_penalty   * width_diff
               else width_penalty = downscale_penalty * width_diff
if (height_diff > 0) height_penalty = upscale_penalty   * height_diff
                else height_penalty = downscale_penalty * height_diff
aspect_penalty = ((preferredImageSize.width / preferredImageSize.height) - 
                  (availableImageSize.width / availableImageSize.height)) * stretch_penalty;
total_penalty = width_penalty + height_penalty + aspect_penalty;

现在您可以使用 3 个数字 upscale_penaltydownscale_penaltystretch_penalty 来赋予这三个质量降低操作不同的重要性。只需尝试几种组合,看看哪种效果最好。

【讨论】:

  • 我喜欢这种方法。我想引入一点权重并使用它的值实际上可能会奏效。谢谢! +1
  • 现在我实现了一个遵循您的加权误差计算想法的解决方案。为了标准化宽度/高度误差,我将它们除以它们的首选宽度/高度(不完全确定这是否是一个好主意)。选择的权重是; upscaleWeight = 3.0f, downscalingWeight = 0.1f, aspectRatioWeight = 2.0f;。总的来说,我认为现在的结果非常好。此外,我添加了一个动态计算模式,以确保仅在将新大小作为输入值时才进行此计算。再次感谢!!
猜你喜欢
  • 2013-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
  • 2013-08-09
相关资源
最近更新 更多