Extract an jpg image corresponding to the face detected area from digikam

Started by grimmo, February 23, 2020, 09:14:04 AM

Previous topic - Next topic

grimmo

Hello, I would like to extract all the face images shown by digikam after face tagging of a certain person. The corresponding informations are in xmp files written by digikam. They contain the location of the face area, picture size and person's name; so everything needed should be inside the xmp file.

I tried to get along with "man exiftool", however did not manage to understand if such a thing is possible in exiftool. Would be great if such a routine already exists.

Thanks for any help in advance.

StarGeek

Exiftool can only manipulate metadata. It has no ability to affect the actual image data.

You would have to use the data in the XMP file to calculate the region you want to extract and then use something like Imagemagick to extract the actual regions.  The problem would be that the data is usually not saved as an exact pixel location/size.  It's usually saved as percentages of the total image.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

grimmo

Thanks!
But is there an easy way with exiftool to extract/read the image size and the face region?

Phil Harvey

...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).


Phil Harvey

For the image size:

exiftool -imagesize FILE

But for the face tags, I can't help because I don't know what tags Digikam writes.  See FAQ 2 and FAQ 3 for help with this.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

grimmo

Great, already got some information, guess I have to study the FAQs...

Thanks! I might come back.

StarGeek

After some searching online, it looks like digikam might be saving regions as MWG regions.  I did see some posts where it might not do so by default, so there may be a setting for that.

To get the data, you would use
exiftool -s -XMP-mwg-rs:all File.jpg

The output will be something like this.  This is an example of an image with two faces taged.
RegionAppliedToDimensionsH      : 2028
RegionAppliedToDimensionsUnit   : pixel
RegionAppliedToDimensionsW      : 1383
RegionAreaH                     : 0.124757763, 0.148424506
RegionAreaUnit                  : normalized, normalized
RegionAreaW                     : 0.151842527, 0.181490806
RegionAreaX                     : 0.650041962, 0.327916381
RegionAreaY                     : 0.100343328, 0.113168536
RegionName                      : John Smith, Jane Smith
RegionType                      : Face, Face


All these numbers are given as a percent of the actual image size, so that way they are accurate even if the image has been resized. RegionAreaX and RegionAreaY indicate the center point of the region.  In this case, the center point John Smith is 0.650041962 x 0.100343328 and for Jane Smith is 0.327916381 x 0.113168536.  Note that the numbers are ordered by the the names.  The first number in each of the tags belongs to the first name, the second number to the second name, etc.

Working out the math
John Smith
X position=RegionAreaX*ImageWidth=0.650041962*1383=899 (rounding off)
Y Position=RegionAreaY*ImageHeight=0.100343328*2028=203
So the center point of the John Smith region is about 899x203.

Now it's important to note that this is the point around which the region is centered, not the upper left coordinate of the region.

Continuing with John Smith
Region Width = RegionAreaW*ImageWidth=0.151842527*1383=210
Region Height = RegionAreaH*ImageHeight=0.124757763*2028=253

To get the upper left corner of the region, you subtract half these numbers from the center point.
X Coord = 899-(210/2)=899-105=794
Y Coord = 203-(253/2)=203-127=76

As an example, using ImageMagick to extract the region, the command would be
magick File.Jpg -crop 210x253+794+76 thumb1.jpg

The final item to watch for is the orientation.  All of these applies to an image that has an EXIF:Orientation value of 1-Horizontal.  If the Orientation is different, then the image must be rotated properly before extracting the image.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

StarGeek

Since I had already done this for a previous project and it was just a cut/paste with a couple of edits, here is a config file that will read the MWG regions and output the thumbnail coordinates for use with ImageMagick.  ImageMagick crop uses the format of Width x Height + XCoord + YCoord but without spaces.  The X and Y coordinates are the upper left corner of the crop.

To use it, drop the file into the same directory as exiftool and this would be the command to use
exiftool -config ImageMagickThumbMWG.config -ImageMagickThumbMWG <FileOrDir>

example output for the previous post's image
Image Magick Thumb MWG          : 209x253+794+76, 251x301+328+79

Edit: Removed older version, see updated version.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

grimmo

I am so happy! Thanks a lot, this saved me a lot of time.

Your instructions and math from the previous post work perfect! It gives me exactly what digikam is showing for the face tagged region.

I am trying to figure out what the problem is with the config file; it doesn't produce any output.
It's probably related to the fact that
exiftool -s -XMP-mwg-rs:all File.jpg
doesn't work for me, because the xmp information is given in a separate xmp file:
exiftool -s -XMP-mwg-rs:all File.JPG.xmp
gives me
RegionName                      : name
RegionType                      : Face
RegionAreaX                     : 0.335612
RegionAreaY                     : 0.57581
RegionAreaW                     : 0.413845
RegionAreaH                     : 0.551505
RegionAreaUnit                  : normalized

I did read image dimensions by
exiftool -TAG -ExifImageHeight file.JPG.xmp
and
exiftool -TAG -ExifImageWidth file.JPG.xmp
and now after replacing that in your config file
exiftool -config ImageMagickThumbMWG.config -ImageMagickThumbMWG file.JPG.xmp
gives what you intended (for my image)
Image Magick Thumb MWG          : 1906x1906+593+1036

Great thanks!
I have to think how to proceed. But I would like to come back to you.

StarGeek

Glad you figured out where the data was.  I don't use Digikam, so I didn't know where it would store the data.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

grimmo

Hello StarGeek, I figured out what I exactly want to do:


  • I would like to read all my folders containing face tagged fotos respectively the xmp files,
  • applying your script on each xmp file and extract the region data only for a certain person (RegionName)
  • and use the output to extract the region with ImageMagick and safe it in a subfolder.

