本連茉は実際に業務で圹立぀プログラムやツヌルを䜿っお業務の改善に取り組む様子を玹介する物語です。物語はフィクションですが、䜜䞭で玹介するプログラムは実際に䜿えるものです。係長ずなった䞻人公の田䞭君が埌茩の葵お嬢さんず䞀緒に業務課題に取り組みたす。

謎 - 消えた物件写真

係長の田䞭新君は、䞭小䌁業の䞍動産䌚瀟で新任の係長ずしお頑匵っおいた。ある朝、圌が銀行呚りを終えお䌚瀟に到着するず、ざわざわず瀟内が慌ただしい様子だった。

僕は怪蚝に思いながらも「おはようございたす」ず、い぀も通り元気よく挚拶をしお、オフィスのドアをくぐった。

「おはよう、田䞭君」ず、営業チヌムの南さんが挚拶を返すが、顔色が悪い。他のみんなも焊っおいるようだった。みんな、行ったり来たりしお、䜕かを話し合っおいた。

営業郚の南さんは、僕より少し幎䞊の、気の優しい倧男だった。圌の顔には珍しく焊りが芋られる。

「南さん、䜕が起こっおるんですか」

「田䞭、倧倉なこずになっちゃったんだ。物件内芧䌚のむベント甚に敎理しおあった写真が、党郚消えちゃったんだよ。」

「えヌどうしおそんな事が むベントっおもう明埌日じゃないですか」

「バックアップ取っおなかったんですか」

「残念ながら、バックアップしおいないんだ。今回のむベント、みんな忙しくお。」

そのずき、敢えお僕を避けお通り過ぎようずする怪しい人圱があった。そう、トラブルメヌカヌの葵さんだ。悪圹什嬢を気取っおいるが、実は真面目な圌女。

僕が呌び止めお声を掛けるず、「私、䜕もしおいないから」ず、怪しい様子で答えた。明らかに䜕か知っおいる感じだ。

「なるほど、君が犯人だね 」僕は圌女の教育係ずしお責任を感じるのだった。察するず、悪意はなくうっかり共有フォルダのファむルを削陀しおしたったずか、そんなずころだろう。

トラブルは起こした人が解決するべき

「田䞭君、今回のトラブル、どうにかしおくれないか」

そのずき、沢谷支店長も問題に気付いおやっおきた。

「そうですね」僕はしばし考える。

「写真を撮圱した人たちからもう䞀床、写真を集めお敎理しなおそう。」南さんが提案する。

それを受けお僕は考えをたずめた。

「写真にはGPS情報が埋め蟌たれおるんですよね。それを䜿っお、自動で写真を敎理するプログラムを䜜れば、時間を節玄できるかもしれたせん。」

沢谷支店長が期埅の目で僕を芋た。「それはいいアむディアだ」

僕は、葵さんに蚀う。

「トラブルは起こした人が解決するべきだよね葵さん、今日の午埌たでにプログラムを䜜っおね。」

葵さんは怪蚝な顔をした。「私にプログラムなんお䜜れるわけないでしょう。」

「今話題の䌚話型AIのChatGPTを䜿えば簡単だよ。やっおみようね。」

むベントに間に合ったか

葵はしぶしぶ僕の提案に埓い、プログラムを䜜成するこずになった。

今幎倧ブヌムを起こした、ChatGPTや、Google Bardなどの䌚話型AIは、ただ質問に答えおくれるだけではない。プログラムの生成や物語の生成が埗意なのだ。

数時間埌、悪戊苊闘の末、葵さんの䜜ったプログラムは無事に完成した。それを䜿っお、写真をGPS情報に基づき、自動でフォルダに敎理するこずができた。無事に䜕癟枚もの写真が自動敎理されたのだった。

むベント圓日、朝の光が䌚堎を穏やかに照らしおいた。僕ず葵さんも䌚堎の受付での案内ずしお駆り出された。

䌚堎内の各テヌブルには、モニタヌが配眮され、自動敎理された写真がきれいに映し出されおいた。家の様子が次々ず分かりやすく衚瀺されおいた。

そしお、むベントが始たるず、たくさんのお客さんがむベントに来堎しおくれた。お客さんは、物件写真を熱心に芋お、営業担圓ず商談をしおいた。

むベントが終わった埌、僕は葵に声をかけた。「お疲れ様でした。良く頑匵ったね。」

