philomena/lib/philomena_web/image_reverse.ex

74 lines
1.7 KiB
Elixir

defmodule PhilomenaWeb.ImageReverse do
alias PhilomenaMedia.Analyzers
alias PhilomenaMedia.Processors
alias Philomena.DuplicateReports
alias Philomena.Repo
import Ecto.Query
def images(image_params) do
image_params
|> Map.get("image")
|> analyze()
|> intensities()
|> case do
:error ->
[]
{analysis, intensities} ->
{width, height} = analysis.dimensions
aspect = width / height
dist = parse_dist(image_params)
limit = parse_limit(image_params)
{intensities, aspect}
|> DuplicateReports.find_duplicates(dist: dist, aspect_dist: dist, limit: limit)
|> preload([:user, :intensity, [:sources, tags: :aliases]])
|> Repo.all()
end
end
defp analyze(%Plug.Upload{path: path}) do
case Analyzers.analyze(path) do
{:ok, analysis} -> {analysis, path}
_ -> :error
end
end
defp analyze(_upload), do: :error
defp intensities(:error), do: :error
defp intensities({analysis, path}) do
{analysis, Processors.intensities(analysis, path)}
end
# The distance metric is taxicab distance, not Euclidean,
# because this is more efficient to index.
defp parse_dist(%{"distance" => distance}) do
distance
|> Decimal.parse()
|> case do
{value, _rest} -> Decimal.to_float(value)
_ -> 0.25
end
|> clamp(0.01, 1.0)
end
defp parse_dist(_params), do: 0.25
defp parse_limit(%{"limit" => limit}) do
limit
|> Integer.parse()
|> case do
{limit, _rest} -> limit
_ -> 10
end
|> clamp(1, 50)
end
defp parse_limit(_params), do: 10
defp clamp(n, min, _max) when n < min, do: min
defp clamp(n, _min, max) when n > max, do: max
defp clamp(n, _min, _max), do: n
end