Skip to content

Commit 0bb8b72

Browse files
authored
Merge pull request darktable-org#241 from piterdias/face_recognition
Solve stability and performance issues on face_recognition.lua
2 parents c7eb101 + 8c75b93 commit 0bb8b72

File tree

1 file changed

+58
-52
lines changed

1 file changed

+58
-52
lines changed

contrib/face_recognition.lua

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ du.check_min_api_version("5.0.0", "face_recognition")
6363
gettext.bindtextdomain("face_recognition", dt.configuration.config_dir.."/lua/locale/")
6464

6565
local function _(msgid)
66-
return gettext.dgettext("face_recognition", msgid)
66+
return gettext.dgettext("face_recognition", msgid)
6767
end
6868

6969
-- preferences
@@ -92,8 +92,10 @@ local function build_image_table(images)
9292
end
9393

9494
for _,img in ipairs(images) do
95-
image_table[img] = tmp_dir .. df.get_basename(img.filename) .. file_extension
96-
cnt = cnt + 1
95+
if img ~= nil then
96+
image_table[tmp_dir .. df.get_basename(img.filename) .. file_extension] = img
97+
cnt = cnt + 1
98+
end
9799
end
98100

99101
return image_table, cnt
@@ -103,17 +105,12 @@ local function stop_job(job)
103105
job.valid = false
104106
end
105107

106-
local function do_export(img_tbl)
108+
local function do_export(img_tbl, images)
107109
local exporter = nil
108110
local upsize = false
109-
local upscale = false
110111
local ff = fc.export_format.value
111112
local height = dt.preferences.read(MODULE, "max_height", "integer")
112113
local width = dt.preferences.read(MODULE, "max_width", "integer")
113-
local images = 0
114-
for k,v in pairs(img_tbl) do
115-
images = images + 1
116-
end
117114

118115
-- get the export format parameters
119116
if string.match(ff, "JPEG") then
@@ -134,7 +131,7 @@ local function do_export(img_tbl)
134131
local exp_cnt = 0
135132
local percent_step = 1.0 / images
136133
job.percent = 0.0
137-
for img,export in pairs(img_tbl) do
134+
for export,img in pairs(img_tbl) do
138135
exp_cnt = exp_cnt + 1
139136
dt.print(string.format(_("Exporting image %i of %i images"), exp_cnt, images))
140137
exporter:write_image(img, export, upsize)
@@ -188,7 +185,7 @@ local function ignoreByTag (image, ignoreTags)
188185
end
189186
end
190187
end
191-
188+
192189
return ignoreImage
193190
end
194191

@@ -221,25 +218,25 @@ local function face_recognition ()
221218
if nrCores < 1 then
222219
nrCores = -1
223220
end
224-
221+
225222
-- Split ignore tags (if any)
226223
ignoreTags = {}
227224
for tag in string.gmatch(ignoreTagString, '([^,]+)') do
228225
table.insert (ignoreTags, tag)
229226
dt.print_log ("Face recognition: Ignore tag: " .. tag)
230227
end
231-
228+
232229
-- list of exported images
233230

234231
local image_table, cnt = build_image_table(dt.gui.action_images)
235232

236233
if cnt > 0 then
237-
local success = do_export(image_table)
234+
local success = do_export(image_table, cnt)
238235
if success then
239236
-- do the face recognition
240237
local img_list = {}
241238

242-
for img,v in pairs(image_table) do
239+
for v,_ in pairs(image_table) do
243240
table.insert (img_list, v)
244241
end
245242

@@ -248,7 +245,7 @@ local function face_recognition ()
248245
dt.print_log ("Face recognition: Path to unknown images: " .. path)
249246
os.setlocale("C")
250247
local tolerance = dt.preferences.read(MODULE, "tolerance", "float")
251-
248+
252249
local command = bin_path .. " --cpus " .. nrCores .. " --tolerance " .. tolerance .. " " .. knownPath .. " " .. path .. " > " .. OUTPUT
253250
os.setlocale()
254251
dt.print_log("Face recognition: Running command: " .. command)
@@ -258,61 +255,77 @@ local function face_recognition ()
258255

