-
Notifications
You must be signed in to change notification settings - Fork 277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Outline effect class #982
base: develop
Are you sure you want to change the base?
Conversation
…remove unused include
…rocess and combining masks for improved output quality
…al of aliased edges
Thanks for sharing! I was able to compile and test this effect, but I'm unclear on exactly it's purpose. Can you add a few images to this PR, which illustrate the before / after of this effect, and describe it's purpose clearly (i.e. when is this useful). Also, I've attached a few changes below, to make this effect available to the OpenShot UI. NOTE: When testing in the UI, an icon needs to be added here:
|
NOTE: Please switch to Chrome if your Safari web player could not play this H265 video. For some reason H265 video cannot be played normally on macOS. Hi, I've just apply your patch and modify it a bit since this effect requires OpenCV, so it will only be available if OpenCV is linked. Sorry I didn't notice those modifications since I only used The purpose is pretty simple: Adding outline (or stroke) to the edge of non-transparent parts of an transparent image since a In my use case, this is my example: The video with original text: original.mp4The video with outlined text, color, outline width are are keyframed: outlined.mp4And this is the example Python code: import openshot
import os
from contextlib import ExitStack
setting = openshot.Settings.Instance()
setting.OMP_THREADS = 16
setting.FF_THREADS = 8
setting.VIDEO_CACHE_PERCENT_AHEAD = 0
setting.VIDEO_CACHE_MIN_PREROLL_FRAMES = 0
setting.VIDEO_CACHE_MAX_PREROLL_FRAMES = 0
setting.VIDEO_CACHE_MAX_FRAMES = 0
setting.ENABLE_PLAYBACK_CACHING = False
setting.HIGH_QUALITY_SCALING = True
setting.DEBUG_TO_STDERR = False
width = 1080
height = 1920
fps = openshot.Fraction(24, 1)
audio_bitrate = 44100
audio_channels = 2
audio_channel_layout = openshot.LAYOUT_STEREO
pixel_ratio = openshot.Fraction(1, 1)
location = os.path.dirname(__file__)
with ExitStack() as stack:
timeline = openshot.Timeline(width, height, fps, audio_bitrate, audio_channels, audio_channel_layout)
r = openshot.FFmpegReader("background.mp4")
r.Open()
stack.callback(r.Close)
c = openshot.Clip(r)
c.Position(0)
c.gravity = openshot.GRAVITY_CENTER
c.Layer(1)
c.Open()
stack.callback(c.Close)
timeline.AddClip(c)
outline_width = openshot.Keyframe()
outline_width.AddPoint(1, 15, openshot.BEZIER)
outline_width.AddPoint(24, 30, openshot.BEZIER)
outline_width.AddPoint(48, 45, openshot.BEZIER)
outline_width.AddPoint(96, 30, openshot.BEZIER)
outline_width.AddPoint(120, 15, openshot.BEZIER)
color = openshot.Keyframe()
color.AddPoint(1, 0, openshot.BEZIER)
color.AddPoint(48, 144, openshot.BEZIER)
color.AddPoint(120, 0, openshot.BEZIER)
alpha = openshot.Keyframe()
alpha.AddPoint(1, 255)
outline_fx = openshot.Outline(outline_width, color, color, color, alpha)
txt = openshot.TextReader(
width, height,
0, 0,
openshot.GRAVITY_CENTER,
"OpenShot is awesome!",
"Roboto-Regular.ttf",
100,
"white",
"transparent"
)
txt.Open()
stack.callback(txt.Close)
txt_c = openshot.Clip(txt)
txt_c.Start(0)
txt_c.End(20)
txt_c.Position(0)
txt_c.AddEffect(outline_fx)
txt_c.scale = openshot.SCALE_NONE
txt_c.gravity = openshot.GRAVITY_CENTER
txt_c.Layer(2)
txt_c.Open()
stack.callback(txt_c.Close)
timeline.AddClip(txt_c)
timeline.Open()
stack.callback(timeline.Close)
w = openshot.FFmpegWriter(os.path.join(location, "example.mp4"))
w.SetAudioOptions(False, "libvorbis", 44100, 2, openshot.LAYOUT_STEREO, 128000)
w.SetVideoOptions(True, "libx265", fps, width, height, pixel_ratio, False, False, 3000000)
w.PrepareStreams()
w.SetOption(openshot.VIDEO_STREAM, "crf", "28")
w.SetOption(openshot.VIDEO_STREAM, "preset", "ultrafast")
w.WriteHeader()
w.Open()
stack.callback(w.Close)
# w.WriteFrame(timeline, 1, math.floor(r.info.duration * float(fps)))
w.WriteFrame(timeline, 1, 120)
w.WriteTrailer() |
@jonoomph Hi Jon, I've added my description and update some more details to it. Please check it out! |
Since OpenShot reader classes don't support stroke (some are intentionally disabled for some reason like ImageMagick's Reader, some are not trivial to implement like Qt's Readers). In my experience, a lot of works require adding stroke to the image/text.
One approach is adding the outline to the image before importing into OpenShot. This is not really handy since the stroke width cannot be keyframed. And adding text requires rasterizing the text into a blank, which is not easy to preview.
To make it easier, I created a rough Outline effect implementation based on OpenCV to solve this problem.
My implementation in general:
De-antialias by threshold the alpha channel and create an alpha mask base on the de-antialiased channelNote: I'm not a skilled C++ programmer and not understand the libopenshot code base thoroughly, so the implementation in opencv might not be as fast as it should. Currently my implementation has two problem:
The outline is pretty jaggy, which requires antialiasing.Partly solved by utilizing canny and gaussian blur.Please check this out! Thanks for reading