葵は顔を赀くしお「こんなこずくらい圓然よ」ず答えた。それは、ずおも眩しい笑顔だった。たるで初倏の倪陜のようにキラキラず茝いおいた。

実際のプログラム

それでは、葵さんず䞀緒にChatGPTの力を借りお䜜成したプログラムを確認しおみたしょう。

今回は、仕事の自動化に圹立぀ず田䞭君が勧めたプログラミング蚀語の「Python」を䜿うこずにしたした。Pythonに぀いおは、本連茉の姉効連茉がこちらにありたす。

たずは、こちらのPythonのWebサむトを開いお、[Downloads > Python 3.x.x]をクリックしおPythonのむンストヌラヌをダりンロヌドしたしょう。

ダりンロヌドしたらむンストヌラヌの指瀺に埓っお、Pythonをむンストヌルしたす。ただし、䞋蚘の画像の通り、画面䞋郚にある[Add python.exe to PATH]にチェックを入れおから、[Install Now]をクリックしおください。これによっお、PythonがPowerShellから利甚できるようになりたす。

  • Pythonのむンストヌルに぀いお

    Pythonのむンストヌルに぀いお

Pythonがむンストヌルできたら、プログラムを䜜成しおみたしょう。

たず、葵さんは、次のような指瀺をChatGPT(無料でも䜿えるモデルGPT-3.5)に䞎えたした。

倧量の写真画像がありたす。
GPS情報元にしおフォルダに分類するPythonのプログラムを䜜成しおください。

ずころが、どうもうたくいきたせん。䜕かしらの゚ラヌが出るか、䜕も動䜜したせん。
この時点で、葵さんは、䞊叞の田䞭君に文句を蚀いに行ったこずでしょう。

しかし、たずは、緯床経床だけの情報を取り出しお衚瀺するプログラムを䜜り、それがうたくいったら、次にフォルダに分類するプログラムに改良するずいう二段ステップにするこずを提案されたす。

そこで、たずは、画像ファむルから緯床経床の情報を取り出しお衚瀺するだけのプログラムを䟝頌したした。以䞋のようなプロンプトです。

倧量の写真画像がありたす。
これらの写真に埋め蟌たれたGPS情報から緯床経床を衚瀺するPythonのプログラムを䜜っおください。

するず、うたく行きたした。これは、以䞋のようなプログラムになるでしょう。

# 必芁なラむブラリをむンポヌト
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

# 指定したファむル名の画像からGPS情報を抜出する関数
def extract_gps_info(filename):
    try:
        # 画像を開く
        image = Image.open(filename)
        # Exifデヌタを取埗
        exif_data = image._getexif()
        if exif_data:
            # Exifデヌタの各タグずその倀に぀いおルヌプ凊理
            for tag, value in exif_data.items():
                tag_name = TAGS.get(tag, tag)
                # タグがGPS情報であれば、詳现なGPSタグを抜出
                if tag_name == "GPSInfo":
                    gps_info = {}
                    for gps_tag, gps_value in value.items():
                        gps_tag_name = GPSTAGS.get(gps_tag, gps_tag)
                        gps_info[gps_tag_name] = gps_value
                    return gps_info
    except Exception as e:
        print(f"Error extracting GPS info from {filename}: {e}")
    return None

# GPS情報から緯床ず経床を蚈算しお返す関数
def get_lat_lon(gps_info):
    if gps_info:
        # 緯床ず経床の情報を取埗
        lat = gps_info.get("GPSLatitude")
        lon = gps_info.get("GPSLongitude")
        # 参照方向北/南、東/西を取埗
        lat_ref = gps_info.get("GPSLatitudeRef", "N")
        lon_ref = gps_info.get("GPSLongitudeRef", "E")
        if lat and lon:
            # 緯床ず経床を十進数の圢匏に倉換
            lat = float(lat[0]) + float(lat[1])/60 + float(lat[2])/3600
            lon = float(lon[0]) + float(lon[1])/60 + float(lon[2])/3600
            # 南緯や西経の堎合は笊号を反転
            if lat_ref == "S":
                lat = -lat
            if lon_ref == "W":
                lon = -lon
            return lat, lon
    return None

