📜 ⬆️ ⬇️

Again the XMP tags are individuals. Everything is bad, but it is fixable

On Habré, the question of storing meta tags of recognized faces for a photo archive has already been raised several times; unfortunately, none of the above recipes turned out to be sufficiently working, and googling did not help, so I had to write my bicycle.

Original articles: one and two .

Everything is written there well and correctly, but there is still no happiness.
')
Picture to attract attention:


The task is simple - to mark people in the photo and be able to use it in the maximum number of places in any way convenient for me.

I will mark people in picas, because they are linked to Google contacts, cross-platform, auto-detecting, storing tags inside a file (with nuances). But I want to watch and use these tags everywhere in gallery3 because she knows how, in the lightroom because I use it as a cataloguer, in microsoft explorer because I have it in Microsoft Live Photo Gallery, just because it is the second popular format and why not use it too.

Who wants to be confused too - welcome under kat.

Problem number 1 where picas stores face information?
Three options:


For obvious reasons, the second option is the most optimal, but as it turned out, not everything is so simple, picas can’t just be said: “Write all the tags in the files” Google guzzled to put such a button. There are several options to solve this problem, both purely picas and using external utilities.

picface
almost works, has recently been updated, but I have repeatedly crashed before completing what I have started, and since I have about 60K photos in the archive, it all takes a long time and is dreary.

most popular avpicfacexmptagger
He knows how to do almost everything that is necessary, but rather one-sided, has not been updated for a long time, came up with his own scheme for xmp, you can think of the existing ones. But in principle, to bring the archive to state two can be used.

I used the recommendation from Google itself, you only need picas version 3.9 with the “Store name tags in photo” checkbox turned on. To ensure that all persons are recorded in xmp, you must go through all the people and rename to something, and then rename it back. Quick, easy, work. On the people tab, double-click on the first name and rename it to 'x', then double-click on 'x' and rename it back. All I have ottegirovano hundred and fifty people and it took just a couple of minutes. After that, Picas is better not to close right away, but to give her some time to write data to disk, because she does not show any progress.

The next step is to extract the names recorded by picas in xmp-mwg-rs in the RegionName tag and write it in the PersonInImage and RegionPersonDisplayName tags after that we can use these tags when searching in all catalogers and even microsoft explorer will show us the names of people in the photo . The easiest way to do this is with exiftool, which can be downloaded here.

exiftool -RegionName>PersonInImage photo.jpg exiftool -RegionName>RegionPersonDisplayName photo.jpg 


after that we see information about people in a variety of third-party programs


It is also possible to convert information about the position of persons on the frame from standard picas to standard from microsoftware, they differ not only in names, but even in the way squares are considered, some set the length and height from the upper left corner of the square, and others from the center. For conversion, we need a config for exiftool.

ExifTool_config_convert_regions
 %Image::ExifTool::UserDefined = ( 'Image::ExifTool::Composite' => { MyRegion => { Require => { 0 => 'RegionInfoMP', 1 => 'ImageWidth', 2 => 'ImageHeight', }, ValueConv => q{ my ($rgn, @newRgns); foreach $rgn (@{$val[0]{Regions}}) { my @rect = split /\s*,\s*/, $$rgn{Rectangle}; my %newRgn = ( Area => { X => $rect[0] + $rect[2]/2, Y => $rect[1] + $rect[3]/2, W => $rect[2], H => $rect[3], Unit => 'normalized', }, Name => $$rgn{PersonDisplayName}, Type => 'Face', ); push @newRgns, \%newRgn; } return { AppliedToDimensions => { W => $val[1], H => $val[2], Unit => 'pixel' }, RegionList => \@newRgns, }; }, }, MyRegionMP => { Require => 'RegionInfo', ValueConv => q{ my ($rgn, @newRgns); foreach $rgn (@{$val[0]{RegionList}}) { my @rect = @{$$rgn{Area}}{'X','Y','W','H'}; $rect[0] -= $rect[2]/2; $rect[1] -= $rect[3]/2; push @newRgns, { PersonDisplayName => $$rgn{Name}, Rectangle => join(', ', @rect), }; } return { Regions => \@newRgns }; }, }, }, ); 1; #end 


The config is found on the Internet and it allows you to convert the regions in both directions, but we need only one. To do this, run exiftool with the following parameters:

 exiftool -config ExifTool_config_convert_regions "-regioninfomp\<MyRegionMP"' photo.jpg 


