TL;DR: Is there an Elixir lib out there that implements a version of Evision’s getPerspectiveTransform
where I can just pass two lists of simple coordinates?
The X in my XY problem is that I recently started a new job that relies on a lot of image processing. Their current implementation is a little old and slow running on ImageMagick. I’ve been doing some spikes with Image
and Vix
(kudos and many thanks, Kip and Akash—very good work) to try and move it over to libvips but, as I’ve learned is sort of a thing, libvips does not support perspective distortions which we do need.
Thanks to a couple of good ol’ stack overflow posts and github comments, I’ve been able to get halfway there (code below for those who are interested) but now stuck on actually creating a transformation matrix.
I’ve read a bunch on the topic and will prob eventually figure it out, but I’m just wondering if anyone else has done this and has an easy answer Even if I do figure out how to use Evision in the way I want, it’s a pretty heavy dependency to bring in to call one function. Also just interested in general image discussion
Anyway, thanks!
Here is the perspective code—sorry for the shitty variable names:
def skew(%Vix.Vips.Image{} = image, {t0, t1, t2, t3, t4, t5, t6, t7} = _this_is_the_transform_matrix_i_need_to_generate) do
alias Vix.Vips.Operation, as: O
{width, height} = {Image.width(image), Image.height(image)}
with {:ok, index_image} <- O.xyz(width, height),
{:ok, copy_image} <- O.copy(index_image),
{:ok, band_0} <- O.extract_band(index_image, 0),
{:ok, band_1} <- O.extract_band(copy_image, 1),
{:ok, x_1} <- O.linear(band_0, [t0], [0]),
{:ok, x_2} <- O.linear(band_1, [t1], [0]),
{:ok, x_3} <- O.add(x_1, x_2),
{:ok, x_a} <- O.linear(x_3, [1], [t2]),
{:ok, x_4} <- O.linear(band_0, [t6], [0]),
{:ok, x_5} <- O.linear(band_1, [t7], [0]),
{:ok, x_6} <- O.add(x_4, x_5),
{:ok, x_b} <- O.linear(x_6, [1], [1]),
{:ok, x} <- O.divide(x_a, x_b),
{:ok, y_1} <- O.linear(band_0, [t3], [0]),
{:ok, y_2} <- O.linear(band_1, [t4], [0]),
{:ok, y_3} <- O.add(y_1, y_2),
{:ok, y_a} <- O.linear(y_3, [1], [t5]),
{:ok, y_4} <- O.linear(band_0, [t6], [0]),
{:ok, y_5} <- O.linear(band_1, [t7], [0]),
{:ok, y_6} <- O.add(y_4, y_5),
{:ok, y_b} <- O.linear(y_6, [1], [1]),
{:ok, y} <- O.divide(y_a, y_b),
{:ok, mapimage} <- O.bandjoin([x, y]),
{:ok, image} <- O.mapim(image, mapimage) do
Image.write!(image, "is_it_working_yet.jpg")
end
end