Maybe together with the query for a certain RegionName it would be nice to also check for the right EXIF:Orientation and rotate if necessary.



grimmo

I managed to allow that second command would work with the output of the first command:
exiftool -config ImageMagickThumbMWG.config -T -ImageMagickThumbMWG image.jpg.xmp > test.txt
writes just the relevant crop information to the txt file. Alternatively you could use instead of -T also -b or -s -S.
magick P1000407.JPG -crop @test.txt thumb1.jpg
reads from this txt file and crops the face thumb.

Now when I have two faces detected in one image it does not work anymore, e.g.
exiftool -config ImageMagickThumbMWG.config -b -ImageMagickThumbMWG image.jpg.xmp
gives me
204x202+1160+813
182x181+1599+946

or
exiftool -config ImageMagickThumbMWG.config -T -ImageMagickThumbMWG image.jpg.xmp
gives me
204x202+1160+813, 182x181+1599+946

Is there an easy way to apply the script ImageMagickThumbMWG.config just to the spacial information needed, e.g. to Person2 from
exiftool -s -XMP-mwg-rs:all image.jpg.xmp
given
RegionName                      : Person1, Person2
RegionType                      : Face, Face
RegionAreaX                     : 0.441877, 0.591737
RegionAreaY                     : 0.427404, 0.484127
RegionAreaW                     : 0.0714286, 0.0637255
RegionAreaH                     : 0.0947712, 0.0849673
RegionAreaUnit                  : normalized, normalized


Any help?

StarGeek

How about this.  Using your "Magick" command example

C:\>exiftool -config ImageMagickThumbMWG.config -g1 -a -s -IMCommandMWG  Y:\!temp\mmm\ACDsee-Regions_JSilva_092517_8623.jpg -b
magick "Y:/!temp/mmm/ACDsee-Regions_JSilva_092517_8623.jpg" -crop 151x180+352+125 "Y:/!temp/mmm/Natasha Romanoff_Thumb.jpg"
magick "Y:/!temp/mmm/ACDsee-Regions_JSilva_092517_8623.jpg" -crop 148x177+539+164 "Y:/!temp/mmm/Harley Quinn_Thumb.jpg"
magick "Y:/!temp/mmm/ACDsee-Regions_JSilva_092517_8623.jpg" -crop 138x167+453+35 "Y:/!temp/mmm/Arthur Dent_Thumb.jpg"
magick "Y:/!temp/mmm/ACDsee-Regions_JSilva_092517_8623.jpg" -crop 144x173+232+11 "Y:/!temp/mmm/Indiana Jones_Thumb.jpg"
magick "Y:/!temp/mmm/ACDsee-Regions_JSilva_092517_8623.jpg" -crop 158x190+669+90 "Y:/!temp/mmm/John Smith_Thumb.jpg""

C:\Programs\My_Stuff>cd /d Y:\!temp\mmm\

Y:\!temp\mmm>exiftool -config ImageMagickThumbMWG.config -g1 -a -s -IMCommandMWG  ACDsee-Regions_JSilva_092517_8623.jpg -b
magick "./ACDsee-Regions_JSilva_092517_8623.jpg" -crop 151x180+352+125 "./Natasha Romanoff_Thumb.jpg"
magick "./ACDsee-Regions_JSilva_092517_8623.jpg" -crop 148x177+539+164 "./Harley Quinn_Thumb.jpg"
magick "./ACDsee-Regions_JSilva_092517_8623.jpg" -crop 138x167+453+35 "./Arthur Dent_Thumb.jpg"
magick "./ACDsee-Regions_JSilva_092517_8623.jpg" -crop 144x173+232+11 "./Indiana Jones_Thumb.jpg"
magick "./ACDsee-Regions_JSilva_092517_8623.jpg" -crop 158x190+669+90 "./John Smith_Thumb.jpg"


You can then redirect that into a bat file and run it directly.  Requires the -b (binary) option to create the batch file.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

grimmo

Thanks!
But I am sorry, I do not understand what you were trying to do and if that is what I wanted. I cannot get your modified script to output anything and it is really hard for me to read the script's language; I cannot interpret the new part of the script.

I thought I was almost there with what I described yesterday; I can combine the two commands in the terminal, and it works perfectly:

exiftool -config ImageMagickThumbMWG.config -T -ImageMagickThumbMWG 100_2325.jpg.xmp > test/test.txt && magick 100_2325.jpg -crop @test/test.txt test/thumb1.jpg

The above command even works, in case more Persons were detected in a single image. Then the above commands just crops the thumb of the first person. I thought there would be a simple way to just address RegionAreaW and RegionAreaH, RegionAreaX and RegionAreaY for Person2 from e.g.
QuoteRegionName                      : Person1, Person2
RegionType                      : Face, Face
RegionAreaX                     : 0.441877, 0.591737
RegionAreaY                     : 0.427404, 0.484127
RegionAreaW                     : 0.0714286, 0.0637255
RegionAreaH                     : 0.0947712, 0.0849673
RegionAreaUnit                  : normalized, normalized

and feed you first script just with the needed information for Person2 (0.0637255, 0.0849673, 0.591737, 0.484127).

Can't these normalized coordinates be addressed "column-like", if one knows which column is needed? In order just use the normalized spacial information for a certain person (e.g. RegionName=Chris).
If you find the value Chris at second position in RegionName then just feed the script with second position of RegionAreaW and RegionAreaH, RegionAreaX and RegionAreaY? Maybe even predefine this person's name inside the script.