After that, the face is correctly displayed in Microsoft Live Photo Gallery and other software that adheres to the same scheme.


It is almost a profit, but I would also automate this business for all the necessary photos, and also write the names into the keywords: the tags Subject and HierarchialSuject yes, here, too, was not without double formats. For these purposes, I wrote a plugin for lightroom, it gives you the opportunity to run it only on the right photos, and add keywords without fear of duplicating them or erasing existing ones, well, just because I use the lightroom as the cataloger of the entire archive.

For the code, please do not beat, but rather tell me how to improve it, this is my first plugin for LR and generally the first time I saw lua.

There are only two files in the plugin.

Info.lua

 return { LrSdkVersion = 3.0, LrSdkMinimumVersion = 1.3, -- minimum SDK version required by this plug-in LrToolkitIdentifier = 'com.adobe.lightroom.sdk.helloworld', LrPluginName = LOC "$$$/PicasaFaceToTag/PluginName=Picasa Faces to Tags", -- Add the menu item to the Library menu. LrLibraryMenuItems = { { title = "Write Picasa Faces to Tags", file = "PersonInImage.lua"}, }, VERSION = { major=4, minor=1, revision=0, build=831116, }, } 


PersonInImage.lua

 --[[---------------------------------------------------------------------------- ------------------------------------------------------------------------------]] -- Access the Lightroom SDK namespaces. local LrTasks = import 'LrTasks' local LrProgressScope = import 'LrProgressScope' local LrApplication = import 'LrApplication' local catalog = LrApplication.activeCatalog() local photos = catalog:getTargetPhotos() local LrPathUtils = import 'LrPathUtils' local logger = import 'LrLogger'("lr") logger:enable('print') local function faceToTag() --[[Convert faces from picasa xmp tag to microsoft xmp ]] exeFile = LrPathUtils.child( _PLUGIN.path, "exiftool.exe" ) cfgFile = LrPathUtils.child( _PLUGIN.path, "ExifTool_config_convert_regions" ) redirect = LrPathUtils.getStandardFilePath('temp') .. "exiftool.stdout" local total = ( # catalog:getTargetPhotos() ) local exifArgs = {"-b -RegionName \>" .. redirect, --'-overwrite_original "-RegionName\>PersonInImage"', '-overwrite_original "-RegionName\>RegionPersonDisplayName"', '-config '..cfgFile..' -overwrite_original "-regioninfomp\<MyRegionMP"'} local progressScope = LrProgressScope{ title = "Write Picasa Faces to Tags", caption = "Updateting " .. total .. " photos." , } progressScope:setCancelable( true ) local parrent catalog:withWriteAccessDo("Create parrent keyword", function () parrent = catalog:createKeyword("names", {}, false, nil, true) --logger:debug("parrent keyword created: " .. tostring(parrent)) end) for completed, photo in ipairs(photos) do progressScope:setPortionComplete(completed, total) progressScope:setCaption("Updated " .. tostring(completed) .. " of " .. tostring(total) .. " photos") if progressScope:isCanceled() then progressScope:done() break end local path = photo:getRawMetadata('path') logger:debug(path) -- write filename to debug log for i,exifArg in ipairs(exifArgs) do local exeCmd ='"' .. exeFile.." "..exifArg.." "..path .. '"' local status = LrTasks.execute(exeCmd) if io.open(redirect):read() == nil then break end --check is there any names in the file --logger:debug(exeCmd) if status ~= 0 then logger:debug("Error "..exeCmd) progressScope:done() end end for name in io.lines(redirect) do if name ~= nil then -- check is there any pleople on photo logger:debug(name) catalog:withWriteAccessDo("Adding name keywords", function () local keyword = catalog:createKeyword(name, {}, true, parrent, true) logger:debug("keyword created: " .. tostring(keyword)) photo:addKeyword(keyword) --photo:setRawMetadata('personShown', keyword) --doesn't work logger:debug("keyword added: " .. name) end) end end end progressScope:done() end LrTasks.startAsyncTask(faceToTag) 


All nominal tags are stored in a hierarchical structure inside the tag "names", programs that do not work with the xmp lightroom scheme will see them just a flat list + tags "names". For the plugin to work in the folder must put exiftool.exe and its config. All in a crowd can be downloaded from github

The plugin works, but it has flaws:


Shl. I was able to find two plugins that do _ almost the same thing, they take people from picas and write them in tags, but they all take people only from picasa.ini and do not work with people recorded in XMP.

Source: https://habr.com/ru/post/193946/


All Articles