1

I have a problem, below is my root tree: In my root I have that:

 ---dir1---sub1(images exif time 10:05:05 to 10:09:55)
        ---sub2(images exif time 10:11:15 to 10:15:42)
        ---sub3(images exif time 10:22:15 to 10:24:41)
        ---sub4(images exif time 10:28:15 to 10:35:40)


 ---dir2---sub1(images exif time 10:05:06 to 10:09:57)
        ---sub2(images exif time 10:11:15 to 10:15:40)
        ---sub3(images exif time 10:22:15 to 10:24:43)
        ---sub4(images exif time 10:28:15 to 10:35:40)
        ---sub5(images exif time 10:40:15 to 10:43:40)

 ---dir3---sub1(images exif time 10:05:05 to 10:09:54)
        ---sub2(images exif time 10:11:15 to 10:15:40)
        ---sub3(images exif time 10:22:15 to 10:24:41)
        ---sub4(images exif time 10:28:15 to 10:35:40)
        ---sub5(images exif time 10:40:15 to 10:43:42)

 ---dir4---sub1(images exif time 10:05:06 to 10:09:57)
        ---sub2(images exif time 10:11:15 to 10:15:40)
        ---sub3(images exif time 10:22:15 to 10:24:43)
        ---sub4(images exif time 10:28:15 to 10:35:40)
        ---sub5(images exif time 10:40:15 to 10:43:40)

 ---dir5---sub1(images exif time 10:05:05 to 10:09:54)
        ---sub2(images exif time 10:11:15 to 10:15:40)
        ---sub3(images exif time 10:22:15 to 10:24:41)
        ---sub4(images exif time 10:28:15 to 10:35:40)
        ---sub5(images exif time 10:40:15 to 10:43:42)

I have 5 dirs in my root and each contains sub-folders(with images) number of sub-folders it's not a same all the time, What I want to do is from first - dir1 get sub1 and put it to new destination folder after go to next dir (dir2) scan sub-folders to check exif(time) if its a same as sub1 from dir1 and copy it to same directory after go to next dir3 and do same for all others dir-s and subfolders, and after create newdir2 go and take sub2 from dir1 and do again same loop till end...

something like:

   ---newdir1---sub1(from dir1)
             ---sub1(from dir2)
             ---sub1(from dir3)
             ---sub1(from dir4)
             ---sub1(from dir5)

   ---newdir2---sub2(from dir1)
             ---sub2(from dir2)
             ---sub2(from dir3)
             ---sub2(from dir4)
             ---sub2(from dir5)

   ---newdir3---sub3(from dir1)
             ---sub3(from dir2)
             ---sub3(from dir3)
             ---sub3(from dir4)
             ---sub3(from dir5)

   ---newdir4---sub4(from dir1)
             ---sub4(from dir2)
             ---sub4(from dir3)
             ---sub4(from dir4)
             ---sub4(from dir5)

   ---newdir5---sub5(from dir2)
             ---sub5(from dir3)
             ---sub5(from dir4)
             ---sub5(from dir5)

I have a part of script with sort my images to dictionary by some time interval, how I can join it to my script?? to get my sub-s with same key to same dir ??:

import os
import exifread
from datetime import datetime, timedelta

TIME_RANGE = 2

src_root = 'F:\gopro_egouts\gopro_img_test\\2018-03-06'

dst_root = src_root + '-copie'

src_dirs_dict = {}

for cam_dir in os.listdir(src_root):
    laps_root = os.path.join(src_root, cam_dir)
    for lap_dir in os.listdir(laps_root):
        files_root = os.path.join(laps_root, lap_dir)
        min_time = None
        max_time = None
        for cam_file in os.listdir(files_root):
            with open(os.path.join(files_root, cam_file), 'rb') as f:
                tags = exifread.process_file(f, details=False, stop_tag="EXIF DateTimeOriginal")
                time_taken = tags.get("EXIF DateTimeOriginal")
                if time_taken:
                    file_time = datetime.strptime(str(time_taken), '%Y:%m:%d %H:%M:%S')
                    if min_time is not None:
                        if file_time < min_time:
                            min_time = file_time
                    else:
                        min_time = file_time

                    if max_time is not None:
                        if file_time > max_time:
                            max_time = file_time
                    else:
                        max_time = file_time


        is_key = None
        for key in src_dirs_dict.keys():
            if (min_time >= key[0] and min_time < key[1]) \
                    or (max_time >= key[0] and max_time < key[1]):
                is_key = key
                break
        min_time = min_time.replace(second=0)
        max_time = min_time + timedelta(minutes=TIME_RANGE)

        if is_key:

            key_min, key_max = is_key
            if min_time < key_min:
                key_min = min_time
            if max_time > key_max:
                key_max = max_time

            new_key = (key_min, key_max)

            if new_key == is_key:
                src_dirs_dict[new_key].append(files_root)
            else:

                src_dirs_dict[new_key] = src_dirs_dict.pop(is_key) + [files_root]
        else:
            new_key = (min_time, max_time)
            src_dirs_dict[new_key] = [files_root]