259256
-- Open output file
260257
local f = io.open(OUTPUT, "rb")
261-
258+
262259
if not f then
263260
dt.print(_("Face recognition failed"))
264261
else
265262
dt.print(_("Face recognition finished"))
266263
f:close ()
267264
end
268-
265+
269266
-- Read output
270267
dt.print(_("processing results..."))
271268
local result = {}
272-
for line in io.lines(OUTPUT) do
273-
if not string.match(line, "^WARNING:") then
269+
local tags_list = {}
270+
local tag_object = {}
271+
for line in io.lines(OUTPUT) do
272+
if not string.match(line, "^WARNING:") and line ~= "" and line ~= nil then
274273
local file, tag = string.match (line, "(.*),(.*)$")
275274
tag = string.gsub (tag, "%d*$", "")
276275
dt.print_log ("File:"..file .." Tag:".. tag)
277-
if result[file] ~= nil then
278-
table.insert (result[file], tag)
276+
tag_object = {}
277+
if result[file] == nil then
278+
tag_object[tag] = true
279+
result[file] = tag_object
279280
else
280-
result[file] = {tag}
281+
tag_object = result[file]
282+
tag_object[tag] = true
283+
result[file] = tag_object
281284
end
282285
end
283286
end
284-
287+
285288
-- Attach tags
289+
local result_index = 0
286290
for file,tags in pairs(result) do
291+
result_index = result_index +1
287292
-- Find image in table
288-
for img,file2 in pairs(image_table) do
289-
if file == file2 then
290-
for _,t in ipairs (tags) do
291-
-- Check if image is ignored
292-
if ignoreByTag (img, ignoreTags) then
293-
dt.print_log("Face recognition: Ignoring image with ID " .. img.id)
294-
else
295-
-- Check of unrecognized unknown_person
296-
if t == "unknown_person" then
297-
t = unknownTag
298-
end
299-
-- Check of unrecognized no_persons_found
300-
if t == "no_persons_found" then
301-
t = nonpersonsfoundTag
302-
end
303-
if t ~= "" and t ~= nil then
304-
dt.print_log ("ImgId:" .. img.id .. " Tag:".. t)
305-
-- Create tag if it does not exists
306-
local tag = dt.tags.create (t)
307-
img:attach_tag (tag)
293+
img = image_table[file]
294+
if img == nil then
295+
dt.print_log("Face recognition: Ignoring face recognition entry: " .. file)
296+
else
297+
for t,_ in pairs (tags) do
298+
-- Check if image is ignored
299+
if ignoreByTag (img, ignoreTags) then
300+
dt.print_log("Face recognition: Ignoring image with ID " .. img.id)
301+
else
302+
-- Check of unrecognized unknown_person
303+
if t == "unknown_person" then
304+
t = unknownTag
305+
end
306+
-- Check of unrecognized no_persons_found
307+
if t == "no_persons_found" then
308+
t = nonpersonsfoundTag
309+
end
310+
if t ~= "" and t ~= nil then
311+
dt.print_log ("ImgId:" .. img.id .. " Tag:".. t)
312+
-- Create tag if it does not exist
313+
if tags_list[t] == nil then
314+
tag = dt.tags.create (t)
315+
tags_list[t] = tag
316+
else
317+
tag = tags_list[t]
308318
end
319+
img:attach_tag (tag)
309320
end
310321
end
311322
end
312323
end
313324
end
314-
dt.print(_("face recognition complete"))
315325
cleanup(img_list)
326+
dt.print_log("img_list cleaned-up")
327+
dt.print_log("face recognition complete")
328+
dt.print(_("face recognition complete"))
316329
else
317330
dt.print(_("image export failed"))
318331
return
@@ -321,8 +334,6 @@ local function face_recognition ()
321334
dt.print(_("no images selected"))
322335
return
323336
end
324-
325-
326337
end
327338

328339
-- build the interface
@@ -446,11 +457,6 @@ fc.widget = dt.new_widget("box"){
446457
table.unpack(widgets),
447458
}
448459

449-
--fc.tolerance.value = dt.preferences.read(MODULE, "tolerance", "float")
450-
451-
-- Register
452-
--dt.register_storage("module_face_recognition", _("Face recognition"), show_status, face_recognition)
453-
454460
dt.register_lib(
455461
"face_recognition", -- Module name
456462
_("face recognition"), -- Visible name

0 commit comments

Comments
 (0)