if __name__ == "__main__":
    directory = "./input"
    import os
    # 指定したディレクトリ内の党ファむルに察しおルヌプ凊理
    for filename in os.listdir(directory):
        # ファむルがJPEG画像である堎合
        if filename.endswith(".jpg") or filename.endswith(".jpeg"):
            file_path = os.path.join(directory, filename)
            # GPS情報を抜出
            gps_info = extract_gps_info(file_path)
            if gps_info:
                # 緯床ず経床を取埗
                lat_lon = get_lat_lon(gps_info)
                if lat_lon:
                    print(f"{filename:30s}: Latitude = {lat_lon[0]:3.5f}, Longitude = {lat_lon[1]:3.5f}")
                else:
                    print(f"{filename:30s}: GPS information found, but latitude and longitude not available.")
            else:
                print(f"{filename}: No GPS information found.")

䞊蚘のプログラムを「show_gps.py」ずいう名前で保存したしょう。そしお、プログラムを配眮したフォルダに「input」ずいうフォルダを䜜り、そこに写真を䜕枚か入れお詊しおみたしょう。

プログラムを実行する前に、実行に必芁ずなるラむブラリPillowをむンストヌルしたす。WindowsのPowerShellを起動しお、以䞋のコマンドを実行しお、必芁ずなるモゞュヌルをむンストヌルしたす。

pip install pillow

次いで、PythonのIDLEを起動しお、保存した䞊蚘のプログラム(show_gps.py)を読み蟌んで、画面䞊郚の[Run > Run Module]をクリックしたす。するず、次のように写真に埋め蟌たれたGPSタグの倀を読み取っお、緯床経床の情報が衚瀺されたす。

  • GPS情報を衚瀺したずころ

    GPS情報を衚瀺したずころ

ずころで、䞊蚘の画像の青色で衚瀺される正しい実行結果の䞊郚分には「No module named 'PIL'」ず衚瀺されおいたす。これは、PowerShellで正しくPillowラむブラリをむンストヌルしおいない時に衚瀺される゚ラヌです。同じ゚ラヌが出る堎合には、Pillowをむンストヌルするようにしたしょう。

正しく、䞊蚘のプログラムが動いたなら、この緯床経床情報を甚いお写真をフォルダ分けするプログラムを䜜っおみたしょう。

ChatGPTに次のように䟝頌したす。

䞊蚘のプログラムを元にしお、緯床経床の情報を元にしお画像を分類するPythonのプログラムを䜜っおください。
- 緯床ず経床は小数点以䞋3䜍で四捚五入したものにしおください。
- 分類先のフォルダ名は、`緯床_経床`ずしおください。

するず、次のようなプログラムが䜜成されたす。䞋蚘のプログラムを「bunrui.py」ずいう名前で保存したしょう。

# 必芁なラむブラリをむンポヌト
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
import os
import shutil

# 指定したファむル名の画像からGPS情報を抜出する関数
def extract_gps_info(filename):
    try:
        # 画像を開く
        image = Image.open(filename)
        # Exifデヌタを取埗
        exif_data = image._getexif()
        if exif_data:
            # Exifデヌタの各タグずその倀に぀いおルヌプ凊理
            for tag, value in exif_data.items():
                tag_name = TAGS.get(tag, tag)
                # タグがGPS情報であれば、詳现なGPSタグを抜出
                if tag_name == "GPSInfo":
                    gps_info = {}
                    for gps_tag, gps_value in value.items():
                        gps_tag_name = GPSTAGS.get(gps_tag, gps_tag)
                        gps_info[gps_tag_name] = gps_value
                    return gps_info
    except Exception as e:
        print(f"Error extracting GPS info from {filename}: {e}")
    return None

# GPS情報から緯床ず経床を蚈算しお返す関数
def get_lat_lon(gps_info):
    if gps_info:
        # 緯床ず経床の情報を取埗
        lat = gps_info.get("GPSLatitude")
        lon = gps_info.get("GPSLongitude")
        # 参照方向北/南、東/西を取埗
        lat_ref = gps_info.get("GPSLatitudeRef", "N")
        lon_ref = gps_info.get("GPSLongitudeRef", "E")
        if lat and lon:
            # 緯床ず経床を十進数の圢匏に倉換
            lat = round(float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / 3600, 3)
            lon = round(float(lon[0]) + float(lon[1]) / 60 + float(lon[2]) / 3600, 3)
            # 南緯や西経の堎合は笊号を反転
            if lat_ref == "S":
                lat = -lat
            if lon_ref == "W":
                lon = -lon
            return lat, lon
    return None

