绕x轴旋转图像 [英] Rotate an image around its x-axis

查看:265
本文介绍了绕x轴旋转图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要围绕x轴(或y轴)旋转图像。我可以使用avisynth轻松创建这样的动画,但是现在我需要使用Python的moviepy模块实现该效果。我可以使用以下脚本轻松旋转图像,但需要一些线索以2D或3D旋转图像。

I need to rotate an image around its x-axis (or y-axis). I can easily create such an animation with avisynth, but now I need to implement that effect with Python's moviepy module. I can easily rotate an image with the following script but need some clues how to rotate it in 2D or 3D.

from moviepy.editor import *

clip = ImageClip('my_image.jpg')
rotated_clip = (clip.add_mask()
                .fx(vfx.resize, width=300, height=300)
                .fx(vfx.rotate, lambda t: 90*t, expand=False)
                .set_duration(5))
final_clip = CompositeVideoClip([rotated_clip.set_pos("center")], size=(800,800), bg_color=3*[255])
final_clip.write_videofile("test.mp4", fps=25, codec="libx264")

这里是实际上生成该示例图像的avisynth脚本。请注意,它确实需要 QUAD插件。

Here is the avisynth script that actually generated that example image. Please note, it does require "QUAD" plugin.

function stars(clip c, int r) {
    c.Overlay(x=rand(c.width),y=rand(c.height),BlankClip(c,width=1,height=1,color=$030301*rand(85)))
    (r==0)? last : stars(r-1)
    Trim(0,-1).Loop(c.Framecount, 0, 0)
}
width= 800
height=600
length=100000
Tcolor=$000040
Bcolor=$000018

StackVertical(BlankClip(length=length,width=2,height=1,color=TColor,pixel_type="RGB32"),BlankClip(length=length,width=2,height=1,color=BColor)).BilinearResize(width,2*height,src_top=0,src_height=2).Crop(0,height/2,0,-height/2).Stars(width*height/3072)

ImageSource("path_to_image.png", start=0, end=total_time, fps=300, pixel_type="RGB32")
#BlankClip(length=length,FPS=25,width=640,height=480,color=$000018,pixel_type="RGB32")

#ColorBars()
HALFCYCLE=10                        # Frames in 1 HALF rotation (spinning clip)
NSPIN   = 1                         # Number of HALF rotations in spinning clip
NSTILL  = 10                        # Frames in STILL clip
V       = 0.2                       # Tilt/Yaw
tim     = PI / HALFCYCLE

ScriptClip("""

    c=last
    t=tim*current_frame
    t1x= 0.5 -  0.5 * cos(t)        # BOTH Left
    t2x= 0.5 +  0.5 * cos(t)        # BOTH Right
    #
    t1y= 0.0 +  V * sin(t)          # ] both Top's opposite sign
    t2y= 0.0 -  V * sin(t)          # ] 
    t3y= 1.0 +  V * sin(t)          # [ both Bottoms opposite sign
    t4y= 1.0 -  V * sin(t)          # [
    ResetMask
    quad(t1x,t1y, t2x,t2y, t2x,t3y, t1x,t4y,  normal=true)
    #Overlay(c,last,mask=last.ShowAlpha())


""")

SPIN=Trim(0,-(NSPIN*HALFCYCLE +1))     # Spinning clip, + 1 to complete last spin
STILL=SPIN.Trim(SPIN.FrameCount-1,-1).Loop(NSTILL,0,0)
SPIN2=Trim((NSPIN%2 ==0)?0:HALFCYCLE,-(NSPIN*HALFCYCLE +1))
SPIN ++ STILL ++ SPIN2
Return Last


推荐答案

一种方法是使用Vapory,MoviePy的作者是另一个库,这有助于通过Python操作POV-Ray。您可以在3D场景中创建一个矩形,然后将其围绕任意轴旋转,以固定的间隔将帧保存到MoviePy剪辑中。

One way to do this is to use Vapory, another library by the author of MoviePy, which facilitates the operation of POV-Ray via Python. You can create a rectangle within a 3D scene and rotate it around whatever axis you like, saving frames into a MoviePy clip at intervals.

from moviepy.editor import concatenate, ImageClip, VideoClip
from vapory import *

img_path = './baseball.png'
img_clip = ImageClip(img_path)
W, H = img_clip.w, img_clip.h
AR = 1.0*W/H

# Set rotation rate by defining the period (in seconds) for 360 deg. revolution
t_rev = 2.0

t_half = t_rev/2.0  # The time required for a half revolution
t_still = 0.8 # How long (in seconds) to hold the half rotated image still


# Static POV-Ray objects
cam = Camera('location', [ 0,  0, -1],
             'look_at',  [ 0,  0,  0])
light = LightSource([0, 0, -1]) # Light at camera location
bg = Background('color', [0, 0, 0]) # Black background


def scene(t):
    """ Returns the scene at time 't' (in seconds) """
    s = Scene(camera = cam, objects = [light, bg])

    # Add POV-Ray box with image textured on it
    s = s.add_objects([
          Box([0, 0, 0],
              [W, H, 0],
              Texture(Pigment(ImageMap('"{}"'.format(img_path), 'once')),
                      Finish('ambient', 1.0)),
              'translate', [-0.5, -0.5, 0],
              'scale', [AR, 1, 0],
              'rotate', [0, (360/t_rev)*t, 0])]) # Can change axis of rotation here
    return s


def make_frame(t):
    return scene(t).render(width=W, height=H, antialiasing=0.1)


still_1 = VideoClip(make_frame).to_ImageClip(t=0).set_duration(t_still)
half_1  = VideoClip(make_frame).subclip(0, t_half)
still_2 = VideoClip(make_frame).to_ImageClip(t=t_half).set_duration(t_still)
half_2  = VideoClip(make_frame).subclip(t_half, t_rev)

final_clip = concatenate([still_1, half_1, still_2, half_2])
final_clip.write_gif("./baseball_rot.gif", fps=15)



输出GIF



Output GIF

您可能要更改的主要内容是 img_path t_rev (完整360度旋转的时间), t_sti ll ,以及输出帧频。

The main things you might want to change are img_path, t_rev (the time for a full 360 degree revolution), t_still, and the output frame rate.

我从示例图片中删除了一列像素,将其缩小到均匀宽度(150 px)。如果只想制作GIF,这并不重要,但是如果您想生成x264编码的MP4,则可能应该使用mod2尺寸。

I removed one column of pixels from your example image to get it down to an even width (150 px). It's not important if you only want to make GIFs, but if you want to produce an x264-encoded MP4, you should probably use mod2 dimensions.

使用光线跟踪器解决此问题,但这是我想到的第一个 working 解决方案。我想将图像表示为3D场景中的2D矩形,我可以在其中简单地指定旋转角度,而3D库将处理其余的图像。

It seems like overkill to use a ray tracer for this problem, but it's the first working solution I came up with. I wanted to represent the image as a 2D rectangle in a 3D scene, where I could simply specify an angle of rotation and the 3D library would handle the rest.

可以使用scikit-image的投影变换来解决此问题,例如此MoviePy示例。请特别注意,该代码清单中间附近的 trapzWarp 函数。

It should be possible to solve this problem using a projective transform from scikit-image, as in this MoviePy example. Note specifically, the trapzWarp function near the middle of that code listing.

这篇关于绕x轴旋转图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