話題のOpen Interpreterがどのように動くのか試してみました。ちょうどstable-diffusionで生成した画像上下に余白をつけてサイズ調整したいと考えていたので、Open Interpreterにはそれを実現するためのPythonコードをお願いしてみたいと思います。
本記事ではOpen Interpreterがどのような流れで動作するのか、また何がうまくできなかったのかを合わせてご紹介いたします。
この記事は以下のような方に向けて書いています。
- Open InterpreterでPythonコードを生成し、画像の余白追加を自動化する方法について解説
- Open Interpreterの回答精度とAPI利用にかかった費用について
実行環境
- windows 11
- Docker version 25.0.3, build 4debf41
- Python(Docker):Python 3.10.12
- open-interpreter:Version: 0.2.2
環境構築については以下の記事をご参照ください。
Pythonコードから実行(うまくいかず)
当初、Pythonコードからinterpreterを呼び出して実行することを試みましたが、途中でエラーが発生してしまいうまくいきませんでした。試したときの手順は以下の通りです。
まずDockerコンテナを起動、接続します。
docker run -it --rm -v /host_mnt/c/Users/<user-name>/openinterpreter/scripts:/home/scripts --name openinterpreter1 openinterpreter /bin/bash
次に以下の簡単なコードを作成します。
from interpreter import interpreter
prompt = "フォルダ内にある全ての画像は1024*1024サイズです。この画像ファイルを1024*1448の大きさのファイルの中央に配置して出力しなおすプログラムをPythonで作成して。解説は日本語でお願いします。"
interpreter.chat(prompt)
すると実行している最中に以下のようにエラーが出て中断してしまいました。
root@bef0493a08c7:/home/scripts# /bin/python3.10 /home/scripts/open-interpreter.py
Open Interpreter will require approval before running code.
Use interpreter -y to bypass this.
Press CTRL-C to exit.
まず、以下のステップにしたがって作業を進めます。
1 まず、カレントディレクトリの全ファイルをリストします。
2 リストに含まれる画像ファイルだけを抽出します。
3 画像ファイルのサイズを変更し、新しいサイズの画像の中央に配置します。
それでは、まずはカレントディレクトリの全ファイルをリストアップします。以下のコードを実行します。
import os
files = os.listdir()
files
Would you like to run this code? (y/n)
y
ディレクトリ内のファイルをリストアップしました。以下がそれです:
{'aaa.txt', 'new_sample_image.jpg', 'open-interpreter.py', 'sample_image.jpg',
'sample_image_new.jpg'}
次に、画像ファイルだけをリストから選び出します。画像ファイルは通常、「.jpg」、「.jpeg」、「.png」等
の拡張子を持つので、これらの拡張子を持つファイルだけを選び出します。
それでは次に、そのようなPythonコードを実行します。
image_files = [file for file in files if file.endswith(('.jpg', '.jpeg', '.png'))]
image_files
Would you like to run this code? (y/n) y
以下の画像ファイルが見つかりました:
'new_sample_image.jpg', 'sample_image.jpg', 'sample_image_new.jpg'
次に、これらの画像ファイルのサイズを変更し、それを新しいサイズの画像の中央に配置することを試みます
。それを実現するには、PythonのPillowライブラリを使用します。
まずPILライブラリがインストールされているか確認します。インストールされていない場合は、Pillowをイン
ストールします。それでは、次のPythonコードを実行します。
root@bef0493a08c7:/home/scripts# [IPKernelApp] WARNING | Parent appears to have exited, shutting down.
5回ほど試しましたが、一度も最後まで実行できませんでした。ChatGPTに尋ねたところ、Dockerコンテナのリソース不足やネットワークの問題が原因の可能性があるとのことでしたが、解決には至らなかったため、コードからの実行は諦めることにしました。
interpreterコマンドから実行(成功)
Pythonコードからの実行ができなかったのでinterpreterコマンドを実行する方法に方針変更しました。以下のようにinterpreterコマンドを実行することで対話が開始します。
interpreter -y
>
まずは依頼したい内容を書き出してみます。日本語で大丈夫なようなので日本語で記入し、回答も日本語で返してもらえるよう明記しました。
>フォルダ内にある全ての画像は1024*1024サイズです。この画像ファイルを1024*1448の大きさのファイルの中央に配置して出力しなおすプログラムをPythonで作成して。解説は日本語でお願いします。
まず、/home/scripts フォルダ内に存在する全ての画像ファイルの一覧を取得するために、globライブラリを使用します。次にPIL(Python Imaging Library)を使用して、画像の操作と変換を行います。
以下が私たちの計画です:
1 現在の作業ディレクトリ/home/scriptsで、全ての画像ファイルを探します。これにはglobライブラリを使用します。
2 各画像ファイルを開き、それらを新しい1024×1448ピクセルの背景画像の真ん中に配置します。これにはPillowライブラリを使用します。
3 更新された画像を保存します。
それでは、まずは現在の作業ディレクトリ内の全ての画像ファイルの一覧を取得するコードを実行しましょう。下記のPythonコードは、.png、.jpgおよび.jpeg形式の全ての画像ファイルを探します。
import os
import glob
# /home/scripts Directory
path = '/home/scripts'
# Define the image formats
formats = ['*.png', '*.jpg', '*.jpeg']
# Initialize the image list
images = []
# Loop through each format
def get_images(form):
# Glob the directory with the specific format
image_list = glob.glob(form)
images.extend(image_list)
# Change the directory
os.chdir(path)
# Get the images
for format in formats:
get_images(format)
# Return the image list
images
['sample_image.jpg']
フォルダ内に見つけた画像ファイルは ‘sample_image.jpg’ です。
次に、この画像を開き、新しい1024×1448ピクセルの背景画像の中央に配置します。 ここでは、”Pillow” ライブラリの “Image” モジュールを使用して画像を操作します。
まず、新しい背景画像(サイズ:1024×1448ピクセル)を作成し、それを白色で塗りつぶします。次に、元の画像を開き、そのサイズを取得します。そして、新しい背景画像に元の画像を配置するための座標を計算します。
新しい背景画像の中心に元の画像を配置するには、次の座標を計算します:
x = (new_width - old_width) / 2
y = (new_height - old_height) / 2
最後に、”paste” メソッドを使用して、新しい背景画像に元の画像を配置します。以下のコードを実行してみましょう。このコードは、見つけた最 初の画像ファイル ‘sample_image.jpg’ を新しい大きさの背景画像の中央に配置します。
注意:この操作を行う前に、Pillowライブラリがインストールされていることを確認してください。もしインストールされていなければ、以下のコードを使用してインストールすることができます:
!pip install pillow
import PIL
from PIL import Image
# New image size
new_size = (1024, 1448)
# Open the image file
img = Image.open('sample_image.jpg')
# Get the size of the image
img_width, img_height = img.size
# Calculate the position to center the image
position = ((new_size[0]-img_width)//2, (new_size[1]-img_height)//2)
# Create a new white image
new_img = Image.new('RGB', new_size, (255, 255, 255))
# Paste the image
new_img.paste(img, position)
# Save the new image
new_img.save('new_sample_image.jpg')
# Return the path of the new image
'new_sample_image.jpg'
新しく生成された画像は ‘new_sample_image.jpg’ という名前で保存されました。この画像では、元の画像が新しい画像サイズ(1024×1448ピクセルの背景画像)の中央に配置されています。
上記の手順をフォルダ内の他の画像に対しても適用したい場合は、Pythonコードの中でforループを追加して各画像に対してこれらの手順を繰り返すことができます。
冒頭に指示を与えてからここまで、一切操作せずに自動で進みました。必要なライブラリもインポートしてプログラムコードも作成されています。私の希望ではフォルダ内のすべての画像に対して画像処理をして欲しいため、その旨をOpen Interpreterに伝えます。また、画像のファイル名が’sample_image.jpg’のときに動くコードになっているので、画像のファイル名に関わらず動作するように変更を求めてみます。
sample_image.jpgという名称は不明の状態で、フォルダにある画像すべてに対して処理を実行してほしいです。
すみませんが、具体的な指示が必要です。たくさんの画像があってそれぞれに新しく名前をつけることを指しているのでしょうか。それとも全ての画像を一つの背景画像に貼り付けたいということでしょうか。それとも別の指示でしょうか。それぞれの場合には異なる取り組み方が必要となるからです。具体的に何をしたいのかお教えいただけますでしょうか。
AIから指示が不明確だと指摘されました。Open Interpreter(ChatGPT)は、このような場合、自分の判断で進めるのではなく、ユーザーとの認識のすり合わせを行う点が優れていますね。もう一度、明確な指示を与えることにします。
フォルダの中に複数の画像があります。その画像一つ一つを新しい画像サイズ(1024×1448ピクセルの背景画像)の中央に配置して ほしいです。
了解しました。先ほどの単一画像の処理をすべての画像に適用するようコードを修正します。そのためには、写真のリストをループしてそれぞれの画像に対して以下の処理を実行します:
1 各画像を開く
2 新しい背景画像を作成(1024×1448ピクセル、白色)
3 元の画像を新しい背景画像の中心に配置
4 新しい画像を保存(新しいファイル名は元のファイル名に’_new’を追加)
それでは、これらの手順を実行するPythonコードを実行します。これにより、フォルダ内の全ての画像が新しいサイズの白い背景の中央に配置された新しい画像として保存されます。
完成したようです。ただ、肝心のコードが出力されていません。表示するようにお願いします。
実行したコードを表示して
# New image size
new_size = (1024, 1448)
# Process all images
for image_file in images:
# Open the image file
img = Image.open(image_file)
# Get the size of the image
img_width, img_height = img.size
# Calculate the position to center the image
position = ((new_size[0]-img_width)//2, (new_size[1]-img_height)//2)
# Create a new white image
new_img = Image.new('RGB', new_size, (255, 255, 255))
# Paste the image
new_img.paste(img, position)
# Save the new image with a new filename
new_img.save(os.path.splitext(image_file)[0] + '_new.jpg')
'Processed all images.'
これにより、/home/scriptsフォルダ内の全ての画像(PNG、JPG、JPEG)が新しい背景画像(サイズ:1024×1448ピクセル)の中央に配置され、元のファイル名に’_new’を追加した新しいファイル名で保存されました。
例えば、元の画像が ‘sample_image.jpg’ だった場合、新しい画像は ‘sample_image_new.jpg’ という名前で保存されます。
この作業はすべての画像について実行され、各画像は元の形状を保ったまま新しい背景上に中央揃えで配置されています。したがって、原画像が1024×1024ピクセル未満の場合でも、新しい画像は1024×1448ピクセルのサイズを保ちます。
もし何か他にご質問や要求がありましたら、いつでもお知らせください。
以上でプログラムコードの作成は終了しました。ほとんど何も操作せずに完了しています。今回はコード作成をして欲しかったので上記のようなオーダーで試しましたが、実行の過程ですでに画像のアウトプットまで実施してありました。
imageサイズが1024*1448になっていて、さらに画像が中央に配置されています。まさにオーダー通りの形になっていますね。素晴らしいです。
完成コードを実行してみる
完成したコードが実際に動作するのか、実際に画像を用意して試してみます。
# New image size
new_size = (1024, 1448)
# Process all images
for image_file in images:
# Open the image file
img = Image.open(image_file)
# Get the size of the image
img_width, img_height = img.size
# Calculate the position to center the image
position = ((new_size[0]-img_width)//2, (new_size[1]-img_height)//2)
# Create a new white image
new_img = Image.new('RGB', new_size, (255, 255, 255))
# Paste the image
new_img.paste(img, position)
# Save the new image with a new filename
new_img.save(os.path.splitext(image_file)[0] + '_new.jpg')
実行しようとコードエディター(VS CODE)に張り付けたところまず冒頭にimport文がなく、さらにfor文の imagesのリストが定義されていませんでした。その旨をもう一度OpenInter preterに指摘します。
for image_file in images: のimagesが定義されていません。修正してコード全文を出力してください。
すみません、imageのリストが不足していました。以下の修正された完全なコードをご確認ください。
import os
import glob
from PIL import Image
# Define the directory and formats
path = '/home/scripts'
formats = ['*.png', '*.jpg', '*.jpeg']
# Function to collect all image files
def collect_images(directory, formats):
images = []
for format in formats:
images.extend(glob.glob(os.path.join(directory, format)))
return images
# Collect all images
images = collect_images(path, formats)
# New image size
new_size = (1024, 1448)
# Process all images
for image_file in images:
# Open the image file
img = Image.open(image_file)
# Get the size of the image
img_width, img_height = img.size
# Calculate the position to center the image
position = ((new_size[0]-img_width)//2, (new_size[1]-img_height)//2)
# Create a new white image
new_img = Image.new('RGB', new_size, (255, 255, 255))
# Paste the image
new_img.paste(img, position)
# Save the new image with a new filename
new_img.save(os.path.splitext(image_file)[0] + '_new.jpg')
print("All images have been processed!")
このコードは、 ‘/home/scripts’ ディレクトリ内の全ての .png, .jpg, .jpeg 画像を収集し、新しい1024×1448ピクセルの背景画像の中央に各画像を配置します。新しい画像は元の画像名に ‘_new’ を追加した名前で保存されます。
コードを直してもう一度実行したところ、画像のフォルダ内にある全ての画像に処理を行うことができました。
左画像が処理前、右画像が処理後になっていて、しっかりオーダー通りのプログラムができました。
API利用でかかった費用
今回、Open InterpreterはGhatGPT-4を利用しているため、APIの費用が掛かります。APIの利用状況はChatGPT公式ページにログインしてUsageを参照すると確認することができます。実際に見てみましょう。
3月19日に$1.37と記載があります。これが今回かかった費用です。上述したように何回かやり直したり、指示を出し直したりしているのでそれを含めた金額になります。調子に乗ってやりすぎてしまうと一気に金額が跳ね上がりそうですね。。気を付けます。
まとめ
本記事では、Open InterpreterでPythonコードを自動生成し、画像の余白追加処理を自動化する方法についてご紹介しました。Open Interpreterは指示に従ってコードを生成してくれるだけでなく、必要に応じてユーザーに質問し、認識のすり合わせを行うことで正確なコードを出力してくれました。
Open InterpreterのようなAIアシスタントを活用することで、プログラミングの生産性を大幅に高めることができそうです。今後もAI技術の発展に伴い、さらに強力なコーディング支援ツールが登場することが期待されます。
本検証内で発生した「PythonコードからOpen Interpreterを呼び出したときに途中で止まってしまう事象」は、原因がわかったらまた更新したいと思います。