print(src_dirs_dict)

My print showing me that:

{(datetime.datetime(2018, 3, 6, 10, 31), datetime.datetime(2018, 3, 6, 10, 32)): ['F:\\gopro_egouts\\gopro_img_test\\2018-03-06\\CAM0101 1\\Time Lapse 3',...

I have a working script with working well but taking a sub-folders one by one , and when some Time-lapse is missing, there I have a problem, his mixing my sub-s(automatically taking next one from next dir with wrong time), where I have to add my exif script from above to here(how modify it)... how to join it together???
Any help will be appreciated.

from collections import defaultdict
import shutil
import os
import re
src_root = r'F:\gp\gp_test\\2018-03-06'

dst_root = src_root + '-copie'

#os.makedirs(dst_root, exist_ok=True)

src_dirname, src_folders, _ = next(os.walk(src_root))
src_folders = sorted(src_folders)

src_folders = [os.path.join(src_root, folder) for folder in src_folders]
print(src_folders)
job = defaultdict(list)

print('mes {} dossier cam'.format(len(src_folders)))

for folder in src_folders:
    print()
    dirname, src_sub_folders, _ = next(os.walk(os.path.join(src_dirname, folder)))
    src_sub_folders = sorted(src_sub_folders, key=lambda x: [re.search(r'(\D+)', x).group(1)] + list(map(int, re.findall(r'\d+', x))))
    print("mes 5 CAM avec {} time laps '{}'".format(len(src_sub_folders), folder))

    for index, sub_folder in enumerate(src_sub_folders, start=1):
        job['Time Lapse-{}'.format(index)].append(os.path.join(dirname, sub_folder))

#print()

for dst_folder, src_folders in sorted(job.items()):
    for index, src_folder in enumerate(src_folders, start=1):
        dst_new_folder = os.path.join(dst_root, dst_folder, 'CAM-{}'.format(index))
        print('{} -> {}'.format(src_folder, dst_new_folder))
        shutil.copytree(src_folder, dst_new_folder)
#shutil.rmtree(src_root)

for root, dirs, files in os.walk(dst_root):
    for f in files:
        prefix = os.path.basename(root)
        prefix1 = os.path.basename(src_root)
        os.rename(os.path.join(root, f), os.path.join(root, "{}-{}-{}".format(prefix1, prefix, f)))
        print("images rennomer ")

print("fini")
print("dossier supprimé")

I'm really sorry if that will be not to clear for users, but English it's not my strongest language ...

  • Your question doesn't actually say what you are trying to do. I guess you are recording several sequences at different times and you have 5 cameras shooting the same scene? Then you want to put all the videos from 5 different cameras together in a subdirectory under each sequence? Or you want to put all sequences from camera 1 in one directory and all sequences from camera 2 in another? Please try and explain more clearly. – Mark Setchell Mar 26 '18 at 13:55
  • I've edited my post hope so will be more clear, I want do exactly same as my first scrip do but using exif to copy them to new sub-s, I want to conserve them divided as they are - each Time-laps in new sub as I demonstarted above –  Mar 26 '18 at 14:17
  • You present a diagram, a script, another diagram and then what has gone wrong, but you still don't say clearly what you are actually trying to do. You mention EXIF in your question title, but your code and description don't talk about EXIF data at all. Sorry, I still don't understand the question. – Mark Setchell Mar 26 '18 at 15:17
  • I've edited my post, hope so now will be better @Mark Setchell –  Mar 27 '18 at 12:03
  • @MarkSetchell hope so that's will help and be more clearly –  Mar 31 '18 at 23:15
  • anyone have some ideas ?? please I'm still stuck with this –  Apr 10 '18 at 08:23
  • I suspect most people can't understand it and therefore don't bother trying to answer. I still don't understand. Maybe if you put a clear statement at the start which describes what you are trying to do, it would help. You have 4 cameras? Or five? You are recording something with all 4 cameras at the same time? Or one camera after another? You want to get all pictures from the same time together in one directory? Or all pictures from the same camera? How long do you shoot pictures for in each sequence? Is there a minimum time between sequences? – Mark Setchell Apr 10 '18 at 08:36
  • Are the cameras all initially set to exactly the same time? What is the problem exactly? If you edit and improve your question, it will show up again in people's browsers and your chances of getting an answer will improve. – Mark Setchell Apr 10 '18 at 08:37
  • I have a 5 cameras , but sometimes one of them doesn't work(by error), its a gopro cameras, when they work , they take a images at same time(time lapse) mostly(sometime i have 3 seconds differences for each camera and time lapse never more than 3 secounds), shooting sequence its not a same that could be 5 minutes , 10 minutes, 3 minutes , dir1 its a camera1 and all time lapse in(sub1, sub2 etc...), dir2=camera2 and her time-lapse etc etc... –  Apr 10 '18 at 09:41
  • People normally get better replies when they click `edit` under the original question and **update** the question with all the relevant information rather than obliging people to read through lots of pages of comments. The question also comes back to the top of the pile when you change it. So there are 2 advantages to updating the question. – Mark Setchell Apr 10 '18 at 09:51
  • How can you have 2 `dir2` and 2 `dir3` in first picture? – Mark Setchell Apr 10 '18 at 09:53
  • it was my error there are in order –  Apr 10 '18 at 09:59

1 Answers1

0

In a nutshell, you have images of the same set of events shot on a number of cameras.

Currently, they are grouped first by camera, then by event:

├── Camera1
│   ├── Event1
│   ├── Event2
│   ├── Event3
│   ├── Event4
│   └── Event5
├── Camera2
│   ├── Event1
│   ├── Event2
│   ├── Event3
│   ├── Event4
│   └── Event5
├── Camera3
│   ├── Event1
│   ├── Event2
│   ├── Event3
│   ├── Event4
│   └── Event5
├── Camera4
│   ├── Event1
│   ├── Event2
│   ├── Event3
│   ├── Event4
│   └── Event5
└── Camera5
    ├── Event1
    ├── Event2
    ├── Event3
    ├── Event4
    └── Event5

... where some events may be missing and the event numbering may not match because one or more events may not be recorded by all cameras.

And you want the same set of images grouped first by event, then by camera:

├── Event1
│   ├── Camera1
│   ├── Camera2
│   ├── Camera3
│   ├── Camera4
│   └── Camera5
├── Event2
│   ├── Camera1
│   ├── Camera2
│   ├── Camera3
│   ├── Camera4
│   └── Camera5
├── Event3
│   ├── Camera1
│   ├── Camera2
│   ├── Camera3
│   ├── Camera4
│   └── Camera5
├── Event4
│   ├── Camera1
│   ├── Camera2
│   ├── Camera3
│   ├── Camera4
│   └── Camera5
└── Event5
    ├── Camera1
    ├── Camera2
    ├── Camera3
    ├── Camera4
    └── Camera5

Here's an idea... I am kind of "thinking aloud" in pseudo-code:

Create the output directories {Event1..EventN}/Camera{1..N}
MissingDirectory=false
for each input directory Camera{1..N}
    if this directory has the full number of subdirectories
        copy all subdirectories to output area
    else
        MissingDirectory=true
    end if
end for

if MissingDirectory
    for each output Event directory
        get times of all files from all cameras for current event
        sort list and take median time of current event
    end for
    for each un-copied input directory
        get the mean time of all the files in it
        assign this directory's files to output directory with nearest median time
    end for
endif

You can convert your EXIF times to pure seconds since midnight (s) with:

s = (hours*3600) + (minutes*60) + seconds

Here's a way to get the time (in seconds since midnight) that an image was taken:

import exifread

def getImageTime(filename):
    "Read EXIF data of given file and return time in seconds since midnight"
    f=open(filename,'rb')
    tags=exifread.process_file(f)
    DateTime=tags["EXIF DateTimeOriginal"].printable
    # DateTime looks like: "2013:03:09 08:59:50"
    Time=DateTime.split()[-1]
    # Time looks like: "08:59:50"
    h,m,s=Time.split(":")
    # Return seconds since midnight: 32390
    return (int(h)*3600) + (int(m)*60) + int(s)

s=getImageTime("image.jpg")
print(s)

After some more thought, this won't work very well if one of the cameras is set, say, 20 minutes different from the others, since all its images from all the sequences will tend to get put into the first or last directory. Needs some more thought...

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • means I have to use time module ?? I'm a beginner in python can You guide me more @Mark Setchell wher I have to add it exactly to my script? –  Apr 10 '18 at 10:34
  • No need for time module, you are just splitting a field. `s="12:18:43"` then `hours, minutes,seconds=s.split(':')` – Mark Setchell Apr 10 '18 at 10:46
  • When i print my exif timeTaken plus filename its show all images like this - 2018:03:06 11:29:26 G0091059.JPG –  Apr 10 '18 at 11:45
  • when I've added that to my script - `timeTaken.split(":") print(timeTaken)` –  Apr 10 '18 at 11:48
  • I have a error message `timeTaken.split(":") AttributeError: 'IfdTag' object has no attribute 'split'` –  Apr 10 '18 at 11:48
  • It's the same as above except you split on the space character. `s="2018:03:06 11:29:26 G0091059.JPG"` then `date, time,filename=s.split(" ")` – Mark Setchell Apr 10 '18 at 11:49
  • I've edited my post, can You check it please did thats should be something like this?? –  Apr 10 '18 at 12:43
  • still I have a error `timeTaken.split(" ") AttributeError: 'IfdTag' object has no attribute 'split'` –  Apr 10 '18 at 12:46
  • Have no ideas how to add it , its a little bit complicated for me –  Apr 10 '18 at 13:26