From 33f91af1af429500686025114fe4d49e9ab744a1 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Sat, 6 Jun 2020 12:39:26 +0200 Subject: [PATCH 1/6] add photils plugin --- README.md | 1 + contrib/photils.lua | 416 ++++++++++++++++++++++++++++ locale/de_DE/LC_MESSAGES/photils.po | 83 ++++++ 3 files changed, 500 insertions(+) create mode 100644 contrib/photils.lua create mode 100644 locale/de_DE/LC_MESSAGES/photils.po diff --git a/README.md b/README.md index 49551e5..2381dbc 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ LabelsToTags|Yes|LMW|Apply tags based on color labels and ratings OpenInExplorer|No|LMW|Open the selected images in the system file manager passport_guide|Yes|LMW|Add passport cropping guide to darkroom crop tool pdf_slideshow|No|LM|Export images to a PDF slideshow +[photils](https://github.com/scheckmedia/photils-dt)|No|LM|Automatic tag suggestions for your images quicktag|Yes|LMW|Create shortcuts for quickly applying tags rate_group|Yes|LMW|Apply or remove a star rating from grouped images rename-tags|Yes|LMW|Change a tag name diff --git a/contrib/photils.lua b/contrib/photils.lua new file mode 100644 index 0000000..102bd4d --- /dev/null +++ b/contrib/photils.lua @@ -0,0 +1,416 @@ +--[[ photils Auto Tagging plugin + copyright (c) 2020 Tobias Scheck + + darktable is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + darktable is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with darktable. If not, see . +--]] + +--[[ + A darktable plugin which tries to predict keywords based on the selected image. + This plugin uses photils-cli to handle this task. Photils-cli is an application + which passes the image through a neural network and generates a feature vector. + This feature vector will be used to find similar images in a self-hosted online + database and the corresponding tags. The usage of the feature vector has this advantage + that at no time your selected image will leave the PC. Rather a representation + of the image is sent. + + ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT + * photils-cli - https://github.com/scheckmedia/photils-cli + + USAGE + * require this script from your main lua file + To do this add this line to the file .config/darktable/luarc: + require "contrib/photils" + * Select an image + * Press "Get Tags" + * Select the tags you want from a list of suggestions + * Press "Attach .. Tags" to add the selected tags to your image +--]] + +local dt = require "darktable" +local du = require "lib/dtutils" +local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" + +local MODULE_NAME = "photils" +du.check_min_api_version("5.0.0", MODULE_NAME) + +local PS = dt.configuration.running_os == "windows" and "\\" or "/" +local gettext = dt.gettext +gettext.bindtextdomain(MODULE_NAME, + dt.configuration.config_dir .. PS .. "lua" .. PS .. "locale" .. PS) + +local exporter = dt.new_format("jpeg") +exporter.quality = 80 +exporter.max_height = 224 +exporter.max_width = 224 + +-- helper functions + +local function _(msgid) + return gettext.dgettext(MODULE_NAME, msgid) +end + +local function num_keys(tbl) + local num = 0 + for _ in pairs(tbl) do num = num + 1 end + return num +end + +local function has_key(tbl, value) + for k, _ in pairs(tbl) do + if k == value then + return true + end + end + + return false +end + +local photils_installed = df.check_if_bin_exists("photils-cli") + +--[[ + local state object + + maybe per_page is a preference variable but I think 10 + is a good value for the ui +]] +local PHOTILS = { + tags = {}, + page = 1, + per_page = 10, + selected_tags = {}, + in_pagination = false, + tagged_image = "" +} + +local GUI = { + container = dt.new_widget("box") { + orientation = "vertical", + sensitive = true, + dt.new_widget("button") { + label = _("Get Tags"), + sensitive = photils_installed, + clicked_callback = function() PHOTILS.on_tags_clicked() end + }, + reset_callback = function() PHOTILS.on_reset(true) end + }, + stack = dt.new_widget("stack"), + prev_button = dt.new_widget("button") { + label = "<", + sensitive = false, + clicked_callback = function() + PHOTILS.page = PHOTILS.page - 1 + PHOTILS.paginate() + end + }, + next_button = dt.new_widget("button") { + label = ">", + sensitive = false, + clicked_callback = function() + PHOTILS.page = PHOTILS.page + 1 + PHOTILS.paginate() + end + }, + tag_box = dt.new_widget("box") {orientation = "vertical"}, + tag_view = dt.new_widget("box") {orientation = "vertical"}, + page_label = dt.new_widget("label") {label = ""}, + error_view = dt.new_widget("box") {orientation = "vertical"}, + warning_label = dt.new_widget("label") { + label = "" + }, + restart_required_label = dt.new_widget("label") { + label = _("requires a restart to be applied") + }, + attach_button = dt.new_widget("button") { + label = "", + sensitive = false, + clicked_callback = function() PHOTILS.attach_tags() end + }, + confidence_slider = dt.new_widget("slider") { + step = 1, + digits = 0, + value = 90, + hard_max = 100, + hard_min = 0, + soft_max = 100, + soft_min = 0, + label = _("Min Confidence Value") + }, + warning = dt.new_widget("label") +} + +function PHOTILS.image_changed() + local current_image = tostring(dt.gui.selection()[1]) + if current_image ~= PHOTILS.tagged_image then + if PHOTILS.tagged_image ~= "" then + PHOTILS.tagged_image_has_changed() + end + + PHOTILS.tagged_image = tostring(current_image) + end +end + +function PHOTILS.tagged_image_has_changed() + GUI.warning.label = _( + "The suggested tags were not generated\n for the currently selected image!") +end + +function PHOTILS.paginate() + PHOTILS.in_pagination = true + local num_pages = math.ceil(#PHOTILS.tags / PHOTILS.per_page) + GUI.page_label.label = string.format(_(" Page %s of %s "), PHOTILS.page, + num_pages) + + if PHOTILS.page <= 1 then + PHOTILS.page = 1 + GUI.prev_button.sensitive = false + else + GUI.prev_button.sensitive = true + end + + if PHOTILS.page > num_pages - 1 then + PHOTILS.page = num_pages + GUI.next_button.sensitive = false + else + GUI.next_button.sensitive = true + end + + local offset = ((PHOTILS.page - 1) * PHOTILS.per_page) + 1 + local tag_index = 1 + for i = offset, offset + PHOTILS.per_page - 1, 1 do + local tag = PHOTILS.tags[i] + GUI.tag_box[tag_index].value = has_key(PHOTILS.selected_tags, tag) + + if tag then + GUI.tag_box[tag_index].label = tag + GUI.tag_box[tag_index].sensitive = true + else + GUI.tag_box[tag_index].label = "" + GUI.tag_box[tag_index].sensitive = false + end + tag_index = tag_index + 1 + end + + PHOTILS.in_pagination = false +end + +function PHOTILS.attach_tags() + local image = dt.gui.selection()[1] + for tag, _ in pairs(PHOTILS.selected_tags) do + local dt_tag = dt.tags.create(tag) + dt.tags.attach(dt_tag, image) + end + + dt.print(_("Tags successfully attached to image")) +end + +function PHOTILS.get_tmp_file() + local tmp_file = os.tmpname() + if dt.configuration.running_os == "windows" then + tmp_file = dt.configuration.tmp_dir .. tmp_file -- windows os.tmpname() defaults to root directory + end + + local f = io.open(tmp_file, "w") + if not f then + dt.print_log(string.format(_("Error writing to `%s`"), tmp_file)) + os.remove(tmp_file) + return nil + end + + return tmp_file +end + +function PHOTILS.get_tags(image, with_export) + local tmp_file = PHOTILS.get_tmp_file() + local in_arg = df.sanitize_filename(tostring(image)) + local out_arg = df.sanitize_filename(tmp_file) + local executable = photils_installed + + if dt.configuration.running_os == "macos" then + executable = executable .. "/Contents/MacOS/photils-cli" + end + + if with_export then + dt.print_log("use export to for prediction") + local export_file = PHOTILS.get_tmp_file() + exporter:write_image(image, export_file) + in_arg = df.sanitize_filename(tostring(export_file)) + end + + local command = executable .. " -c " .. " -i " .. in_arg .. " -o " .. out_arg + + local ret = dtsys.external_command(command) + if ret > 0 then + dt.print_error(string.format("command %s returned error code %d", command, ret)) + os.remove(tmp_file) + + -- try to export the image and run tagging + if not with_export then + return PHOTILS.get_tags(image, true) + end + + return false + end + + for i = #PHOTILS.tags, 1, -1 do + PHOTILS.tags[i] = nil + end + + for tag in io.lines(tmp_file) do + local splitted = du.split(tag, ":") + if 100 * tonumber(splitted[2]) >= GUI.confidence_slider.value then + PHOTILS.tags[#PHOTILS.tags + 1] = splitted[1] + end + end + + dt.print(string.format(_("%s found %d tags for your image"), MODULE_NAME, + #PHOTILS.tags)) + os.remove(tmp_file) + + return true +end + +function PHOTILS.on_tags_clicked() + PHOTILS.page = 1 + GUI.warning.label = "" + + PHOTILS.on_reset(false) + + local images = dt.gui.selection() + + if #images == 0 then + dt.print(_("No image selected.")) + dt.control.sleep(2000) + else + if #images > 1 then + dt.print(_("This plugin can only handle a single image.")) + dt.gui.selection({images[1]}) + dt.control.sleep(2000) + end + + if not PHOTILS.get_tags(images[1], true) then + local msg = string.format(_("%s failed, see terminal output for details"), MODULE_NAME) + GUI.warning_label.label = msg + GUI.stack.active = GUI.error_view + dt.print(msg) + return + end + + if #PHOTILS.tags == 0 then + local msg = string.format(_("No tags where found"), MODULE_NAME) + GUI.warning_label.label = msg + GUI.stack.active = GUI.error_view + return + end + + GUI.stack.active = GUI.tag_view + PHOTILS.paginate() + end +end + +function PHOTILS.tag_selected(tag_button) + if PHOTILS.in_pagination then return end + + if tag_button.value then + PHOTILS.selected_tags[tag_button.label] = tag_button.label + else + PHOTILS.selected_tags[tag_button.label] = nil + end + + local num_selected = num_keys(PHOTILS.selected_tags) + if num_selected == 0 then + GUI.attach_button.label = "" + GUI.attach_button.sensitive = false + else + GUI.attach_button.label = string.format(_("Attach %d Tags"), + num_selected) + GUI.attach_button.sensitive = true + end +end + +function PHOTILS.on_reset(with_view) + if with_view then GUI.stack.active = 1 end + + for k, _ in pairs(PHOTILS.selected_tags) do + PHOTILS.selected_tags[k] = nil + end + + for _, v in ipairs(GUI.tag_box) do + v.value = false + end + + GUI.attach_button.label = "" + GUI.attach_button.sensitive = false +end + +-- add a fix number of buttons +for _ = 1, PHOTILS.per_page, 1 do + local btn_tag = dt.new_widget("check_button") { + label = "", + sensitive = false, + clicked_callback = PHOTILS.tag_selected + } + + table.insert(GUI.tag_box, btn_tag) +end + +if not photils_installed then + GUI.warning_label.label = _("photils-cli not found") + dt.print_log(_("photils-cli not found")) +else + GUI.warning_label.label = _("Select an image, click \"Get Tags\" and get \nsuggestions for tags.") +end + +GUI.pagination = dt.new_widget("box") { + orientation = "horizontal", + GUI.prev_button, + GUI.page_label, + GUI.next_button +} + + +table.insert(GUI.error_view, GUI.warning_label) +if not photils_installed then + table.insert(GUI.error_view, df.executable_path_widget({"photils-cli"})) + table.insert(GUI.error_view, GUI.restart_required_label) +end +table.insert(GUI.stack, GUI.error_view) +table.insert(GUI.stack, GUI.tag_view) + +table.insert(GUI.tag_view, GUI.pagination) +table.insert(GUI.tag_view, GUI.tag_box) +table.insert(GUI.tag_view, GUI.attach_button) +table.insert(GUI.tag_view, GUI.warning) + +table.insert(GUI.container, GUI.confidence_slider) +table.insert(GUI.container, GUI.stack) + +GUI.stack.active = 1 + +local plugin_display_views = { + [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}, + [dt.gui.views.darkroom] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 100} +} + +-- dt.control.dispatch(PHOTILS.image_changed) +dt.register_event("mouse-over-image-changed",PHOTILS.image_changed) +dt.register_lib(MODULE_NAME, + "photils autotagger", + true, + true, + plugin_display_views, + GUI.container, + nil, + nil +) diff --git a/locale/de_DE/LC_MESSAGES/photils.po b/locale/de_DE/LC_MESSAGES/photils.po new file mode 100644 index 0000000..f1480a1 --- /dev/null +++ b/locale/de_DE/LC_MESSAGES/photils.po @@ -0,0 +1,83 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Lua photils\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-12 13:12+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../../../contrib/photils.lua:97 +msgid "Get Tags" +msgstr "Hole Stichwörter" + +#: ../../../contrib/photils.lua:128 +msgid "requires a restart to be applied" +msgstr "erfordert die Neustart um angewendet zu werden" + +#: ../../../contrib/photils.lua:155 +msgid "" +"The suggested tags were not generated\n" +" for the currently selected image!" +msgstr "" +"Die vorgeschlagenen Stichwörter wurden für das\n" +"aktuell ausgewählte Bild nicht generiert!" + +#: ../../../contrib/photils.lua:161 +#, lua-format +msgid " Page %s of %s " +msgstr " Seite %s von %s " + +#: ../../../contrib/photils.lua:204 +msgid "Tags successfully attached to image" +msgstr "Stichwörter erfolgreich an Bild angefügt" + +#: ../../../contrib/photils.lua:215 +#, lua-format +msgid "Error writing to `%s`" +msgstr "Fehler beim Schreiben in `%s`" + +#: ../../../contrib/photils.lua:229 +#, lua-format +msgid "%s failed, see terminal output for details" +msgstr "%s fehlgeschlagen, siehe Terminal-Ausgabe für Details" + +#: ../../../contrib/photils.lua:243 +#, lua-format +msgid "%s found %d tags for your image" +msgstr "%s gefunden %d-Stichwörter für Ihr Bild" + +#: ../../../contrib/photils.lua:257 +msgid "No image selected." +msgstr "Kein Bild ausgewählt." + +#: ../../../contrib/photils.lua:262 +msgid "This plugin can only handle a single image." +msgstr "Dieses Plugin kann nur ein einziges Bild verarbeiten." + +#: ../../../contrib/photils.lua:293 +#, lua-format +msgid "Attach %d Tags" +msgstr "%d-Stichwörter anhängen" + +#: ../../../contrib/photils.lua:326 ../../../contrib/photils.lua:327 +msgid "photils-cli not found" +msgstr "photils-cli nicht gefunden" + +#: ../../../contrib/photils.lua:329 +msgid "" +"Select an image, click \"Get Tags\" and get \n" +"suggestions for tags." +msgstr "" +"Wählen Sie ein Bild aus, drücken Sie \"Hole Stichwörter\"\n" +" und erhalten Sie Vorschläge für Stichwörter." From 60fa4b9ee02fe67b4844ff639a7cd77db3030818 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Tue, 9 Jun 2020 08:50:26 +0200 Subject: [PATCH 2/6] update description --- contrib/photils.lua | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index 102bd4d..f4a046e 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -16,13 +16,11 @@ --]] --[[ - A darktable plugin which tries to predict keywords based on the selected image. - This plugin uses photils-cli to handle this task. Photils-cli is an application - which passes the image through a neural network and generates a feature vector. - This feature vector will be used to find similar images in a self-hosted online - database and the corresponding tags. The usage of the feature vector has this advantage - that at no time your selected image will leave the PC. Rather a representation - of the image is sent. + A darktable plugin that tries to predict keywords based on the selected image. + This plugin uses photils-cli to handle this task. Photils-cli is an application + that passes the image through a neural network, classifies it, and extracts the + suggested tags. Everything happens offline without the need that your data are + sent over the internet. ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT * photils-cli - https://github.com/scheckmedia/photils-cli From fd97ac18da3c87a039b756a512a9a18aa15f3cf9 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Wed, 10 Jun 2020 14:48:18 +0200 Subject: [PATCH 3/6] add comments for clarification; formatting --- contrib/photils.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index f4a046e..f498903 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -160,8 +160,7 @@ function PHOTILS.image_changed() end function PHOTILS.tagged_image_has_changed() - GUI.warning.label = _( - "The suggested tags were not generated\n for the currently selected image!") + GUI.warning.label = _("The suggested tags were not generated\n for the currently selected image!") end function PHOTILS.paginate() @@ -184,6 +183,13 @@ function PHOTILS.paginate() GUI.next_button.sensitive = true end + --[[ + calculates the start positon in the tag array based on the current page + and takes N tags from that array to show these in darktable + e.g. page 1 goes from 1 to 10, page 2 from 11 to 20 a.s.o. + the paginaton approach is related to a problem with the dynamic addition + of mutliple widgets https://github.com/darktable-org/darktable/issues/4934#event-3318100463 + ]]-- local offset = ((PHOTILS.page - 1) * PHOTILS.per_page) + 1 local tag_index = 1 for i = offset, offset + PHOTILS.per_page - 1, 1 do From 2e27b812d6f619737d37ab3823545fce5937bba4 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Wed, 10 Jun 2020 14:48:27 +0200 Subject: [PATCH 4/6] fix spelling --- locale/de_DE/LC_MESSAGES/photils.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/de_DE/LC_MESSAGES/photils.po b/locale/de_DE/LC_MESSAGES/photils.po index f1480a1..0acd02a 100644 --- a/locale/de_DE/LC_MESSAGES/photils.po +++ b/locale/de_DE/LC_MESSAGES/photils.po @@ -23,7 +23,7 @@ msgstr "Hole Stichwörter" #: ../../../contrib/photils.lua:128 msgid "requires a restart to be applied" -msgstr "erfordert die Neustart um angewendet zu werden" +msgstr "erfordert einen Neustart um angewendet zu werden" #: ../../../contrib/photils.lua:155 msgid "" From 1378441dfa74fa72f8cce5afbdba895eee071bd3 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Sun, 14 Jun 2020 07:47:28 +0200 Subject: [PATCH 5/6] change labels to lower case to fit darktable style --- contrib/photils.lua | 14 +++++++------- locale/de_DE/LC_MESSAGES/photils.po | 28 +++++++++------------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index f498903..39b71b9 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -30,7 +30,7 @@ To do this add this line to the file .config/darktable/luarc: require "contrib/photils" * Select an image - * Press "Get Tags" + * Press "get tags" * Select the tags you want from a list of suggestions * Press "Attach .. Tags" to add the selected tags to your image --]] @@ -97,7 +97,7 @@ local GUI = { orientation = "vertical", sensitive = true, dt.new_widget("button") { - label = _("Get Tags"), + label = _("get tags"), sensitive = photils_installed, clicked_callback = function() PHOTILS.on_tags_clicked() end }, @@ -143,7 +143,7 @@ local GUI = { hard_min = 0, soft_max = 100, soft_min = 0, - label = _("Min Confidence Value") + label = _("min confidence value") }, warning = dt.new_widget("label") } @@ -166,7 +166,7 @@ end function PHOTILS.paginate() PHOTILS.in_pagination = true local num_pages = math.ceil(#PHOTILS.tags / PHOTILS.per_page) - GUI.page_label.label = string.format(_(" Page %s of %s "), PHOTILS.page, + GUI.page_label.label = string.format(_(" page %s of %s "), PHOTILS.page, num_pages) if PHOTILS.page <= 1 then @@ -312,7 +312,7 @@ function PHOTILS.on_tags_clicked() end if #PHOTILS.tags == 0 then - local msg = string.format(_("No tags where found"), MODULE_NAME) + local msg = string.format(_("no tags where found"), MODULE_NAME) GUI.warning_label.label = msg GUI.stack.active = GUI.error_view return @@ -337,7 +337,7 @@ function PHOTILS.tag_selected(tag_button) GUI.attach_button.label = "" GUI.attach_button.sensitive = false else - GUI.attach_button.label = string.format(_("Attach %d Tags"), + GUI.attach_button.label = string.format(_("attach %d tags"), num_selected) GUI.attach_button.sensitive = true end @@ -373,7 +373,7 @@ if not photils_installed then GUI.warning_label.label = _("photils-cli not found") dt.print_log(_("photils-cli not found")) else - GUI.warning_label.label = _("Select an image, click \"Get Tags\" and get \nsuggestions for tags.") + GUI.warning_label.label = _("Select an image, click \"get tags\" and get \nsuggestions for tags.") end GUI.pagination = dt.new_widget("box") { diff --git a/locale/de_DE/LC_MESSAGES/photils.po b/locale/de_DE/LC_MESSAGES/photils.po index 0acd02a..b81dbc7 100644 --- a/locale/de_DE/LC_MESSAGES/photils.po +++ b/locale/de_DE/LC_MESSAGES/photils.po @@ -17,15 +17,15 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../../../contrib/photils.lua:97 -msgid "Get Tags" -msgstr "Hole Stichwörter" +msgid "get tags" +msgstr "hole stichwörter" -#: ../../../contrib/photils.lua:128 msgid "requires a restart to be applied" msgstr "erfordert einen Neustart um angewendet zu werden" -#: ../../../contrib/photils.lua:155 +msgid "min confidence value" +msgstr "min vertrauenswert" + msgid "" "The suggested tags were not generated\n" " for the currently selected image!" @@ -33,48 +33,38 @@ msgstr "" "Die vorgeschlagenen Stichwörter wurden für das\n" "aktuell ausgewählte Bild nicht generiert!" -#: ../../../contrib/photils.lua:161 #, lua-format -msgid " Page %s of %s " -msgstr " Seite %s von %s " +msgid " page %s of %s " +msgstr " seite %s von %s " -#: ../../../contrib/photils.lua:204 msgid "Tags successfully attached to image" msgstr "Stichwörter erfolgreich an Bild angefügt" -#: ../../../contrib/photils.lua:215 #, lua-format msgid "Error writing to `%s`" msgstr "Fehler beim Schreiben in `%s`" -#: ../../../contrib/photils.lua:229 #, lua-format msgid "%s failed, see terminal output for details" msgstr "%s fehlgeschlagen, siehe Terminal-Ausgabe für Details" -#: ../../../contrib/photils.lua:243 #, lua-format msgid "%s found %d tags for your image" msgstr "%s gefunden %d-Stichwörter für Ihr Bild" -#: ../../../contrib/photils.lua:257 msgid "No image selected." msgstr "Kein Bild ausgewählt." -#: ../../../contrib/photils.lua:262 msgid "This plugin can only handle a single image." msgstr "Dieses Plugin kann nur ein einziges Bild verarbeiten." -#: ../../../contrib/photils.lua:293 #, lua-format -msgid "Attach %d Tags" -msgstr "%d-Stichwörter anhängen" +msgid "attach %d tags" +msgstr "%d stichwörter anhängen" -#: ../../../contrib/photils.lua:326 ../../../contrib/photils.lua:327 msgid "photils-cli not found" msgstr "photils-cli nicht gefunden" -#: ../../../contrib/photils.lua:329 msgid "" "Select an image, click \"Get Tags\" and get \n" "suggestions for tags." From 72bd66d3f567a885e060baf94c893257ef1f1e10 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Sun, 14 Jun 2020 08:57:17 +0200 Subject: [PATCH 6/6] add option to display confidence value, add notice that windows version is not available yet --- contrib/photils.lua | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index 39b71b9..85a2275 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -23,12 +23,13 @@ sent over the internet. ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT - * photils-cli - https://github.com/scheckmedia/photils-cli + * photils-cli - https://github.com/scheckmedia/photils-cli at the moment only + available for Linux and MacOS USAGE * require this script from your main lua file - To do this add this line to the file .config/darktable/luarc: - require "contrib/photils" + To do this add this line to the file .config/darktable/luarc: + require "contrib/photils" * Select an image * Press "get tags" * Select the tags you want from a list of suggestions @@ -85,6 +86,7 @@ local photils_installed = df.check_if_bin_exists("photils-cli") ]] local PHOTILS = { tags = {}, + confidences = {}, page = 1, per_page = 10, selected_tags = {}, @@ -194,9 +196,15 @@ function PHOTILS.paginate() local tag_index = 1 for i = offset, offset + PHOTILS.per_page - 1, 1 do local tag = PHOTILS.tags[i] + local conf = PHOTILS.confidences[i] + GUI.tag_box[tag_index].value = has_key(PHOTILS.selected_tags, tag) if tag then + if dt.preferences.read(MODULE_NAME, "show_confidence", "bool") then + tag = tag .. string.format(" (%.3f)", conf) + end + GUI.tag_box[tag_index].label = tag GUI.tag_box[tag_index].sensitive = true else @@ -269,12 +277,14 @@ function PHOTILS.get_tags(image, with_export) for i = #PHOTILS.tags, 1, -1 do PHOTILS.tags[i] = nil + PHOTILS.confidences[i] = nil end for tag in io.lines(tmp_file) do local splitted = du.split(tag, ":") if 100 * tonumber(splitted[2]) >= GUI.confidence_slider.value then PHOTILS.tags[#PHOTILS.tags + 1] = splitted[1] + PHOTILS.confidences[#PHOTILS.confidences+1] = splitted[2] end end @@ -327,7 +337,13 @@ function PHOTILS.tag_selected(tag_button) if PHOTILS.in_pagination then return end if tag_button.value then - PHOTILS.selected_tags[tag_button.label] = tag_button.label + local tag = tag_button.label + if dt.preferences.read(MODULE_NAME, "show_confidence", "bool") then + local idx = string.find(tag, "%(") - 2 + tag = string.sub(tag, 0, idx) + end + + PHOTILS.selected_tags[tag] = tag else PHOTILS.selected_tags[tag_button.label] = nil end @@ -407,7 +423,15 @@ local plugin_display_views = { [dt.gui.views.darkroom] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 100} } --- dt.control.dispatch(PHOTILS.image_changed) + +-- uses photils: prefix because script settings are all together and not seperated by script +dt.preferences.register(MODULE_NAME, + "show_confidence", + "bool", + _("photils: show confidence value"), + _("if enabled, the confidence value for each tag is displayed"), + true) + dt.register_event("mouse-over-image-changed",PHOTILS.image_changed) dt.register_lib(MODULE_NAME, "photils autotagger",