<jupyter_start><jupyter_text>OCR Google Photos PrepSimple Jupyter script to run OCR on images in `src/` and then save results to IPTC so they will be set as the description in Google Photos when the image is uploaded.Images will be converted to `.jpg` (metadata support) and saved to `output/` folder.  Import<jupyter_code>import pytesseract
import os
import glob
import re

from iptcinfo3 import IPTCInfo
from PIL import Image

import time
import datetime

from tqdm import tqdm<jupyter_output><empty_output><jupyter_text>SetupSet correct tesseract executable[Tesseract guide](https://tesseract-ocr.github.io/tessdoc/Home.html)<jupyter_code>pytesseract.pytesseract.tesseract_cmd = r'/usr/local/Cellar/tesseract/4.1.1/bin/tesseract'<jupyter_output><empty_output><jupyter_text>Optional prefix (when renaming MacOS screenshots)<jupyter_code>output_prefix = 'processed'
"""
    filename helper
    formats standard MacOS screenshot format to "url friendly" plus prefix
    otherwise keeps same filename
"""
def prep_filename(filename, prefix='', separator='-'):
    # check if matches MacOS screenshot format
    regex = re.search("Screen Shot ([0-9]{4}-[0-9]{2}-[0-9]{2}) at ([0-9]{1,2}\.[0-9]{2}\.[0-9]{2})(?:\s)?(AM|PM)?", filename)
    if regex is not None: 
        datetime_string = regex.group(1) +" "+ regex.group(2)
        # default 24-hour format
        datetime_format = "%Y-%m-%d %H.%M.%S"
        # check if 12-hour format
        if regex.group(3) is not None:
            datetime_string = datetime_string +" "+ regex.group(3)
            datetime_format  = "%Y-%m-%d %I.%M.%S %p"
        datetime_obj = datetime.datetime.strptime(datetime_string, datetime_format)
        return prefix+separator+datetime_obj.strftime("%Y-%m-%d-%H-%M-%S")
    else:
        # keep filename
        r = re.search("^(src/)(.*)(\.(png|jpg|jpeg|gif))$", filename)
        return r.group(2)<jupyter_output><empty_output><jupyter_text>Sample![title](sample.png)<jupyter_code>sample_string = pytesseract.image_to_string(r'sample.png')
print(sample_string)<jupyter_output><empty_output><jupyter_text>Gather Files<jupyter_code># find images in ./src/
screenshots = glob.glob("src/*.png") + glob.glob("src/*.gif") + glob.glob("src/*.jpg") + glob.glob("src/*.jpeg")
print("Files found: "+str(len(screenshots)))
import random
from IPython.display import display
test_image = Image.open( random.choice(screenshots) )
display(test_image)<jupyter_output><empty_output><jupyter_text>Run Operations<jupyter_code># list to store output filenames
output_screenshots = []
# list to store OCR results
captions = []<jupyter_output><empty_output><jupyter_text>Convert to JPEG and run OCRImages must be converted to JPG to support EXIF/IPTC metadata. Run Tesseract to read text in images.<jupyter_code># loop through screenshots in src/ to pass through OCR and convert to JPG
for i in tqdm(range(len(screenshots))):
    # load image
    with Image.open(screenshots[i]) as sshot:
        # convert to rgb (saving to jpg later)
        sshot = sshot.convert('RGB')
        # tesseract (OCR)
        caption = pytesseract.image_to_string(sshot)
        # store result in list
        captions.append(caption)
        # prepare filename
        filebase = prep_filename(screenshots[i], prefix=output_prefix)
        filename = "output/"+filebase+".jpg"
        output_screenshots.append(filename)
        # save jpg
        sshot.save(filename)
        sshot.close()<jupyter_output><empty_output><jupyter_text>Insert CaptionOpen the saved jpg using IPTCInfo to write caption in.<jupyter_code>for j in tqdm(range(len(output_screenshots))):
    try:
        """
            wrapping in a try for now
            > "WARNING:iptcinfo:Marker scan hit start of image data"
            IPTC metadata is still updated
        """
        info = IPTCInfo(output_screenshots[j], force=True)
        info['caption/abstract'] = str.encode(captions[j])
        info.save()
    except:
        pass<jupyter_output><empty_output><jupyter_text>Cleanup ~ Files(to investigate) IPTCInfo lib may create duplicate files with `~` prefixed. This portion removes those files (if found)<jupyter_code># remove ~ files
for k in tqdm(range(len(output_screenshots))):
    filename = output_screenshots[k]+"~"
    # check if file exists and as simple safeguard lookout for jpg string
    if(os.path.exists(filename) and "jpg" in filename):
        os.remove(filename)<jupyter_output><empty_output><jupyter_text>ReportAt this point the processing is complete. This section is to review some of the results.<jupyter_code>total_reports = min(len(captions), 10)
for n in range(total_reports):
    print(str(n)+'| '+output_screenshots[n])
    print(' | '+captions[n][:100].replace("\n", " "))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12316099201345103, 'fraction_numerical': 0.007776376628835646, 'mean_word_length': 4.195414847161572, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 42, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '356437', 'license': 'MIT', 'n_tokens_mistral': 1620, 'n_tokens_neox': 1562, 'n_words': 380, 'path': 'ocr-to-iptc.ipynb', 'repo_name': 'andrewthong/ocr-to-iptc', 'size': '4758'}