philomena/lib/philomena_web/controllers/search/reverse_controller.ex

65 lines
1.5 KiB
Elixir
Raw Normal View History

2019-11-29 01:11:05 +01:00
defmodule PhilomenaWeb.Search.ReverseController do
use PhilomenaWeb, :controller
alias Philomena.Processors
alias Philomena.DuplicateReports
alias Philomena.Repo
import Ecto.Query
plug PhilomenaWeb.ScraperPlug, [params_key: "image", params_name: "image"] when action in [:create]
def index(conn, _params) do
render(conn, "index.html", images: nil)
end
def create(conn, %{"image" => image_params}) do
images =
image_params["image"].path
|> mime()
|> analyze()
|> intensities()
|> case do
:error ->
[]
{analysis, intensities} ->
{width, height} = analysis.dimensions
aspect = width / height
dist = normalize_dist(image_params)
DuplicateReports.duplicates_of(intensities, aspect, dist, dist)
|> preload(:tags)
|> Repo.all()
end
conn
|> render("index.html", images: images)
end
defp mime(file) do
{:ok, mime} = Philomena.Mime.file(file)
{mime, file}
end
defp analyze({mime, file}) do
case Processors.analyzers(mime) do
nil -> :error
a -> {a.analyze(file), mime, file}
end
end
defp intensities(:error), do: :error
defp intensities({analysis, mime, file}) do
{analysis, Processors.processors(mime).intensities(analysis, file)}
end
# The distance metric is taxicab distance, not Euclidean,
# because this is more efficient to index.
defp normalize_dist(%{"distance" => distance}) do
distance
|> String.to_float()
|> max(0.01)
|> min(1.0)
end
end