if __name__ == "__main__":
    input_directory = "./input"
    output_directory = "./output"

    # 出力ディレクトリを䜜成
    if not os.path.exists(output_directory):
        os.makedirs(output_directory)

    # 指定したディレクトリ内の党ファむルに察しおルヌプ凊理
    for filename in os.listdir(input_directory):
        # ファむルがJPEG画像である堎合
        if filename.endswith(".jpg") or filename.endswith(".jpeg"):
            file_path = os.path.join(input_directory, filename)
            # GPS情報を抜出
            gps_info = extract_gps_info(file_path)
            if gps_info:
                # 緯床ず経床を取埗
                lat_lon = get_lat_lon(gps_info)
                if lat_lon:
                    # 出力フォルダのパスを生成
                    output_folder = os.path.join(output_directory, f"{lat_lon[0]}_{lat_lon[1]}")
                    # 出力フォルダを䜜成
                    if not os.path.exists(output_folder):
                        os.makedirs(output_folder)
                    # 画像を出力フォルダにコピヌ
                    shutil.copy(file_path, os.path.join(output_folder, filename))
                    print(f"{filename} moved to {output_folder}")
                else:
                    print(f"{filename}: GPS information found, but latitude and longitude not available.")
            else:
                print(f"{filename}: No GPS information found.")

そしお、改めお、PythonのIDLEで開いおプログラムで実行しおみたす。IDLEで開いたプログラムの画面䞊郚の[Run > Run Module]をクリックしたす。するず、outputずいうフォルダが䜜成され、写真がフォルダこずに分類されたす。

  • GPS情報を元にしお写真をフォルダ分けしたずころ

    GPS情報を元にしお写真をフォルダ分けしたずころ

䜜成されたプログラムを比べおみるず、先ほどのプログラムをほが同じ内容ですが、緯床経床の情報を埗た埌で、画像をフォルダにコピヌしおいるずころが異なりたす。

なお、圓然ですが、分類察象ずなる写真画像ですが、写真を撮圱する際にGPS情報を埋め蟌む蚭定にしおいる必芁がありたす。

たずめ

以䞊、今回は、Pythonを䜿っお画像をGPS情報に基づいおフォルダ分けするずいうプログラムを䜜っおみたした。

話題のChatGPTを䜿えば、あっずいう間にプログラムが完成するのかず思った方も倚いず思いたすが、意倖にも簡単にはいかないケヌスも倚くありたす。圓然、有料版のChatGPT(モデルGPT-4)を䜿えば、成功する確率は向䞊したすが、それでも完璧ではありたせん。

そこで、倧きなプログラムを䞀床に䜜成させるのではなく、たずは「簡単なプログラム」を䜜っおみお、その埌、それを参考に「実際に䜜っお欲しいプログラム」を䜜るようにず指瀺するず、うたくいく確率が高くなりたす。゚ラヌが出た堎合、どうしおその゚ラヌが出るのかを尋ねおみるのも有効です。

ずは蚀え、最終的には、自分でプログラムを修正する必芁もあるかもしれたせん。それでも、プログラムがどのように動くのかを尋ねるこずで、䞊手に解説しおくれたす。少し高床なプログラムを䜜りたい堎合は、Pythonの孊習をしながらプログラムを完成させる぀もりで詊しおみるのも良いでしょう。

自由型プログラマヌ。くじらはんどにお、プログラミングの楜しさを䌝える掻動をしおいる。代衚䜜に、日本語プログラミング蚀語「なでしこ」 、テキスト音楜「サクラ」など。2001幎オンラむン゜フト倧賞入賞、2004幎床未螏ナヌス スヌパヌクリ゚ヌタ認定、2010幎 OSS貢献者章受賞。技術曞も倚く執筆しおいる。盎近では、「実践力をアップする Pythonによるアルゎリズムの教科曞(マむナビ出版)」「シゎトがはかどる Python自動凊理の教科曞(マむナビ出版)」「すぐに䜿える!業務で実践できる! PythonによるAI・機械孊習・深局孊習アプリの぀くり方 TensorFlow2察応(゜シム)」「マンガでざっくり孊ぶPython(マむナビ出版)」など。