Replies: 7 comments 30 replies
-
@kipcole9,
Not sure what you mean, the image won't be in memory when you open right? but it is loaded when the write_to_binary operation is called. That said I am not sure if 10+ms is higher or lower. Do you have some baseline expectations, perhaps from other libraries. I tried to check if it is coming from the libvips or vix,
So It seems libvips call itself takes the whole time and not Vix. |
Beta Was this translation helpful? Give feedback.
-
@akash-akya thanks for kick-starting my brain. I added a one more test to the benchmark that writes a generated image and the results reflect what you said. The writing to binary is only 1.33ms. So It's probably them the
|
Beta Was this translation helpful? Give feedback.
-
Good suggestion. I updated the benchmark to do an
I will take a look about |
Beta Was this translation helpful? Give feedback.
-
@kipcole9 @mat-hek I checked YUV and played around a bit. It seems resizing the image is taking significant time. I got 33% gain by using
Other than that, I couldn't find anything much. I think we should find a way to optimize scaling an image by Found this discussion in libvips: libvips/libvips#2560 |
Beta Was this translation helpful? Give feedback.
-
I went back to basics and just focused on comparing TLDR; the performance constraint isn't Performance results
Observations
ConclusionMy current conclusion is that it is the conversion process that is taking the time. This is similar to the findings in the libvips discussion (albeit that was focused more on the conversion TO rgb. @mat-hek I'm not seeing a path to delivering 30fps processing for 1080p, and probably the same for 720p, images. Unless there are any other insights or ideas I can try, I propose closing this discussion. |
Beta Was this translation helpful? Give feedback.
-
@akash-akya, yes, I'd say libyuv from the Google Chrome project would be the best place to start for a way to get native performance. But ..... let's just say the documentation is "sparse". :-). And as you know, my NIF-fu is not good enough to tackle that with any confidence. Closing the discussion for now, thanks for your patience @akash-akya, and sorry for not finding a path to the performance you need @mat-hek. |
Beta Was this translation helpful? Give feedback.
-
Ok, I tried an approach with overlaying separate planes and it seems it works and it's fast! 13ms for 720p, 18ms for 1080p on my machine. The only problem is that it doesn't consider the alpha channel. Mix.install([:vix, {:image, github: "elixir-image/image", branch: "yuv"}, :benchee])
defmodule Overlay do
alias Vix.Vips.Image, as: Vimage
def run() do
overlay = Image.open!("membrane.png")
yuv = File.read!("image.yuv")
{:ok, overlay_yuv} = Image.YUV.write_to_binary(overlay, :C420)
{overlay_y, overlay_u, overlay_v} = open_planes(overlay_yuv, 400, 400)
# Benchee.run(%{
# yuv: fn ->
{image_y, image_u, image_v} = open_planes(yuv, 1920, 1080)
composed_y = compose_to_binary(image_y, overlay_y)
composed_u = compose_to_binary(image_u, overlay_u)
composed_v = compose_to_binary(image_v, overlay_v)
composed = composed_y <> composed_u <> composed_v
# end
# })
{:ok, output} = Image.YUV.new_from_binary(composed, 1920, 1080, :C420)
Image.write!(output, "output.jpeg")
end
defp open_planes(yuv, width, height) do
half_width = div(width, 2)
half_height = div(height, 2)
y_size = width * height
uv_size = half_width * half_height
<<y::binary-size(y_size), u::binary-size(uv_size), v::binary-size(uv_size)>> = yuv
{:ok, y} = Vimage.new_from_binary(y, width, height, 1, :VIPS_FORMAT_UCHAR)
{:ok, u} = Vimage.new_from_binary(u, half_width, half_height, 1, :VIPS_FORMAT_UCHAR)
{:ok, v} = Vimage.new_from_binary(v, half_width, half_height, 1, :VIPS_FORMAT_UCHAR)
{y, u, v}
end
defp compose_to_binary(image, overlay) do
{:ok, binary} = Image.compose!(image, overlay) |> Image.flatten!() |> Vimage.write_to_binary()
binary
end
end
Overlay.run() And it outputs Any ideas on how I can make it consider the alpha channel of the overlay? Even binary alpha (either fully transparent or no transparency) could be enough. |
Beta Was this translation helpful? Give feedback.
-
@akash-akya, I'm trying to support @mat-hek with consuming and producing YUV images. Whilst functionally complete I am currently not able to meet his performance expectations.
When benchmarking, the primary culprit seems to be
Vix.Vips.Image.write_to_binary/1
which, for a 1920x1080 RGB image takes about 10.8ms. Indeed even when trying to write just a single band of the image it takes the same amount of time.Given that the test image is memory resident, and there is no operations pipeline, 10+ ms seems much higher than I would have expected.
Do you have any explanation or ideas? Or are my expectations incorrect? I wanted to check with you before I ask John's advice as well.
As always, many thanks.
Beta Was this translation helpful? Give feedback.
All reactions