@@ -63,7 +63,7 @@ du.check_min_api_version("5.0.0", "face_recognition")
63
63
gettext .bindtextdomain (" face_recognition" , dt .configuration .config_dir .. " /lua/locale/" )
64
64
65
65
local function _ (msgid )
66
- return gettext .dgettext (" face_recognition" , msgid )
66
+ return gettext .dgettext (" face_recognition" , msgid )
67
67
end
68
68
69
69
-- preferences
@@ -92,8 +92,10 @@ local function build_image_table(images)
92
92
end
93
93
94
94
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
97
99
end
98
100
99
101
return image_table , cnt
@@ -103,17 +105,12 @@ local function stop_job(job)
103
105
job .valid = false
104
106
end
105
107
106
- local function do_export (img_tbl )
108
+ local function do_export (img_tbl , images )
107
109
local exporter = nil
108
110
local upsize = false
109
- local upscale = false
110
111
local ff = fc .export_format .value
111
112
local height = dt .preferences .read (MODULE , " max_height" , " integer" )
112
113
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
117
114
118
115
-- get the export format parameters
119
116
if string.match (ff , " JPEG" ) then
@@ -134,7 +131,7 @@ local function do_export(img_tbl)
134
131
local exp_cnt = 0
135
132
local percent_step = 1.0 / images
136
133
job .percent = 0.0
137
- for img , export in pairs (img_tbl ) do
134
+ for export , img in pairs (img_tbl ) do
138
135
exp_cnt = exp_cnt + 1
139
136
dt .print (string.format (_ (" Exporting image %i of %i images" ), exp_cnt , images ))
140
137
exporter :write_image (img , export , upsize )
@@ -188,7 +185,7 @@ local function ignoreByTag (image, ignoreTags)
188
185
end
189
186
end
190
187
end
191
-
188
+
192
189
return ignoreImage
193
190
end
194
191
@@ -221,25 +218,25 @@ local function face_recognition ()
221
218
if nrCores < 1 then
222
219
nrCores = - 1
223
220
end
224
-
221
+
225
222
-- Split ignore tags (if any)
226
223
ignoreTags = {}
227
224
for tag in string.gmatch (ignoreTagString , ' ([^,]+)' ) do
228
225
table.insert (ignoreTags , tag )
229
226
dt .print_log (" Face recognition: Ignore tag: " .. tag )
230
227
end
231
-
228
+
232
229
-- list of exported images
233
230
234
231
local image_table , cnt = build_image_table (dt .gui .action_images )
235
232
236
233
if cnt > 0 then
237
- local success = do_export (image_table )
234
+ local success = do_export (image_table , cnt )
238
235
if success then
239
236
-- do the face recognition
240
237
local img_list = {}
241
238
242
- for img , v in pairs (image_table ) do
239
+ for v , _ in pairs (image_table ) do
243
240
table.insert (img_list , v )
244
241
end
245
242
@@ -248,7 +245,7 @@ local function face_recognition ()
248
245
dt .print_log (" Face recognition: Path to unknown images: " .. path )
249
246
os.setlocale (" C" )
250
247
local tolerance = dt .preferences .read (MODULE , " tolerance" , " float" )
251
-
248
+
252
249
local command = bin_path .. " --cpus " .. nrCores .. " --tolerance " .. tolerance .. " " .. knownPath .. " " .. path .. " > " .. OUTPUT
253
250
os.setlocale ()
254
251
dt .print_log (" Face recognition: Running command: " .. command )
@@ -258,61 +255,77 @@ local function face_recognition ()
258
255
259
256
-- Open output file
260
257
local f = io.open (OUTPUT , " rb" )
261
-
258
+
262
259
if not f then
263
260
dt .print (_ (" Face recognition failed" ))
264
261
else
265
262
dt .print (_ (" Face recognition finished" ))
266
263
f :close ()
267
264
end
268
-
265
+
269
266
-- Read output
270
267
dt .print (_ (" processing results..." ))
271
268
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
274
273
local file , tag = string.match (line , " (.*),(.*)$" )
275
274
tag = string.gsub (tag , " %d*$" , " " )
276
275
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
279
280
else
280
- result [file ] = {tag }
281
+ tag_object = result [file ]
282
+ tag_object [tag ] = true
283
+ result [file ] = tag_object
281
284
end
282
285
end
283
286
end
284
-
287
+
285
288
-- Attach tags
289
+ local result_index = 0
286
290
for file ,tags in pairs (result ) do
291
+ result_index = result_index + 1
287
292
-- 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 ]
308
318
end
319
+ img :attach_tag (tag )
309
320
end
310
321
end
311
322
end
312
323
end
313
324
end
314
- dt .print (_ (" face recognition complete" ))
315
325
cleanup (img_list )
326
+ dt .print_log (" img_list cleaned-up" )
327
+ dt .print_log (" face recognition complete" )
328
+ dt .print (_ (" face recognition complete" ))
316
329
else
317
330
dt .print (_ (" image export failed" ))
318
331
return
@@ -321,8 +334,6 @@ local function face_recognition ()
321
334
dt .print (_ (" no images selected" ))
322
335
return
323
336
end
324
-
325
-
326
337
end
327
338
328
339
-- build the interface
@@ -376,7 +387,7 @@ fc.known_image_path = dt.new_widget("file_chooser_button"){
376
387
is_directory = true ,
377
388
changed_callback = function (this )
378
389
dt .preferences .write (MODULE , " known_image_path" , " directory" , this .value )
379
- end
390
+ end
380
391
}
381
392
382
393
fc .export_format = dt .new_widget (" combobox" ){
@@ -403,9 +414,9 @@ fc.height = dt.new_widget("entry"){
403
414
404
415
fc .execute = dt .new_widget (" button" ){
405
416
label = " detect faces" ,
406
- clicked_callback = function (this )
417
+ clicked_callback = function (this )
407
418
face_recognition ()
408
- end
419
+ end
409
420
}
410
421
411
422
local widgets = {
@@ -422,14 +433,14 @@ local widgets = {
422
433
if dt .configuration .running_os == " windows" or dt .configuration .running_os == " macos" then
423
434
table.insert (widgets , df .executable_path_widget ({" face_recognition" }))
424
435
end
425
- table.insert (widgets , dt .new_widget (" section_label" ){ label = _ (" processing options" )})
426
- table.insert (widgets , fc .tolerance )
427
- table.insert (widgets , fc .num_cores )
428
- table.insert (widgets , fc .export_format )
429
- table.insert (widgets , dt .new_widget (" box" ){
430
- orientation = " horizontal" ,
431
- dt .new_widget (" label" ){ label = _ (" width " )},
432
- fc .width ,
436
+ table.insert (widgets , dt .new_widget (" section_label" ){ label = _ (" processing options" )})
437
+ table.insert (widgets , fc .tolerance )
438
+ table.insert (widgets , fc .num_cores )
439
+ table.insert (widgets , fc .export_format )
440
+ table.insert (widgets , dt .new_widget (" box" ){
441
+ orientation = " horizontal" ,
442
+ dt .new_widget (" label" ){ label = _ (" width " )},
443
+ fc .width ,
433
444
})
434
445
table.insert (widgets , dt .new_widget (" box" ){
435
446
orientation = " horizontal" ,
@@ -439,18 +450,13 @@ table.insert(widgets, dt.new_widget("box"){
439
450
table.insert (widgets , fc .execute )
440
451
441
452
fc .widget = dt .new_widget (" box" ){
442
- orientation = vertical ,
443
- reset_callback = function (this )
453
+ orientation = vertical ,
454
+ reset_callback = function (this )
444
455
reset_preferences ()
445
- end ,
446
- table.unpack (widgets ),
456
+ end ,
457
+ table.unpack (widgets ),
447
458
}
448
459
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
-
454
460
dt .register_lib (
455
461
" face_recognition" , -- Module name
456
462
_ (" face recognition" ), -- Visible name
0 commit comments