'Looking for a way to trap 'OSError - Errno 9' in Python or BASH And Continue

I'm training face models for a Deep Fake project using .png images extracted from .mp4 video clips, which get saved to a "Face A" folder and a "Face B" folder with the facial metadata saved as a header in each .png file. The face-swap trainer then reads the images in the extraction directories, learning each face, comparing the features, and learning how to re-map.

However, my project partner resized some of the images because she ran the extraction routine at a different output size for some of the video clips we added after-the-fact (the trainer won't run if all face images aren't the same size) so she ran ImageMagick to fix the images, which worked, but it stripped out the facial metadata header on the files it resized.

Because FaceSwap isn't expecting the training images to be modified, it has no built-in way to skip "bad" files - images whose facial-data headers are corrupt or missing, and I have no way to know which files have been stripped of their headers just from looking at them because the image data - the detected face - doesn't change.

To make a long story short, I learned all this the hard way the first time we tried to run the trainer, so now, I have to re-run the model trainer, wait to see if it will fail, remove the offending image myself if it does, then re-run the trainer, and see if it fails again. Wash, rinse, repeat.

The output always looks like this the name of the .png file changes, of course):

05/12/2022 01:15:36 VERBOSE  Loading config: '/home/deepfaker/faceswap/config/train.ini'
05/12/2022 01:18:09 CRITICAL Error caught! Exiting...                                                                                                                                                                                         
05/12/2022 01:18:09 ERROR    Caught exception in thread: '_training_0'
05/12/2022 01:18:09 ERROR    Invalid face image found. Aborting: '/home/deepfaker/Deep_Fakes/In/project_1/workspace/face_a_3_001646_0.png'
Exception ignored in: <function Pool.__del__ at 0x7f6f04c738b0>
Traceback (most recent call last):
  File "/home/deepfaker/miniconda3/envs/faceswap/lib/python3.8/multiprocessing/pool.py", line 268, in __del__
    self._change_notifier.put(None)
  File "/home/deepfaker/miniconda3/envs/faceswap/lib/python3.8/multiprocessing/queues.py", line 368, in put
    self._writer.send_bytes(obj)
  File "/home/deepfaker/miniconda3/envs/faceswap/lib/python3.8/multiprocessing/connection.py", line 200, in send_bytes
    self._send_bytes(m[offset:offset + size])  File "/home/deepfaker/miniconda3/envs/faceswap/lib/python3.8/multiprocessing/connection.py", line 411, in _send_bytes
    self._send(header + buf)
  File "/home/deepfaker/miniconda3/envs/faceswap/lib/python3.8/multiprocessing/connection.py", line 368, in _send
    n = write(self._handle, buf)
OSError: [Errno 9] Bad file descriptor

I asked on the FaceSwap discord if there was a way to do this from within the trainer itself, and they said it could technically be done but it would add too much overhead and significantly slow the training process down, especially on larger projects, and recommended re-running the extraction process as the image files are automatically overwritten - but it took nearly 4 days to run the extraction and facial analysis on the 9 source videos, and I don't want to have do that all over again. So now I've come here to see if there's a way to catch the problem in BASH or with another Python script and create a run-if-fail-loop which removes the offending image file, then restarts the trainer?

As I said, the error text is always the same, except for the timestamp and the name of the file:

{DATE} {TIME} ERROR Invalid face image found. Aborting: '{PNG_FILE}'

I would love to be able to filter out everything except that file, capture it in a string, pass that string to either mv or rm and keep going, but I don't know how.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source