ruby - 使用 Rmagick 和 FFmpeg 实现图片缩放效果

标签 ruby ffmpeg zooming rmagick

我有一张图片,我需要对生成的视频进行缩放效果。我几乎得到了想要的结果..但是。生成的图片看起来有点不稳定。这是因为裁剪和调整大小的四舍五入..所以每次转换时图片的中心都会稍微移动。我能用它做什么?或者也许还有其他方法可以实现它?
在输入中我有
图片,zoom_type,zoom_percent,zoom_duration,scene_duration
这是完成这项工作的部分代码:

img = Magick::ImageList.new(picture).first
width, height = img.columns.to_f, img.rows.to_f
img_fps = 30
if width >= height
  aspect_ratio = (width / height)
  zoom_small_size = ((height * (100 - zoom_percent)) / 100).to_f
  small_size = height
else
  aspect_ratio = (height / width)
  zoom_small_size = ((width * (100 - zoom_percent)) / 100).to_f
  small_size = width
end
factor = (((small_size - zoom_small_size) / (img_fps * zoom_duration))).to_f
while factor < 2
  img_fps -= 1
  factor = ((small_size - zoom_small_size) / (img_fps * zoom_duration))
end
total_images = img_fps * scene_duration
zoom_images = img_fps * zoom_duration_seed
new_width =  width
new_height =  height
zoom_changed_small_size = small_size

total_images.times do |i|
if zoom_images > 0 && zoom_changed_small_size > zoom_small_size
  img_n = img.crop(new_width, new_height, true)
  new_width = (width <= height) ? (new_width - factor).round : (new_width-factor*aspect_ratio).round
  new_height = (width >= height) ? (new_height-factor).round : (new_height-factor*aspect_ratio).round
  zoom_changed_small_size = (width >= height) ? img_n.rows : img_n.columns
  img_n.resize_to_fill!(width, height)
  img_n.write("#{sprintf("img_%04d.jpg" % (i+1))}")
  zoom_images -= 1
  img = img_n.copy if zoom_images == 0 || zoom_changed_small_size <= zoom_small_size
  img_n.destroy!
else
  img.write("#{sprintf("img_%04d.jpg" % (i+1))}")
  puts "Writing - #{img.filename}"
end
end

然后 ffmpeg -y -f image2 -r 30 -i img_%04d.jpg -crf 0 -preset ultrafast -tune stillimage -pix_fmt yuv420p out.mp4

最佳答案

您可以采取的最简单的蛮力方法是在过程开始时将起始图像的大小调整为最大缩放所需的 3 或 4 倍。一旦您将视频帧的大小缩小到(希望)不容易看到或至少不会分散注意力的程度,这将减少整数像素舍入的影响。这种方法的优点是您可以保持大部分现有代码不变。缺点是您需要尝试获得正确的缩放因子,并且根据您的源素材和目标视频大小,您最终可能会处理一些非常大的图像。

如果您不喜欢那个简单的补丁,那么可以在 Image Magick 中使用亚像素采样缩放和平移。 . .

我看过使用 affine_transform ,但实际上它很繁琐。相反,这里使用 distort方法,这似乎是为您的需要而设计的。这个例子需要一个图像,一组定义“ View 矩形”的点(都可以是浮点数),以及放大图像的目标宽度、高度(应该是整数):

def zoom_window image, from_left, from_top, from_right, from_bottom, to_width, to_height
  from_width = (from_right - from_left).to_f
  from_height = (from_bottom - from_top).to_f

  from_centre_x = 0.5 * ( from_left + from_right )
  from_centre_y = 0.5 * ( from_top + from_bottom )

  scale_x = to_width/from_width
  scale_y = to_height/from_height

  zoomed_and_scaled_image = image.distort( Magick::ScaleRotateTranslateDistortion,
    [ from_centre_x, from_centre_y, scale_x, scale_y, 0.0,
    0.5 * to_width, 0.5 * to_height]  ) { |i| i.define("distort:viewport", "#{to_width}x#{to_height}+0+0") }

  zoomed_and_scaled_image
end

我已经测试了这个逐渐缩小 from_ 的输出。矩形,然后使用 ffmpeg 的变体命令 - 它产生了平滑的缩放效果,很好地处理了亚像素精度,即使在极端放大时(当然这些看起来很模糊)。要使用它,您需要计算缩放窗口的浮点坐标,并在当前裁剪和调整大小的位置调用上述方法(或您的变体)img_n .

注意我并没有做太多尝试让这个 Ruby 代码“好”,它只是一个概念验证。

关于ruby - 使用 Rmagick 和 FFmpeg 实现图片缩放效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17185902/

相关文章:

ruby - 安装 gem Nokogiri-1.8.4 时出错

ruby - gets.chomp 不换行

ffmpeg:从 mp3 中删除封面图片/转换为无封面的 ogg

iphone - 使用跨度缩放到用户位置

ruby - 动态设置 Ruby 对象的属性

ruby - 如何在有和没有javascript的情况下运行 cucumber 场景避免代码重复

linux - 使用 mencoder 或 ffmpeg 时特殊字符变得不明确

ios - FFmpeg + iOS + 有损蜂窝连接

javascript - 单击按钮时传单缩放至属性

android - WebView 摆脱双击缩放。