はじめに
2023年9月1日~3日に開催された東京藝術大学の学祭(通称:藝祭)にて出店した アスキーアートになるプリ機 についての技術をまとめた記事となっています。
注意
今回の企画は私一人で行ったわけではありません。 あくまで担当範囲内での技術共有、来年度に向けたフィードバックを目的に記事にしています。
今回の企画に携わっていただいたみんなには感謝してもしきれません。ありがとうございました!!!これからもよろしくお願いします!
目次
東京藝術大学テクノロジー研究会とは
自己紹介
今回の企画概要
システム概要
当日の様子
実際のコード
さいごに
東京藝術大学テクノロジー研究会とは
東京藝術大学の公式サークルです。実態はDiscordサーバーになっていて、学外の生徒や社会人などいろいろな方がいます。
活動は不定期、CG・プログラミングなどを使って創作をすることを目的で活動しています。
𝕏(Twitter):https://twitter.com/geidai_techno
自己紹介
プリ機の撮影・ラクガキブースの各システムを開発した 塩田航佑 と申します。
理数科の中高一貫校に通っていました。中高時代、情報工学部という部活でC++を使って競技プログラミングをしたり、高校ではPythonを用いた機械学習について研究したりしていました。また、映画製作に魅了され中学三年生から自主制作で映画を作ったりしています。
そんなこんなで、メディアアート・映像表現を探求できる東京藝術大学先端芸術表現科に在籍しているという感じです。
※撮影したデータの共有システム、ダウンロード用のWEBサイト開発は尾上(@YumNumm )くん/ラクガキペンのシステム開発は内田さんが担当しています
<尾上君の記事>
今回の企画概要
5月中旬に差し掛かったある日、「BUG」をテーマにアートマーケットで何かを出店しようという話がサークル内で提案されました。そこで、「アスキーアート」「グリッチノイズ」などについてのリサーチが始まり、最終的にはそれらを体験として楽しんでもらえる「プリントシール機」を出店することにまとまりました。
今回の企画、最大の特徴は「盛る」ではなく「バグ」というコンセプトの元、顔などの情報が文字へと変換され、視認性が低くなることです。従来のプリ機とは違い、匿名性を少し内包するような不思議なプリにできたらと考えました。なぜなら、私自身が自分の写真を誰かと共有することに抵抗感があったからです。私を含め、今までのプリ機に抵抗感があった層にも新たな体験を生み出せないかと思い、進めていったのが今回の企画になります。
システム概要
言語 | Python |
主要ライブラリ | cv2 / numpy / PIL / rembg / tkinter / pygame |
PC | Mac(撮影ブース) / Windows(ラクガキブース) |
周辺機器 | Logicool C920(WEBカメラ) / BenQ PD2700Q(27インチモニタ) |
■全体の流れ
2:撮影ブースへ移動
▶先ほどのQRコードをカメラにかざす
4:ラクガキブースへ移動
▶QRコードをカメラにかざす
撮影された写真 | アスキーアート化された写真 |
---|---|
※撮影された写真にはモザイクが入っています;;
6:体験終了
▶チケットのQRコードをスマホで読み込むとダウンロードサイトへ飛ぶ
■撮影ブース
画像処理 | cv2/numpy/PIL |
クロマキー処理 | rembg |
GUI処理 | tkinter / pygame |
<画像処理>
撮影した写真をアスキーアート化する処理です。
具体的にはキャプチャ画像をグレースケール化して、256階調をそれぞれ文字に割り当てるという感じです。
<クロマキー処理>
Rembgという優秀なライブラリがあったのでこちらを完全に使用しました。
<GUI処理>
ユーザーが操作することはなかったのですが画面変遷と音声ガイドが必要だったのでtkinterとpygameを使用しました。
■ラクガキブース
画像処理 | cv2/numpy/PIL |
GUI処理 | tkinter / pygame |
<画像処理>
ペンでなぞった部分が写真になる処理を加えたり、半透明合成、スタンプの合成などを行っています。
※最終章にあるコードを読んでいただければわかるのですが、cv2とPILがごちゃごちゃで処理することになってしまって最高に重いです。反省です。
<GUI処理>
ペンやスタンプの選択画面の処理、音声ガイドの処理です。
※こちらもマルチスレッド処理の実装が間に合わなかった点、rootでのマウス検知の限界があり操作感が最悪なので反省です。
■まとめ
今回、初めてGUIを伴ったシステムの開発をしたため調べながらの二か月間だったのですが、「処理が重すぎる」という課題に尽きる気がします。まずはマルチスレッドでの処理は必須でした。また、なぞったところが写真になったりAAになったりするというリアルタイム処理が必須となる今回のシステムは初めてやるにはハードルが高すぎたかもしれません。もっと時間をかけて、よりよい処理を考えていきたいというのが今後の展望になります。
当日の様子
たくさんの方に体験していただきありがとうございました。
以下、当日のみなさんの反応と発生した問題についてまとめました。
当日の皆さんの反応
アスキーアートと融合しちゃう変わったプリクラ機で遊んできた🙌
— なかじ @8/13~Vフレット正式版リリース🎉 (@nkjzm) September 3, 2023
藝祭の中での出し物なんだけど、上野公園の中に突如プリクラ機が現れてめちゃ目立ってましたww
らくがきコーナーではアスキーアート化した写真の一部を元に戻せるようになってて、不思議な感じのプリになりました💓💫 #藝祭 #藝祭2023 pic.twitter.com/rW1PkRtnIw
#藝祭2023 が終わりました。
— shino osawa (@hananoutena04) September 3, 2023
色々と大変だったけれど、無事に終わってよかった!
ご来場、作品をご購入いただいた皆様ありがとうございました😊
沢山の方とお話しできて楽しかったです♪
…ちなみに、今日は研究室メンバーとプリクラを撮ったり、ファミレスで打ち上げしたりして楽しみました🌸 pic.twitter.com/uM18O506Z2
#藝祭2023 @geisai_koushiki
— 佐藤はなえ Hanae Sato (@eanahotas) September 3, 2023
東京藝大のテクノロジー研究会による「アスキーアートになるプリクラ機」@geidai_techno
研究室メンバーと体験した!
今日も私は19時まで国際交流棟3階で展示してるよ!来てね〜! pic.twitter.com/m5wNYE8u57
藝祭なう。まずは顧問してるテクノロジー研究会のプリクラ見にきた。
— 八谷和彦 (@hachiya) September 3, 2023
自作ゲーム機売ってたので買った。 pic.twitter.com/yHVKIjbpqu
当日発生した問題
- 1:使用電力が多すぎた
- 屋外での設営だったため、発電機を用いた。事前に計算していたものの、気温などの影響もあり15:00頃に一度発電機がダウン。安定的な電力供給はなかなか難しい。
- 解決策:昼に一度メンタンスを兼ねてガソリン補給などの時間を設けるようにした。
- 2:インターネット回線がダウン
- 画像の共有をテザリングで行っていた。初日はdocomoの5Gギガホプレミアムを使用して行っていたが、まさかのお昼でダウン。問い合わせたところ契約書のなかに「機械的な発信などにより、1度の音声発信またはデータ通信接続において長時間の通話継続または大量のデータ通信があった場合や、一定時間内に連続で音声発信またはデータ通信接続をした場合など、当社設備に影響をおよぼすと当社が判断した場合は、その音声通話を切断またはそのデータ通信の速度を制限することがあります。」という記載がありこれに該当した模様。絶対にパソコン同士のデータ共有はLANで有線接続するほうがよかったと反省。しかし、クラウドに画像を挙げる部分には必ずネット回線が必要なため今後も代替案を考える必要がある。
- 解決策:USBを使ってパワー運用。データは当日の22時にアップするという対応にさせていただき、パソコンとプリンター間の共有は私がUSBを使って行った。(体験までに想定の10倍以上の時間を必要としてしまいご迷惑をおかけしました。すみません。)
- 3:設営作業が大変すぎた
- 公園を使用させていただいている立場だったため毎回設営と解体をやらなくてはいけなかった。その都合もあり次の日に改善したいと思ってもそんな余裕はなく新パッチを適応するための調整などが十分にできなかった。
- 解決策:家で似た環境を構築して家で修正➡当日試すみたいなことをやってみた。(結果は失敗)
実際のコード
注意
・一部(画像共有部分の関数など)掲載していないコードがあります
・使用した素材については配布しません
・バグがあります
当日は再ビルドして解決していましたが、現在も改善中のコードになります
<ディレクトリ構造>
■ラクガキブース
C:\USERS\USERNAME\デスクトップ\SHOOTING_PURI
│ AAmozi.txt
│ AA_S_1.png
│ AA_S_2.png
│ AA_S_3.png
│ BG.png
│ BG1.png
│ BG2.png
│ BG3.png
│ camera_count0.png
│ camera_count1.png
│ camera_count2.png
│ camera_count3.png
│ camera_loading.png
│ comp_S_1.png
│ comp_S_2.png
│ comp_S_3.png
│ count1.png
│ count2.png
│ count3.png
│ guide.png
│ main.py
│ mask.png
│ notice.png
│ puriGUI_ver1.0.py
│ result_1.png
│ result_2.png
│ result_3.png
│ samplepose1.png
│ samplepose2.png
│ samplepose3.png
│ scene1.png
│ scene3.png
│ UUID.csv
└─shot_picture
└─customer1
└─customer2
└─customer3
└─customer4
.
.
.
■ラクガキブース
C:\USERS\USERNAME\デスクトップ\RAKUGAK_PURI
│ AA_L_1.png
│ AA_L_2.png
│ AA_L_3.png
│ bg_1.png
│ bg_1_a.png
│ bg_1_b.png
│ bg_1_c.png
│ bg_2.png
│ bg_3.png
│ bg_4.png
│ brush_widgh1.png
│ brush_widgh1_off.png
│ brush_widgh2.png
│ brush_widgh2_off.png
│ brush_widgh3.png
│ brush_widgh3_off.png
│ brush_widgh4.png
│ brush_widgh4_off.png
│ comp_L_1_temp.png
│ comp_L_2_temp.png
│ comp_L_3_temp.png
│ DL_explanation.wav
│ drawGUI_ver1.0.py
│ icon1.png
│ icon1_off.png
│ icon2.png
│ icon2_off.png
│ icon3.png
│ icon3_off.png
│ icon4.png
│ icon4_off.png
│ icon_stamp1.png
│ icon_stamp1_off.png
│ icon_stamp2.png
│ icon_stamp2_off.png
│ icon_stamp3.png
│ icon_stamp3_off.png
│ icon_stamp4.png
│ icon_stamp4_off.png
│ pen_bg.png
│ printing_explanation.wav
│ QRcodeRead.wav
│ qrread.png
│ rest1.wav
│ rest10.wav
│ rest2.wav
│ rest3.wav
│ rest5.wav
│ result_L_1.png
│ result_L_2.png
│ result_L_3.png
│ scene3_1.png
│ scene3_2.png
│ select_explanation.wav
│ stamp1.png
│ stamp2.png
│ stamp3.png
│ stamp4.png
│ stamp_bg.png
│ start_call.wav
│ time_explanation.wav
│ UUID.csv
撮影ブース
ソースコード
使用したライブラリ一覧
import tkinter as tk
import tkinter.ttk as ttk
import cv2
import numpy as np
import tkinter.filedialog
import PIL.ImageTk
import PIL.Image
import os
import pygame
import requests
from PIL import Image, ImageDraw, ImageFont, ImageOps
from rembg import remove # クロマキーライブラリ
「world_timer」関数で時間制御。しかし、これが最悪でafterで1秒ループしても少しずれるため力技で処理。撮影するタイミング・音声ガイド・ロードタイミングがずれて大変だった。
また、ロードできなかった場合にもう一度読み込むという処理を入れていないので読めなかったらErrorを吐く。これも最大の反省で、画像が読み込めたのかを判定する変数を作るべきだった。そのため、今回は撮った後3秒したら読み込む形でError回避をするようにした。ものすごく力技なのでアスキーアート化する処理などが3秒以上かかるとバグる。
# 管理関数 ------------------------------------- #
def world_timer(): # 時間管理
global time, scene_num, shot_count, animation
time += 1
if scene_num == 1:
if time % 10 == 0 and soundFlag[1] == False:
QRcodeRead.play()
soundFlag[0] = time
soundFlag[1] = True
if time == int(soundFlag[0] + 1):
soundFlag[1] = False
if scene_num == 2:
if time == 3:
if soundFlag[1] == False:
position_explanation.play()
soundFlag[1] = True
if time == scene2_wait:
animation = 0
scene_num = 3
soundFlag[1] = False
if scene_num == 3:
if time == scene2_wait + (shot_time * 3) + 5: # 7s待機
show_scene3()
if time > scene2_wait + 4:
if time == scene2_wait + 5:
pose1.play() # かわいくピース
if time == scene2_wait + shot_time + 4:
pose2.play() # うさみみポーズ
if time == scene2_wait + (shot_time * 2) + 4:
pose3.play() # おまかせポーズ
if ((time - (scene2_wait + (shot_time - 2))) % shot_time) == 0:
count3.play()
if ((time - (scene2_wait + (shot_time - 1))) % shot_time) == 0:
count2.play()
if ((time - (scene2_wait + (shot_time))) % shot_time) == 0:
count1.play()
if ((time - (scene2_wait + (shot_time + 1))) % shot_time) == 0:
shutter.play() # シャッター音(効果音ラボより)
if (time - (scene2_wait + 1)) % shot_time == 0:
if time > (scene2_wait + 1):
if shot_count < 3:
shot_count += 1
if scene_num == 4:
if time == scene2_wait + (shot_time * 3) + 17: # 10s待機
show_scene1()
frame2.after(1000, world_timer)
def road_picture(read_num): # 画像ロード用関数
global notice_2, slot1_AF, slot2_AF, slot3_AF, slot4_AF, slot5_AF, slot6_AF
if read_num == 0:
notice_2 = tk.PhotoImage(file="notice_2.png")
if read_num == 2:
slot1_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/comp_S_1_temp.png"
)
slot2_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/AA_S_1.png"
)
if read_num == 3:
slot1_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/comp_S_1_temp.png"
)
slot2_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/AA_S_1.png"
)
slot3_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/comp_S_2_temp.png"
)
slot4_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/AA_S_2.png"
)
if read_num == 4:
slot1_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/comp_S_1_temp.png"
)
slot2_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/AA_S_1.png"
)
slot3_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/comp_S_2_temp.png"
)
slot4_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/AA_S_2.png"
)
slot5_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/comp_S_3_temp.png"
)
slot6_AF = tk.PhotoImage(
file="./shot_picture/customer" + str(qr_UUID) + "/AA_S_3.png"
)
# -------------------------------------------- #
全部で3つのシーンで構成されている。
それぞれのシーンを見せる時(最上面に移動させる)変数を初期化。
# シーンチェンジ関数 ---------------------------- #
def show_scene1():
global scene_num, soundFlag, qrreadFlag, data
scene_num = 1
soundFlag[1] = False
qrreadFlag = False
data = None
scene1.tkraise()
def show_scene2():
global scene_num, time, shot_count, soundFlag
scene_num = 2
time = 0
shot_count = 0 # 撮影枚数カウント
soundFlag[1] = False
scene2.tkraise()
def show_scene3():
global scene_num, qr_UUID
ImageTransfer.upload_image(
qr_UUID, "./shot_picture/customer" + str(qr_UUID) + "/AA_L_1.png"
)
ImageTransfer.upload_image(
qr_UUID, "./shot_picture/customer" + str(qr_UUID) + "/AA_L_2.png"
)
ImageTransfer.upload_image(
qr_UUID, "./shot_picture/customer" + str(qr_UUID) + "/AA_L_3.png"
)
ImageTransfer.upload_image(
qr_UUID, "./shot_picture/customer" + str(qr_UUID) + "/comp_L_1_temp.png"
)
ImageTransfer.upload_image(
qr_UUID, "./shot_picture/customer" + str(qr_UUID) + "/comp_L_2_temp.png"
)
ImageTransfer.upload_image(
qr_UUID, "./shot_picture/customer" + str(qr_UUID) + "/comp_L_3_temp.png"
)
rakugaki_move.play()
scene_num = 4
scene3.tkraise()
# -------------------------------------------- #
アスキーアート化する処理部分。
ライブラリがごちゃごちゃでいちいち変換したり戻したりでもっとスマートにできたと思う。特に、いちいち画像ファイルとして書き出して読み込んでという処理がもったいない。
等幅フォントを用いてきれいにAAになるようにはなったもののフォントサイズが整数でしか定義できず、無理やりクロップしたり引き延ばして対応した。正確には少し写真とずれている;;
# 画像加工関数 ---------------------------- #
def printText(img, text, point, size, color): # テキスト描画処理
# 等幅フォントであるMenloを使用
font = ImageFont.truetype("/System/Library/Fonts/Menlo.ttc", size)
# imgをndarrayからPILに変換
img_pil = Image.fromarray(img)
# drawインスタンス生成
draw = ImageDraw.Draw(img_pil)
# テキスト描画
draw.text(point, text, fill=color, font=font)
# PILからndarrayに変換して返す
return np.array(img_pil)
def AAFrame(): # AA処理
capframe = cv2.imread(
"./shot_picture/customer"
+ str(qr_UUID)
+ "/comp_L_"
+ str(shot_count)
+ "_temp.png"
)
capframe = cv2.convertScaleAbs(capframe, alpha=1.3, beta=0) # コントラスト調整
moziframe = cv2.resize(capframe, (75, 90)) # 1/12に縮小
gray = cv2.cvtColor(moziframe, cv2.COLOR_BGR2GRAY)
gray1 = cv2.equalizeHist(gray) # ヒストグラムの平坦化処理
outputM = ""
# AA化処理
for gray2 in gray1:
outputM += "\n"
for dark in gray2:
outputM += colorset[dark // 16] * 2
# 同ファイル内に「AAmozi.txt」を作った上で実行してください
with open("AAmozi.txt", mode="w") as f:
f.write(outputM)
# 改行ごとにリスト化
mozi_textList = outputM.split("\n")
AAframe = np.full((1080, 950, 3), (255, 255, 255), dtype=np.uint8) # 1080*950
# AAを書き込み
for i in range(len(mozi_textList)):
AAframe = printText(
AAframe, mozi_textList[i], (0, int(i * 11.75)), 10, (0, 0, 0)
) # 等倍
# AAframe = printText(AAframe, mozi_textList[i], (5, 0 + int(i * 7.45)), 6, (0, 0, 0)) #二倍
# cv2.imwrite('AA.png', AAframe)
AAfin = AAframe[12:1068, 0:903]
resize_AAfin_L = cv2.resize(AAfin, (900, 1080))
cv2.imwrite(
"./shot_picture/customer" + str(qr_UUID) + "/AA_L_" + str(shot_count) + ".png",
resize_AAfin_L,
[cv2.IMWRITE_PNG_COMPRESSION, 9],
)
resize_AAfin_S = cv2.resize(resize_AAfin_L, (250, 300))
cv2.imwrite(
"./shot_picture/customer" + str(qr_UUID) + "/AA_S_" + str(shot_count) + ".png",
resize_AAfin_S,
[cv2.IMWRITE_PNG_COMPRESSION, 9],
)
def keying(capframe): # グリーンバック合成処理
shotframe = cv2.cvtColor(capframe, cv2.COLOR_BGR2RGB)
shotframe = cv2.resize(shotframe, (1920, 1080))
human_mask = remove(shotframe)
resize_human_mask_L = human_mask[0:1080, 510:1410]
cv2.imwrite(
"./shot_picture/customer"
+ str(qr_UUID)
+ "/comp_L_"
+ str(shot_count)
+ "_temp.png",
resize_human_mask_L,
[cv2.IMWRITE_PNG_COMPRESSION, 9],
)
resize_human_mask_S = cv2.resize(resize_human_mask_L, (250, 300))
cv2.imwrite(
"./shot_picture/customer"
+ str(qr_UUID)
+ "/comp_S_"
+ str(shot_count)
+ "_temp.png",
resize_human_mask_S,
[cv2.IMWRITE_PNG_COMPRESSION, 9],
)
def image_processing(capframe):
# ------AA / keying------#
keying(capframe)
AAFrame()
# -------------------------------------------- #
最大の反省ポイント。
afterでループさせて再描画はよかったが、これらがずっと回り続けているのがよくない。絶対にafter_cancel()を使うべきだった。また、マルチスレッドにして描画と画像処理を分けるべき。
※解決しなかったバグとしてはQRコードの判別部分で何度かエラーを吐き、カメラ映像が描画されないという症状があった。「data = detector.detectAndDecode(capframe)」これがよくないみたい。
# 描画関数-------------------------------------- #
def frame1_2_GUI():
global time, qr_UUID, qrreadFlag
global data
if scene_num == 1:
canvas1_2.delete("all") # キャッシュ処理
canvas1_2.create_image(420, 375, image=bg_2)
ret, capframe = capture.read()
capframe = cv2.cvtColor(capframe, cv2.COLOR_BGR2RGB)
if ret == True:
# QRコードを認識
data = detector.detectAndDecode(capframe)
if data != None:
qr_UUID = data[0] # https://tekken.work/art-market/[UUID]/
qr_UUID = qr_UUID.replace("https://tekken.work/art-market/", "")
qr_UUID = qr_UUID.replace("/", "")
if qr_UUID in UUID_list:
if qrreadFlag == False:
is_dir = os.path.exists("shot_picture/customer" + str(qr_UUID))
if is_dir == False: # 二回目を弾くため
start_shot.play()
show_scene2()
os.mkdir(
"shot_picture/customer" + str(qr_UUID)
) # 撮影データ補完ファイル作成
qrreadFlag = True
frame1_2.photo = PIL.ImageTk.PhotoImage(image=PIL.Image.fromarray(capframe))
canvas1_2.create_image(-246, 50, image=frame1_2.photo, anchor=tkinter.NW)
frame1_2.after(50, frame1_2_GUI) # ディレイ・繰り返し処理
def frame2_1_GUI():
global time, shot_count, scene_num, animation, soundFlag
canvas2_1.delete("all") # キャッシュ処理
canvas2_1.create_image(270, 375, image=bg_1)
if scene_num == 3:
if shot_count == 0:
canvas2_1.create_image(295, 150, image=countPic1)
if animation % 3 == 0:
canvas2_1.create_image(145 + 150, 250 + 175, image=samplepose1_1)
if animation % 3 == 1:
canvas2_1.create_image(145 + 150, 250 + 175, image=samplepose1_2)
if animation % 3 == 2:
canvas2_1.create_image(145 + 150, 250 + 175, image=samplepose1_3)
if shot_count == 1:
canvas2_1.create_image(295, 150, image=countPic2)
if animation % 3 == 0:
canvas2_1.create_image(145 + 150, 250 + 175, image=samplepose2_1)
if animation % 3 == 1:
canvas2_1.create_image(145 + 150, 250 + 175, image=samplepose2_2)
if animation % 3 == 2:
canvas2_1.create_image(145 + 150, 250 + 175, image=samplepose2_3)
if shot_count == 2:
canvas2_1.create_image(295, 150, image=countPic3)
canvas2_1.create_image(145 + 150, 250 + 175, image=samplepose3_1)
animation += 1
frame1.after(500, frame2_1_GUI) # ディレイ・繰り返し処理
def frame2_2_GUI():
global time
if scene_num == 2 or scene_num == 3:
canvas2_2.delete("all") # キャッシュ処理
canvas2_2.create_image(420, 375, image=bg_2)
ret, capframe = capture.read()
capframe = cv2.cvtColor(capframe, cv2.COLOR_BGR2RGB)
capframe = cv2.flip(capframe, 1)
frame2.photo = PIL.ImageTk.PhotoImage(image=PIL.Image.fromarray(capframe))
canvas2_2.create_image(-246, 50, image=frame2.photo, anchor=tkinter.NW)
if time > scene2_wait:
canvas2_2.create_image(420, 400, image=guide)
canvas2_2.create_image(420, 400, image=angle_frame)
if time > scene2_wait + 3: # [+3]は最初の余裕分の排除のため
if (time - (scene2_wait + (shot_time - 3))) % shot_time == 0:
canvas2_2.create_image(420, 400, image=camera_count3)
if (time - (scene2_wait + (shot_time - 2))) % shot_time == 0:
canvas2_2.create_image(420, 400, image=camera_count2)
if (time - (scene2_wait + (shot_time - 1))) % shot_time == 0:
canvas2_2.create_image(420, 400, image=camera_count1)
if (time - (scene2_wait + shot_time)) % shot_time == 0:
canvas2_2.create_image(420, 400, image=camera_count0)
if (
(time - (scene2_wait + (shot_time + 1))) % shot_time == 0
or (time - (scene2_wait + (shot_time + 2))) % shot_time == 0
or (time - (scene2_wait + (shot_time + 3))) % shot_time == 0
): # 3s処理分の余裕を持たせる
canvas2_2.create_image(420, 400, image=camera_loading)
if time > (scene2_wait + 1):
if (time - (scene2_wait + 1)) % shot_time == 0:
image_processing(capframe)
frame2.after(10, frame2_2_GUI) # ディレイ・繰り返し処理 #最適なループ時間を検証中
def frame2_4_GUI(): # ループさせなくても毎回読み込めばいけるのでは、またキャッシュ処理がなくても問題なさそう
global notice_2, slot1_AF, slot2_AF, slot3_AF, slot4_AF, slot5_AF, slot6_AF
global time
if scene_num == 2:
canvas2_4.delete("all") # キャッシュ処理
canvas2_4.create_image(960, 165, image=bg4_slot)
road_picture(0)
canvas2_4.create_image(960, 165, image=notice_2)
if scene_num == 3:
if time >= (scene2_wait) and time < (scene2_wait + (shot_time + 1)):
canvas2_4.delete("all") # キャッシュ処理
canvas2_4.create_image(960, 165, image=bg4_slot)
if time == scene2_wait + shot_time + 3:
canvas2_4.delete("all") # キャッシュ処理
canvas2_4.create_image(960, 165, image=bg4_slot)
road_picture(2)
canvas2_4.create_image(60 + 125, 165, image=slot1_AF)
canvas2_4.create_image(370 + 125, 165, image=slot2_AF)
if time == scene2_wait + (shot_time * 2) + 3:
canvas2_4.delete("all") # キャッシュ処理
canvas2_4.create_image(960, 165, image=bg4_slot)
road_picture(3)
canvas2_4.create_image(60 + 125, 165, image=slot1_AF)
canvas2_4.create_image(370 + 125, 165, image=slot2_AF)
canvas2_4.create_image(680 + 125, 165, image=slot3_AF)
canvas2_4.create_image(990 + 125, 165, image=slot4_AF)
if time == scene2_wait + (shot_time * 3) + 3:
canvas2_4.delete("all") # キャッシュ処理
canvas2_4.create_image(960, 165, image=bg4_slot)
road_picture(4)
canvas2_4.create_image(60 + 125, 165, image=slot1_AF)
canvas2_4.create_image(370 + 125, 165, image=slot2_AF)
canvas2_4.create_image(680 + 125, 165, image=slot3_AF)
canvas2_4.create_image(990 + 125, 165, image=slot4_AF)
canvas2_4.create_image(1300 + 125, 165, image=slot5_AF)
canvas2_4.create_image(1610 + 125, 165, image=slot6_AF)
frame4.after(500, frame2_4_GUI) # ディレイ・繰り返し処理
# -------------------------------------------- #
画面構成。初めてでわからないことだらけだったが、こんなに多重構造にするのは果たしてよかったのか。
if __name__ == "__main__":
root = tkinter.Tk() # この下に画面構成を記述
pygame.init()
# -------------------------------------------- #
root.title("プリクラ") # 画面タイトル設定
root.geometry("1920x1080") # 画面サイズ設定
root.resizable(False, False) # リサイズ不可に設定
root.attributes("-fullscreen", True) # 画面最大化
# rootメインウィンドウのグリッドを 1x1 にする
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
# -------------------------------------------- #
# -------------------------------------------- #
time = 0 # タイマー
detector = cv2.QRCodeDetector()
with open("UUID.csv", encoding="utf-8-sig") as f:
UUID_list = f.readlines()
UUID_list = [line.strip() for line in UUID_list] # 改行を削除
scene_num = 1 # シーン番号
shot_count = 0 # 撮影枚数カウント
scene2_wait = 8 # 注意事項の表示時間
shot_time = 15 # 撮影にかかる時間(scene_waitの値以上 and 3s分の余裕を持たせたい)
animation = 0
qrreadFlag = False
soundFlag = [0, False]
colorset = "#@$&/?(*)=~^:,. " #AA用文字セット
bg_1 = tk.PhotoImage(file="bg_1.png")
bg_2 = tk.PhotoImage(file="bg_2.png")
bg_3 = tk.PhotoImage(file="bg_3.png")
bg4_slot = tk.PhotoImage(file="bg4_slot.png")
# -------------------------------------------- #
# -------------------------------------------- #
QRcodeRead = pygame.mixer.Sound("QRcodeRead.wav")
start_shot = pygame.mixer.Sound("start_shot.wav")
position_explanation = pygame.mixer.Sound("position_explanation.wav")
pose1 = pygame.mixer.Sound("pose1.wav")
pose2 = pygame.mixer.Sound("pose2.wav")
pose3 = pygame.mixer.Sound("pose3.wav")
count1 = pygame.mixer.Sound("count1.wav")
count2 = pygame.mixer.Sound("count2.wav")
count3 = pygame.mixer.Sound("count3.wav")
shutter = pygame.mixer.Sound("shutter.wav")
rakugaki_move = pygame.mixer.Sound("rakugaki_move.wav")
# -------------------------------------------- #
# -------------------------------------------- #
capture = cv2.VideoCapture(0)
capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc("H", "2", "6", "4"))
capture.set(cv2.CAP_PROP_FPS, 30)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1244)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 700)
# -------------------------------------------- #
# ------------------ Scene1 ------------------ #
scene1 = tk.Frame(root, width=1920, height=1080, bg="white")
scene1.grid(row=0, column=0, sticky="nsew")
scene1.propagate(False) # Frameサイズを固定
frame1_1 = tk.Frame(scene1, width=540, height=750)
frame1_2 = tk.Frame(scene1, width=840, height=750)
frame1_3 = tk.Frame(scene1, width=540, height=750)
frame1_4 = tk.Frame(scene1, width=1920, height=330)
frame1_1.propagate(False)
frame1_2.propagate(False)
frame1_3.propagate(False)
frame1_4.propagate(False)
frame1_1.grid(row=0, column=0)
frame1_2.grid(row=0, column=1)
frame1_3.grid(row=0, column=2)
frame1_4.grid(row=1, column=0, columnspan=3)
canvas1_1 = tk.Canvas(frame1_1, width=540, height=750, highlightthickness=0)
canvas1_2 = tk.Canvas(frame1_2, width=840, height=750, highlightthickness=0)
canvas1_3 = tk.Canvas(frame1_3, width=540, height=750, highlightthickness=0)
canvas1_4 = tk.Canvas(frame1_4, width=1920, height=330, highlightthickness=0)
canvas1_1.grid(row=0, column=0)
canvas1_2.grid(row=0, column=1)
canvas1_3.grid(row=0, column=2)
canvas1_4.grid(row=1, column=0, columnspan=3)
canvas1_1.create_image(270, 375, image=bg_1)
canvas1_3.create_image(270, 375, image=bg_3)
qrread = tk.PhotoImage(file="qrread.png")
canvas1_4.create_image(960, 165, image=qrread)
frame1_2_GUI()
# ------------------ Scene2 ------------------ #
scene2 = tk.Frame(root, width=1920, height=108)
scene2.grid(row=0, column=0, sticky="nsew")
scene2.propagate(False) # Frameサイズを固定
frame1 = tk.Frame(scene2, width=540, height=750)
frame2 = tk.Frame(scene2, width=840, height=750)
frame3 = tk.Frame(scene2, width=540, height=750)
frame4 = tk.Frame(scene2, width=1920, height=330)
frame1.propagate(False) # Frameサイズを固定
frame2.propagate(False)
frame3.propagate(False)
frame4.propagate(False)
frame1.grid(row=0, column=0) # Frameを配置(grid)
frame2.grid(row=0, column=1)
frame3.grid(row=0, column=2)
frame4.grid(row=1, column=0, columnspan=3)
# ----------- frame1 ----------- #
countPic1 = tk.PhotoImage(file="count1.png")
samplepose1_1 = tk.PhotoImage(file="samplepose1_1.png")
samplepose1_2 = tk.PhotoImage(file="samplepose1_2.png")
samplepose1_3 = tk.PhotoImage(file="samplepose1_3.png")
countPic2 = tk.PhotoImage(file="count2.png")
samplepose2_1 = tk.PhotoImage(file="samplepose2_1.png")
samplepose2_2 = tk.PhotoImage(file="samplepose2_2.png")
samplepose2_3 = tk.PhotoImage(file="samplepose2_3.png")
countPic3 = tk.PhotoImage(file="count3.png")
samplepose3_1 = tk.PhotoImage(file="samplepose3_1.png")
canvas2_1 = tk.Canvas(frame1, width=540, height=750, highlightthickness=0)
canvas2_1.grid(row=0, column=0)
# ----------- frame2 ----------- #
camera_count3 = tk.PhotoImage(file="camera_count3.png")
camera_count2 = tk.PhotoImage(file="camera_count2.png")
camera_count1 = tk.PhotoImage(file="camera_count1.png")
camera_count0 = tk.PhotoImage(file="camera_count0.png")
camera_loading = tk.PhotoImage(file="camera_loading.png")
guide = tk.PhotoImage(file="guide.png")
angle_frame = tk.PhotoImage(file="angle_frame.png")
canvas2_2 = tk.Canvas(frame2, width=840, height=750, highlightthickness=0)
canvas2_2.grid(row=0, column=1)
# ----------- frame3 ----------- #
canvas2_3 = tk.Canvas(frame3, width=540, height=750, highlightthickness=0)
canvas2_3.grid(row=0, column=2)
canvas2_3.create_image(270, 375, image=bg_3)
# ----------- frame4 ----------- #
canvas2_4 = tk.Canvas(frame4, width=1920, height=330, highlightthickness=0)
canvas2_4.grid(row=1, column=0, columnspan=3)
world_timer() # タイマースタート
frame2_2_GUI()
frame2_1_GUI()
frame2_4_GUI()
# ------------------ Scene3 ------------------ #
scene3 = tk.Frame(root, width=1920, height=1080)
scene3.grid(row=0, column=0, sticky="nsew")
scene3.propagate(False) # Frameサイズを固定
canvas3_1 = tk.Canvas(scene3, width=1920, height=1080, highlightthickness=0)
canvas3_1.pack(padx=0, pady=0)
scene3_1 = tk.PhotoImage(file="scene3_1.png")
canvas3_1.create_image(960, 540, image=scene3_1)
# -------------------------------------------- #
show_scene1()
root.mainloop()
ラクガキブース
ソースコード
使用したライブラリ一覧。
import tkinter as tk
import tkinter.ttk as ttk
import cv2
import numpy as np
import tkinter.filedialog
import PIL.ImageTk
import PIL.Image
import os
import pygame
import requests
import pyautogui
import random
from PIL import Image, ImageTk
撮影ブース同様です。
# 管理関数 ------------------------------------- #
def world_timer(): #時間管理
global time,loadFlag
time += 1
if scene_num == 2:
if loadFlag == False:
if time == 2:
time_explanation.play()
if time == 7:
select_explanation.play()
if time == 12:
start_call.play()
time = 0
loadFlag = True
if loadFlag == True:
if time_limit-time==10:
rest10.play()
if time_limit-time==5:
rest5.play()
if time_limit-time==2:
rest3.play()
if time_limit-time==1:
rest2.play()
if time_limit-time==0:
rest1.play()
if time_limit-time==-1:
show_scene3()
if scene_num == 3:
if time_limit-time==-1:
canvas3_1.create_image(960,540,image=scene3_1)
DL_explanation.play()
if time_limit-time==-8:
canvas3_1.create_image(960,540,image=scene3_2)
printing_explanation.play()
if time_limit-time==-20:
show_scene1()
frame1.after(1000,world_timer)
def road_picture():
global data
global comp,comp_tk,aa,aa_tk
global result_tk_out,result_tk,mask
global comp_select,comp_select_off
comp = [None,None,None]
comp_tk = [None,None,None]
aa = [None,None,None]
aa_tk = [None,None,None]
result_tk_out = [None,None,None]
result_tk = [None,None,None]
mask = [None,None,None]
comp_select = [None,None,None]
comp_select_off = [None,None,None]
ImageTransfer.download_image(qr_UUID,'AA_L_1.png')
ImageTransfer.download_image(qr_UUID,'AA_L_2.png')
ImageTransfer.download_image(qr_UUID,'AA_L_3.png')
ImageTransfer.download_image(qr_UUID,'comp_L_1_temp.png')
ImageTransfer.download_image(qr_UUID,'comp_L_2_temp.png')
ImageTransfer.download_image(qr_UUID,'comp_L_3_temp.png')
aa[0] = cv2.imread("AA_L_1.png")
aa[1] = cv2.imread("AA_L_2.png")
aa[2] = cv2.imread("AA_L_3.png")
comp[0] = cv2.imread("comp_L_1_temp.png")
comp[1] = cv2.imread("comp_L_2_temp.png")
comp[2] = cv2.imread("comp_L_3_temp.png")
for i in range(3):
# ラクガキ用(frame2/4)
comp[i] = cv2.resize(comp[i], (625, 750))
comp_tk[i] = cv2_to_tk(comp[i])
aa[i] = cv2.resize(aa[i], (625, 750))
aa_tk[i] = cv2_to_tk(aa[i])
result_tk_out[i] = aa_tk[i]
mask[i] = np.zeros_like(comp[i]) #マスク画像生成
# セレクト写真用(frame1)
comp_select[i] = cv2.resize(comp[i], (165, 198))
comp_select_off[i] = cv2.cvtColor(comp_select[i],cv2.COLOR_BGR2GRAY)
comp_select[i] = cv2_to_tk(comp_select[i])
comp_select_off[i] = cv2_to_tk(comp_select_off[i])
# -------------------------------------------- #
# 変換関数 ------------------------------------ #
def cv2_to_tk(cv2_image):
cv2_image = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB) # imreadはBGRなのでRGBに変換
PIL_image = Image.fromarray(cv2_image) # RGBからPILフォーマットへ変換
tk_image = ImageTk.PhotoImage(PIL_image) # ImageTkフォーマットへ変換
return tk_image
# -------------------------------------------- #
# シーンチェンジ関数 --------------------------- #
def show_scene1():
global scene_num,soundFlag,upload_Flag
scene_num = 1
soundFlag[1] = False
upload_Flag = False
scene1.tkraise()
def show_scene2():
global time,scene_num,loadFlag
global select_num_R,select_num_L
global brush_num,brush_widgh,stamp_num,stamp_list,stamp_count,stampselect_Flag_R,stampselect_Flag_L,pen_or_stamp
#初期化
time = 0
scene_num = 2
loadFlag = False
select_num_R = 0
select_num_L = 1
brush_num = 0
brush_widgh = 70
stamp_num = 0
stamp_list = []
stamp_count = 0
stampselect_Flag_R = False
stampselect_Flag_L = False
pen_or_stamp = 0 #0:ペン 1:スタンプ
scene2.tkraise()
def show_scene3():
global scene_num,result_tk,qr_UUID
scene_num = 3
scene3.tkraise()
cv2.imwrite("result_L_1.png", result_tk[0])
cv2.imwrite("result_L_2.png", result_tk[1])
cv2.imwrite("result_L_3.png", result_tk[2])
picRandom = random.randrange(2)
if picRandom == 0:
base = Image.open("print_bg1_1.png") #1日目
#base = Image.open("print_bg1_2.png") #2日目
#base = Image.open("print_bg1_3.png") #3日目
if picRandom == 1:
base = Image.open("print_bg2_1.png") #1日目
#base = Image.open("print_bg2_2.png") #2日目
#base = Image.open("print_bg2_3.png") #3日目
stamp1_img_PIL = Image.open("icon_stamp1.png")
stamp2_img_PIL = Image.open("icon_stamp2.png")
stamp3_img_PIL = Image.open("icon_stamp3.png")
stamp4_img_PIL = Image.open("icon_stamp4.png")
# base.paste(logo, (0, 0))
base.paste(logo, (0, 0), logo)
base.save(out_path)
#スタンプ描画
'''
for i in range(stamp_count): #stamp_list[stamp_num(0),sx(1),sy(2),select_num(3)]
if stamp_list[i][3]==0:
if stamp_list[i][0]==0:
canvas2_2.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp1_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==1:
canvas2_2.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp2_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==2:
canvas2_2.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp3_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==3:
canvas2_2.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp4_img, anchor='nw',tag="stamp_comp")
'''
ImageTransfer.upload_image(qr_UUID, "./result_L_1.png")
ImageTransfer.upload_image(qr_UUID, "./result_L_2.png")
ImageTransfer.upload_image(qr_UUID, "./result_L_3.png")
# -------------------------------------------- #
rootでマウスの動作を検知して「クリック」「ドラック」の二種類から描画する形をとったが、あまり綺麗にラクガキする体験を提供できなかった。重くなると露骨に直線になってしまうし、文字を書こうとするとなかなか難しくなってしまったのは反省点です。この処理はうまくやる方法を現在も模索中です。
# マウス検知関数 ------------------------------ #
def on_pressed(event,lr):
global sx,sy
global comp,comp_tk,aa,aa_tk
global result_tk,result_tk_out,mask
global stamp_list,stamp_count
if 87.5<event.x and event.x<712.5 and 65<event.y and event.y<815:
sx = event.x
sy = event.y
if pen_or_stamp == 0:
if lr == 0:
if brush_num == 0:
color = (85,85,85)
color = (85,85,85)
if brush_num == 1:
color = (255,255,255)
if brush_num == 2:
color = (63,105,39)
if brush_num == 3:
color = (0,0,0)
cv2.circle(mask[select_num_R],(int(sx-87.5),int(sy-65)),int(brush_widgh),color,thickness=-1)
result_tk[select_num_R] = addweight(comp[select_num_R],aa[select_num_R],mask[select_num_R])
result_tk_out[select_num_R] = cv2_to_tk(result_tk[select_num_R])
if lr == 1:
if brush_num == 0:
color = (85,85,85)
if brush_num == 1:
color = (255,255,255)
if brush_num == 2:
color = (63,105,39)
if brush_num == 3:
color = (0,0,0)
cv2.circle(mask[select_num_L],(int(sx-87.5),int(sy-65)),brush_widgh,color,thickness=-1)
result_tk[select_num_L] = addweight(comp[select_num_L],aa[select_num_L],mask[select_num_L])
result_tk_out[select_num_L] = cv2_to_tk(result_tk[select_num_L])
if pen_or_stamp == 1:
if lr == 0 : stamp_list.append([stamp_num,sx,sy,select_num_R])
if lr == 1 : stamp_list.append([stamp_num,sx,sy,select_num_L])
stamp_count+=1
if stamp_num == 0:
pyautogui.moveTo(900, 850) #連打回避用
if stamp_num == 1:
pyautogui.moveTo(1015, 850)
if stamp_num == 2:
pyautogui.moveTo(900, 985)
if stamp_num == 3:
pyautogui.moveTo(1015, 985)
def on_dragged(event,lr):
global sx,sy
global comp,comp_tk,aa,aa_tk
global result_tk,result_tk_out,mask
if pen_or_stamp == 0:
if lr == 0:
if brush_num == 0:
color = (85,85,85)
brush_widgh_line = int(brush_widgh*2)
if brush_num == 1:
color = (255,255,255)
brush_widgh_line = int(brush_widgh*2)
if brush_num == 2:
color = (63,105,39)
brush_widgh_line = int(brush_widgh*2)
if brush_num == 3:
color = (0,0,0)
brush_widgh_line = int(brush_widgh*2)
if 87.5<event.x and event.x<712.5 and 65<event.y and event.y<815:
cv2.line(mask[select_num_R], (int(sx-87.5), int(sy-65)), (int(event.x-87.5), int(event.y-65)), color, thickness=brush_widgh_line, lineType=cv2.LINE_AA)
result_tk[select_num_R] = addweight(comp[select_num_R],aa[select_num_R],mask[select_num_R])
result_tk_out[select_num_R] = cv2_to_tk(result_tk[select_num_R])
if lr == 1:
if brush_num == 0:
color = (85,85,85)
brush_widgh_line = int(brush_widgh*2)
if brush_num == 1:
color = (255,255,255)
brush_widgh_line = int(brush_widgh*2)
if brush_num == 2:
color = (63,105,39)
brush_widgh_line = int(brush_widgh*2)
if brush_num == 3:
color = (0,0,0)
brush_widgh_line = int(brush_widgh*2)
if 87.5<event.x and event.x<712.5 and 65<event.y and event.y<815:
cv2.line(mask[select_num_L], (int(sx-87.5), int(sy-65)), (int(event.x-87.5), int(event.y-65)), color, thickness=brush_widgh_line, lineType=cv2.LINE_AA)
result_tk[select_num_L] = addweight(comp[select_num_L],aa[select_num_L],mask[select_num_L])
result_tk_out[select_num_L] = cv2_to_tk(result_tk[select_num_L])
if 87.5<event.x and event.x<712.5 and 65<event.y and event.y<815:
sx = event.x
sy = event.y
def on_moved(event,lr):
global stamp_sx_L,stamp_sy_L,stamp_sx_R,stamp_sy_R,stampselect_Flag_R,stampselect_Flag_L
if lr == 0:
stamp_sx_R = event.x
stamp_sy_R = event.y
stampselect_Flag_R = True
stampselect_Flag_L = False
if lr == 1:
stamp_sx_L = event.x
stamp_sy_L = event.y
stampselect_Flag_R = False
stampselect_Flag_L = True
# -------------------------------------------- #
# ブラシ関数 ---------------------------------- #
def addweight(im1,im2,mask):
result_aa_pic = im2.copy()
mask = mask/255
indexForIm2 = np.where( mask == [0,0,0] )
indexForIm1 = np.where( mask == [1,1,1] )
indexForWeight = np.where( (mask != [0,0,0]) & (mask != [1,1,1]) )
result_aa_pic[ indexForIm1[0] ,indexForIm1[1] ] = im1[ indexForIm1[0] ,indexForIm1[1] ]
result_aa_pic[ indexForWeight[0] ,indexForWeight[1] ] = ( (1 - mask[ indexForWeight[0] ,indexForWeight[1] ]) * im2[ indexForWeight[0] ,indexForWeight[1] ]) + ( mask[ indexForWeight[0] ,indexForWeight[1] ] * im1[ indexForWeight[0] ,indexForWeight[1] ])
result_aa_pic[ indexForIm2[0] ,indexForIm2[1] ] = im2[ indexForIm2[0] ,indexForIm2[1]]
result_aa_pic = result_aa_pic.astype(np.uint8)
return result_aa_pic
def select1_R():
global select_num_R
if not select_num_L == 0:
select_img_reset_R()
select_num_R = 0
button_comp1_R = tk.Button(canvas2_1a, image = comp_select_off[0], compound="top", command=select1_R , relief=tk.FLAT).place(x = 80, y = 1, width = 160, height = 200)
def select2_R():
global select_num_R
if not select_num_L == 1:
select_img_reset_R()
select_num_R = 1
button_comp2_R = tk.Button(canvas2_1a, image = comp_select_off[1], compound="top", command=select2_R , relief=tk.FLAT).place(x = 320, y = 1, width = 160, height = 200)
def select3_R():
global select_num_R
if not select_num_L == 2:
select_img_reset_R()
select_num_R = 2
button_comp3_R = tk.Button(canvas2_1a, image = comp_select_off[2], compound="top", command=select3_R , relief=tk.FLAT).place(x = 560, y = 1, width = 160, height = 200)
def select1_L():
global select_num_L
if not select_num_R == 0:
select_img_reset_L()
select_num_L = 0
button_comp1_L = tk.Button(canvas2_1c, image = comp_select_off[0], compound="top", command=select1_L , relief=tk.FLAT).place(x = 140, y = 1, width = 160, height = 200)
def select2_L():
global select_num_L
if not select_num_R == 1:
select_img_reset_L()
select_num_L = 1
button_comp2_L = tk.Button(canvas2_1c, image = comp_select_off[1], compound="top", command=select2_L , relief=tk.FLAT).place(x = 380, y = 1, width = 160, height = 200)
def select3_L():
global select_num_L
if not select_num_R == 2:
select_img_reset_L()
select_num_L = 2
button_comp3_L = tk.Button(canvas2_1c, image = comp_select_off[2], compound="top", command=select3_L , relief=tk.FLAT).place(x = 620, y = 1, width = 160, height = 200)
def select_img_reset_R():
if select_num_R == 0:
button_comp1_R = tk.Button(canvas2_1a, image = comp_select[0], compound="top", command=select1_R , relief=tk.FLAT).place(x = 80, y = 1, width = 160, height = 200)
if select_num_R == 1:
button_comp2_R = tk.Button(canvas2_1a, image = comp_select[1], compound="top", command=select2_R , relief=tk.FLAT).place(x = 320, y = 1, width = 160, height = 200)
if select_num_R == 2:
button_comp3_R = tk.Button(canvas2_1a, image = comp_select[2], compound="top", command=select3_R , relief=tk.FLAT).place(x = 560, y = 1, width = 160, height = 200)
def select_img_reset_L():
if select_num_L == 0:
button_comp1_L = tk.Button(canvas2_1c, image = comp_select[0], compound="top", command=select1_L , relief=tk.FLAT).place(x = 140, y = 1, width = 160, height = 200)
if select_num_L == 1:
button_comp2_L = tk.Button(canvas2_1c, image = comp_select[1], compound="top", command=select2_L , relief=tk.FLAT).place(x = 380, y = 1, width = 160, height = 200)
if select_num_L == 2:
button_comp3_L = tk.Button(canvas2_1c, image = comp_select[2], compound="top", command=select3_L , relief=tk.FLAT).place(x = 620, y = 1, width = 160, height = 200)
def brush1():
brush_img_reset()
global brush_num,stampselect_Flag_R,stampselect_Flag_L,pen_or_stamp
pen_or_stamp = 0
brush_num = 0
stampselect_Flag_R = False
stampselect_Flag_L = False
button_icon1 = tk.Button(canvas2_3, image=icon1_off, compound="top", command=brush1, relief=tk.RAISED)
button_icon1.place(x = 30, y = 30)
def brush2():
brush_img_reset()
global brush_num,stampselect_Flag_R,stampselect_Flag_L,pen_or_stamp
pen_or_stamp = 0
brush_num = 1
stampselect_Flag_R = False
stampselect_Flag_L = False
button_icon2 = tk.Button(canvas2_3, image=icon2_off, compound="top", command=brush2, relief=tk.RAISED)
button_icon2.place(x = 30, y = 140)
def brush3():
brush_img_reset()
global brush_num,stampselect_Flag_R,stampselect_Flag_L,pen_or_stamp
pen_or_stamp = 0
brush_num = 2
stampselect_Flag_R = False
stampselect_Flag_L = False
button_icon3 = tk.Button(canvas2_3, image=icon3_off, compound="top", command=brush2, relief=tk.RAISED)
button_icon3.place(x = 30, y = 250)
def eraser1():
brush_img_reset()
global brush_num,stampselect_Flag_R,stampselect_Flag_L,pen_or_stamp
pen_or_stamp = 0
brush_num = 3
stampselect_Flag_R = False
stampselect_Flag_L = False
button_icon4 = tk.Button(canvas2_3, image=icon4_off, compound="top", command=eraser1, relief=tk.RAISED)
button_icon4.place(x = 30, y = 360)
def brush_img_reset():
if brush_num == 0:
button_icon1 = tk.Button(canvas2_3, image=icon1, compound="top", command=brush1, relief=tk.RAISED)
button_icon1.place(x = 30, y = 30)
if brush_num == 1:
button_icon2 = tk.Button(canvas2_3, image=icon2, compound="top", command=brush2, relief=tk.RAISED)
button_icon2.place(x = 30, y = 140)
if brush_num == 2:
button_icon3 = tk.Button(canvas2_3, image=icon3, compound="top", command=brush3, relief=tk.RAISED)
button_icon3.place(x = 30, y = 250)
if brush_num == 3:
button_icon4 = tk.Button(canvas2_3, image=icon4, compound="top", command=eraser1, relief=tk.RAISED)
button_icon4.place(x = 30, y = 360)
if stamp_num == 0:
button_stamp1 = tk.Button(canvas2_3, image=icon_stamp1, compound="top", command=stamp1, relief=tk.RAISED)
button_stamp1.place(x = 50, y = 590)
if stamp_num == 1:
button_stamp2 = tk.Button(canvas2_3, image=icon_stamp2, compound="top", command=stamp2, relief=tk.RAISED)
button_stamp2.place(x = 165, y = 590)
if stamp_num == 2:
button_stamp3 = tk.Button(canvas2_3, image=icon_stamp3, compound="top", command=stamp3, relief=tk.RAISED)
button_stamp3.place(x = 50, y = 725)
if stamp_num == 3:
button_stamp4 = tk.Button(canvas2_3, image=icon_stamp4, compound="top", command=stamp4, relief=tk.RAISED)
button_stamp4.place(x = 165, y = 725)
def brush_widgh4_setting():
brush_widgh_img_reset()
global brush_widgh
brush_widgh = 70
button_brush_widgh4 = tk.Button(canvas2_3, image=brush_widgh4_off, compound="top", command=brush_widgh4_setting, relief=tk.RAISED)
button_brush_widgh4.place(x = 185, y = 30)
def brush_widgh3_setting():
brush_widgh_img_reset()
global brush_widgh
brush_widgh = 50
button_brush_widgh3 = tk.Button(canvas2_3, image=brush_widgh3_off, compound="top", command=brush_widgh3_setting, relief=tk.RAISED)
button_brush_widgh3.place(x = 185, y = 140)
def brush_widgh2_setting():
brush_widgh_img_reset()
global brush_widgh
brush_widgh = 30
button_brush_widgh2 = tk.Button(canvas2_3, image=brush_widgh2_off, compound="top", command=brush_widgh2_setting, relief=tk.RAISED)
button_brush_widgh2.place(x = 185, y = 250)
def brush_widgh1_setting():
brush_widgh_img_reset()
global brush_widgh
brush_widgh = 10
button_brush_widgh1 = tk.Button(canvas2_3, image=brush_widgh1_off, compound="top", command=brush_widgh1_setting, relief=tk.RAISED)
button_brush_widgh1.place(x = 185, y = 360)
def brush_widgh_img_reset():
if brush_widgh == 70:
button_brush_widgh4 = tk.Button(canvas2_3, image=brush_widgh4, compound="top", command=brush_widgh4_setting, relief=tk.RAISED)
button_brush_widgh4.place(x = 185, y = 30)
if brush_widgh == 50:
button_brush_widgh3 = tk.Button(canvas2_3, image=brush_widgh3, compound="top", command=brush_widgh3_setting, relief=tk.RAISED)
button_brush_widgh3.place(x = 185, y = 140)
if brush_widgh == 30:
button_brush_widgh2 = tk.Button(canvas2_3, image=brush_widgh2, compound="top", command=brush_widgh2_setting, relief=tk.RAISED)
button_brush_widgh2.place(x = 185, y = 250)
if brush_widgh == 10:
button_brush_widgh1 = tk.Button(canvas2_3, image=brush_widgh1, compound="top", command=brush_widgh1_setting, relief=tk.RAISED)
button_brush_widgh1.place(x = 185, y = 360)
def stamp1():
stamp_img_reset()
global stamp_num,pen_or_stamp,stamp_sx_L,stamp_sy_L,stamp_sx_R,stamp_sy_R
pen_or_stamp = 1
stamp_num = 0
stamp_sx_L = -100
stamp_sy_L = -100
stamp_sx_R = -100
stamp_sy_R = -100
button_stamp1 = tk.Button(canvas2_3, image=icon_stamp1_off, compound="top", command=stamp1, relief=tk.RAISED)
button_stamp1.place(x = 50, y = 590)
def stamp2():
stamp_img_reset()
global stamp_num,pen_or_stamp,stamp_sx_L,stamp_sy_L,stamp_sx_R,stamp_sy_R
pen_or_stamp = 1
stamp_num = 1
stamp_sx_L = -100
stamp_sy_L = -100
stamp_sx_R = -100
stamp_sy_R = -100
button_stamp2 = tk.Button(canvas2_3, image=icon_stamp2_off, compound="top", command=stamp2, relief=tk.RAISED)
button_stamp2.place(x = 165, y = 590)
def stamp3():
stamp_img_reset()
global stamp_num,pen_or_stamp,stamp_sx_L,stamp_sy_L,stamp_sx_R,stamp_sy_R
pen_or_stamp = 1
stamp_num = 2
stamp_sx_L = -100
stamp_sy_L = -100
stamp_sx_R = -100
stamp_sy_R = -100
button_stamp3 = tk.Button(canvas2_3, image=icon_stamp3_off, compound="top", command=stamp3, relief=tk.RAISED)
button_stamp3.place(x = 50, y = 725)
def stamp4():
stamp_img_reset()
global stamp_num,pen_or_stamp,stamp_sx_L,stamp_sy_L,stamp_sx_R,stamp_sy_R
pen_or_stamp = 1
stamp_num = 3
stamp_sx_L = -100
stamp_sy_L = -100
stamp_sx_R = -100
stamp_sy_R = -100
button_stamp4 = tk.Button(canvas2_3, image=icon_stamp4_off, compound="top", command=stamp4, relief=tk.RAISED)
button_stamp4.place(x = 165, y = 725)
def stamp_img_reset():
if stamp_num == 0:
button_stamp1 = tk.Button(canvas2_3, image=icon_stamp1, compound="top", command=stamp1, relief=tk.RAISED)
button_stamp1.place(x = 50, y = 590)
if stamp_num == 1:
button_stamp2 = tk.Button(canvas2_3, image=icon_stamp2, compound="top", command=stamp2, relief=tk.RAISED)
button_stamp2.place(x = 165, y = 590)
if stamp_num == 2:
button_stamp3 = tk.Button(canvas2_3, image=icon_stamp3, compound="top", command=stamp3, relief=tk.RAISED)
button_stamp3.place(x = 50, y = 725)
if stamp_num == 3:
button_stamp4 = tk.Button(canvas2_3, image=icon_stamp4, compound="top", command=stamp4, relief=tk.RAISED)
button_stamp4.place(x = 165, y = 725)
if brush_num == 0:
button_icon1 = tk.Button(canvas2_3, image=icon1, compound="top", command=brush1, relief=tk.RAISED)
button_icon1.place(x = 30, y = 30)
if brush_num == 1:
button_icon2 = tk.Button(canvas2_3, image=icon2, compound="top", command=brush2, relief=tk.RAISED)
button_icon2.place(x = 30, y = 140)
if brush_num == 2:
button_icon3 = tk.Button(canvas2_3, image=icon3, compound="top", command=brush3, relief=tk.RAISED)
button_icon3.place(x = 30, y = 250)
if brush_num == 3:
button_icon4 = tk.Button(canvas2_3, image=icon4, compound="top", command=eraser1, relief=tk.RAISED)
button_icon4.place(x = 30, y = 360)
# -------------------------------------------- #
※※※
撮影ブースと同様。
# 描画関数 ------------------------------------ #
def frame1_2_GUI():
global time,soundFlag,qr_UUID
if scene_num == 1:
canvas1_2.delete('all') #キャッシュ処理
canvas1_2.create_image(420,375,image=bg_2)
ret, capframe = capture.read()
capframe = cv2.cvtColor(capframe, cv2.COLOR_BGR2RGB)
if ret == True:
if time%10==0 and soundFlag[1]==False:
QRcodeRead.play()
soundFlag[0] = time
soundFlag[1] = True
if time==int(soundFlag[0]+1):
soundFlag[1] = False
# QRコードを認識
data = detector.detectAndDecode(capframe)
qr_UUID = data[0] #https://tekken.work/art-market/[UUID]/
qr_UUID = qr_UUID.replace('https://tekken.work/art-market/', '')
qr_UUID = qr_UUID.replace('/', '')
if qr_UUID in UUID_list:
road_picture() #画像のダウンロードおよびセットアップ
frame1ac_GUI()
frame2_GUI()
frame4_GUI()
show_scene2()
frame1_2.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(capframe))
canvas1_2.create_image(-246,50, image=frame1_2.photo, anchor = tkinter.NW)
frame1_2.after(33, frame1_2_GUI) #ディレイ・繰り返し処理 #最適なループ時間を検証中
def frame1b_GUI():
canvas2_1b.delete('all')
canvas2_1b.create_image(100,100,image=bg_1_b)
canvas2_1b.create_oval(10, 10, 190, 190, width=10, outline="#000000")
if loadFlag == False:
canvas2_1b.create_text(100,100,text='60',font=("Menlo",80),fill="black",anchor="c") #フォント指定注意
if loadFlag == True:
#canvas2_1b.create_image(130,100,image='timer_pic'+str(int((time_limit-time)/10))) #10の位
#canvas2_1b.create_image(70,100,image='timer_pic'+str((time_limit-time)%10)) #1の位
if time_limit-time==10:
canvas2_1b.create_text(100,100,text=time_limit-time,font=("Menlo",80),fill="red",anchor="c") #フォント指定注意
elif time_limit - time < 10:
canvas2_1b.create_text(100,100,text=time_limit-time,font=("Menlo",100),fill="red",anchor="c")
else:
canvas2_1b.create_text(100,100,text=time_limit-time,font=("Menlo",80),fill="black",anchor="c")
frame2.after(500, frame1b_GUI) #ディレイ・繰り返し処理
def frame1ac_GUI():
# 各種ウィジェットの作成
button_comp1_R = tk.Button(canvas2_1a, image = comp_select_off[0], compound="top", command=select1_R , relief=tk.FLAT)
button_comp2_R = tk.Button(canvas2_1a, image = comp_select[1], compound="top", command=select2_R , relief=tk.FLAT)
button_comp3_R = tk.Button(canvas2_1a, image = comp_select[2], compound="top", command=select3_R , relief=tk.FLAT)
button_comp1_R.place(x = 80, y = 1, width = 160, height = 200)
button_comp2_R.place(x = 320, y = 1, width = 160, height = 200)
button_comp3_R.place(x = 560, y = 1, width = 160, height = 200)
button_comp1_L = tk.Button(canvas2_1c, image = comp_select[0], compound="top", command=select1_L , relief=tk.FLAT)
button_comp2_L = tk.Button(canvas2_1c, image = comp_select_off[1], compound="top", command=select2_L , relief=tk.FLAT)
button_comp3_L = tk.Button(canvas2_1c, image = comp_select[2], compound="top", command=select3_L , relief=tk.FLAT)
button_comp1_L.place(x = 140, y = 1, width = 160, height = 200)
button_comp2_L.place(x = 380, y = 1, width = 160, height = 200)
button_comp3_L.place(x = 620, y = 1, width = 160, height = 200)
def frame2_GUI():
global select_num_R,result_tk,result_tk_out,stamp_sx_R,stamp_sy_R
global upload_Flag
canvas2_2.delete('img')
canvas2_2.create_image(400,440,image=bg_2,tag="BG")
canvas2_2.create_image(87.5, 65, image=result_tk_out[select_num_R], anchor='nw',tag="img")
if stampselect_Flag_R == True and pen_or_stamp == 1:
if stamp_num == 0:
canvas2_2.create_image(stamp_sx_R-38, stamp_sy_R-38, image=stamp1_img, anchor='nw',tag="stamp")
if stamp_num == 1:
canvas2_2.create_image(stamp_sx_R-38, stamp_sy_R-38, image=stamp2_img, anchor='nw',tag="stamp")
if stamp_num == 2:
canvas2_2.create_image(stamp_sx_R-38, stamp_sy_R-38, image=stamp3_img, anchor='nw',tag="stamp")
if stamp_num == 3:
canvas2_2.create_image(stamp_sx_R-38, stamp_sy_R-38, image=stamp4_img, anchor='nw',tag="stamp")
for i in range(stamp_count): #stamp_list[stamp_num(0),sx(1),sy(2),select_num(3)]
if stamp_list[i][3]==select_num_R:
if stamp_list[i][0]==0:
canvas2_2.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp1_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==1:
canvas2_2.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp2_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==2:
canvas2_2.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp3_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==3:
canvas2_2.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp4_img, anchor='nw',tag="stamp_comp")
frame2.after(33, frame2_GUI) #ディレイ・繰り返し処理
def frame4_GUI():
global select_num_L,result_tk,result_tk_out,stamp_sx_L,stamp_sy_L
canvas2_4.delete('img')
canvas2_4.create_image(400,440,image=bg_4,tag="BG")
canvas2_4.create_image(87.5, 65, image=result_tk_out[select_num_L], anchor='nw',tag="img")
if stampselect_Flag_L == True and pen_or_stamp == 1:
if stamp_num == 0:
canvas2_4.create_image(stamp_sx_L-38, stamp_sy_L-38, image=stamp1_img, anchor='nw',tag="stamp")
if stamp_num == 1:
canvas2_4.create_image(stamp_sx_L-38, stamp_sy_L-38, image=stamp2_img, anchor='nw',tag="stamp")
if stamp_num == 2:
canvas2_4.create_image(stamp_sx_L-38, stamp_sy_L-38, image=stamp3_img, anchor='nw',tag="stamp")
if stamp_num == 3:
canvas2_4.create_image(stamp_sx_L-38, stamp_sy_L-38, image=stamp4_img, anchor='nw',tag="stamp")
for i in range(stamp_count): #stamp_list[stamp_num(0),sx(1),sy(2),select_num(3)]
if stamp_list[i][3]==select_num_L:
if stamp_list[i][0]==0:
canvas2_4.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp1_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==1:
canvas2_4.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp2_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==2:
canvas2_4.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp3_img, anchor='nw',tag="stamp_comp")
if stamp_list[i][0]==3:
canvas2_4.create_image(stamp_list[i][1]-38, stamp_list[i][2]-38, image=stamp4_img, anchor='nw',tag="stamp_comp")
frame4.after(33, frame4_GUI) #ディレイ・繰り返し処理
# -------------------------------------------- #
撮影ブースと同様です。
if __name__ == "__main__":
root = tkinter.Tk() # この下に画面構成を記述
pygame.init() #初期化
# -------------------------------------------- #
root.title('ラクガキ') #画面タイトル設定
root.geometry('1920x1080') #画面サイズ設定
root.resizable(False, False) #リサイズ不可に設定
root.attributes('-fullscreen', True) #画面最大化
# rootメインウィンドウのグリッドを 1x1 にする
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
# -------------------------------------------- #
scene_num = 1 #シーン番号
time = 0
time_limit = 15
detector = cv2.QRCodeDetector()
with open('UUID.csv', encoding = 'utf-8-sig') as f:
UUID_list = f.readlines()
UUID_list = [ line.strip() for line in UUID_list] #改行を削除
loadFlag = False #Scene1>2へのロード待機用
select_num_R = 0
select_num_L = 1
brush_num = 0
brush_widgh = 70
stamp_num = 0
stamp_list = [[0,0,0,0]]
stamp_count = 0
stamp_redo = [0,0,0,0] #redo用の保管
stampselect_Flag_R = False
stampselect_Flag_L = False
pen_or_stamp = 0 #0:ペン 1:スタンプ
stamp1_img = tk.PhotoImage(file="stamp1.png")
stamp2_img = tk.PhotoImage(file="stamp2.png")
stamp3_img = tk.PhotoImage(file="stamp3.png")
stamp4_img = tk.PhotoImage(file="stamp4.png")
bg_1 = tk.PhotoImage(file="bg_1.png")
bg_1_a = tk.PhotoImage(file="bg_1_a.png")
bg_1_b = tk.PhotoImage(file="bg_1_b.png")
bg_1_c = tk.PhotoImage(file="bg_1_c.png")
bg_2 = tk.PhotoImage(file="bg_2.png")
bg_3 = tk.PhotoImage(file="bg_3.png")
bg_4 = tk.PhotoImage(file="bg_4.png")
soundFlag = [0,False]
QRcodeRead = pygame.mixer.Sound("QRcodeRead.wav")
start_call = pygame.mixer.Sound("start_call.wav")
time_explanation = pygame.mixer.Sound("time_explanation.wav")
select_explanation = pygame.mixer.Sound("select_explanation.wav")
rest10 = pygame.mixer.Sound("rest10.wav")
rest5 = pygame.mixer.Sound("rest5.wav")
rest3 = pygame.mixer.Sound("rest3.wav")
rest2 = pygame.mixer.Sound("rest2.wav")
rest1 = pygame.mixer.Sound("rest1.wav")
DL_explanation = pygame.mixer.Sound("DL_explanation.wav")
printing_explanation = pygame.mixer.Sound("printing_explanation.wav")
# -------------------------------------------- #
# -------------------------------------------- #
capture = cv2.VideoCapture(0)
#capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(‘H’, ‘2’, ‘6’, ‘4’))
capture.set(cv2.CAP_PROP_FPS, 30)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1244)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 700)
# -------------------------------------------- #
# ------------------ Scene1 ------------------ #
scene1 = tk.Frame(root, width=1920, height=1080)
scene1.grid(row=0, column=0, sticky="nsew")
scene1.propagate(False) #Frameサイズを固定
frame1_1 = tk.Frame(scene1, width=540, height=750)
frame1_2 = tk.Frame(scene1, width=840, height=750)
frame1_3 = tk.Frame(scene1, width=540, height=750)
frame1_4 = tk.Frame(scene1, width=1920, height=330)
frame1_1.propagate(False) #Frameサイズを固定
frame1_2.propagate(False)
frame1_3.propagate(False)
frame1_4.propagate(False)
frame1_1.grid(row=0, column=0) #Frameを配置(grid)
frame1_2.grid(row=0, column=1)
frame1_3.grid(row=0, column=2)
frame1_4.grid(row=1, column=0, columnspan = 3)
canvas1_1 = tk.Canvas(frame1_1,width=540,height=750, highlightthickness=0)
canvas1_2 = tk.Canvas(frame1_2,width=840,height=750, highlightthickness=0)
canvas1_3 = tk.Canvas(frame1_3,width=540,height=750, highlightthickness=0)
canvas1_4 = tk.Canvas(frame1_4,width=1920,height=330, highlightthickness=0)
canvas1_1.grid(row=0, column=0)
canvas1_2.grid(row=0, column=1)
canvas1_3.grid(row=0, column=2)
canvas1_4.grid(row=1, column=0, columnspan=3)
qrread = tk.PhotoImage(file="qrread.png")
canvas1_1.create_image(270,375,image=bg_1)
canvas1_3.create_image(270,375,image=bg_3)
canvas1_4.create_image(960,165,image=qrread)
frame1_2_GUI()
# ------------------ Scene2 ------------------ #
scene2 = tk.Frame(root, width=1920, height=1080)
scene2.grid(row=0, column=0, sticky="nsew")
scene2.propagate(False) #Frameサイズを固定
frame1 = tk.Frame(scene2, width=1920, height=200)
frame2 = tk.Frame(scene2, width=800, height=880)
frame3 = tk.Frame(scene2, width=320, height=880)
frame4 = tk.Frame(scene2, width=800, height=880)
frame1.propagate(False) #Frameサイズを固定
frame2.propagate(False)
frame3.propagate(False)
frame4.propagate(False)
frame1.grid(row=0, column=0, columnspan = 3) #Frameを配置(grid)
frame2.grid(row=1, column=0)
frame3.grid(row=1, column=1)
frame4.grid(row=1, column=2)
# ----------- frame1 ----------- #
canvas2_1a = tkinter.Canvas(frame1,width=860,height=200, highlightthickness=0)
canvas2_1b = tkinter.Canvas(frame1,width=200,height=200, highlightthickness=0)
canvas2_1c = tkinter.Canvas(frame1,width=860,height=200, highlightthickness=0)
canvas2_1a.grid(row=0, column=0)
canvas2_1b.grid(row=0, column=1)
canvas2_1c.grid(row=0, column=2)
canvas2_1a.create_image(430,100,image=bg_1_a)
canvas2_1c.create_image(430,100,image=bg_1_c)
# ----------- frame2 ----------- #
canvas2_2 = tkinter.Canvas(frame2,width=800,height=880, highlightthickness=0)
canvas2_2.pack()
canvas2_2.bind("<ButtonPress-1>", lambda event:on_pressed(event,0))
canvas2_2.bind("<B1-Motion>", lambda event:on_dragged(event,0))
canvas2_2.bind("<Motion>", lambda event:on_moved(event,0))
# ----------- frame3 ----------- #
canvas2_3 = tkinter.Canvas(frame3,width=320,height=880, highlightthickness=0)
canvas2_3.pack()
pen_bg = tk.PhotoImage(file="pen_bg.png")
stamp_bg = tk.PhotoImage(file="stamp_bg.png")
canvas2_3.create_image(160,440,image=bg_3)
canvas2_3.create_image(82.5,250,image=pen_bg)
canvas2_3.create_image(237.5,250,image=pen_bg)
canvas2_3.create_image(160,690,image=stamp_bg)
icon1 = tk.PhotoImage(file="icon1.png")
icon2 = tk.PhotoImage(file="icon2.png")
icon3 = tk.PhotoImage(file="icon3.png")
icon4 = tk.PhotoImage(file="icon4.png")
icon1_off = tk.PhotoImage(file="icon1_off.png")
icon2_off = tk.PhotoImage(file="icon2_off.png")
icon3_off = tk.PhotoImage(file="icon3_off.png")
icon4_off = tk.PhotoImage(file="icon4_off.png")
brush_widgh1 = tk.PhotoImage(file="brush_widgh1.png")
brush_widgh2 = tk.PhotoImage(file="brush_widgh2.png")
brush_widgh3 = tk.PhotoImage(file="brush_widgh3.png")
brush_widgh4 = tk.PhotoImage(file="brush_widgh4.png")
brush_widgh1_off = tk.PhotoImage(file="brush_widgh1_off.png")
brush_widgh2_off = tk.PhotoImage(file="brush_widgh2_off.png")
brush_widgh3_off = tk.PhotoImage(file="brush_widgh3_off.png")
brush_widgh4_off = tk.PhotoImage(file="brush_widgh4_off.png")
icon_stamp1 = tk.PhotoImage(file="icon_stamp1.png")
icon_stamp2 = tk.PhotoImage(file="icon_stamp2.png")
icon_stamp3 = tk.PhotoImage(file="icon_stamp3.png")
icon_stamp4 = tk.PhotoImage(file="icon_stamp4.png")
icon_stamp1_off = tk.PhotoImage(file="icon_stamp1_off.png")
icon_stamp2_off = tk.PhotoImage(file="icon_stamp2_off.png")
icon_stamp3_off = tk.PhotoImage(file="icon_stamp3_off.png")
icon_stamp4_off = tk.PhotoImage(file="icon_stamp4_off.png")
# 各種ウィジェットの作成
button_icon1 = tk.Button(canvas2_3, image=icon1_off, compound="top", command=brush1, relief=tk.RAISED)
button_icon2 = tk.Button(canvas2_3, image=icon2, compound="top", command=brush2, relief=tk.RAISED)
button_icon3 = tk.Button(canvas2_3, image=icon3, compound="top", command=brush3, relief=tk.RAISED)
button_icon4 = tk.Button(canvas2_3, image=icon4, compound="top", command=eraser1, relief=tk.RAISED)
button_brush_widgh4 = tk.Button(canvas2_3, image=brush_widgh4_off, compound="top", command=brush_widgh4_setting, relief=tk.RAISED)
button_brush_widgh3 = tk.Button(canvas2_3, image=brush_widgh3, compound="top", command=brush_widgh3_setting, relief=tk.RAISED)
button_brush_widgh2 = tk.Button(canvas2_3, image=brush_widgh2, compound="top", command=brush_widgh2_setting, relief=tk.RAISED)
button_brush_widgh1 = tk.Button(canvas2_3, image=brush_widgh1, compound="top", command=brush_widgh1_setting, relief=tk.RAISED)
button_stamp1 = tk.Button(canvas2_3, image=icon_stamp1, compound="top", command=stamp1, relief=tk.RAISED)
button_stamp2 = tk.Button(canvas2_3, image=icon_stamp2, compound="top", command=stamp2, relief=tk.RAISED)
button_stamp3 = tk.Button(canvas2_3, image=icon_stamp3, compound="top", command=stamp3, relief=tk.RAISED)
button_stamp4 = tk.Button(canvas2_3, image=icon_stamp4, compound="top", command=stamp4, relief=tk.RAISED)
button_icon1.place(x = 30, y = 30)
button_icon2.place(x = 30, y = 140)
button_icon3.place(x = 30, y = 250)
button_icon4.place(x = 30, y = 360)
button_brush_widgh4.place(x = 185, y = 30)
button_brush_widgh3.place(x = 185, y = 140)
button_brush_widgh2.place(x = 185, y = 250)
button_brush_widgh1.place(x = 185, y = 360)
button_stamp1.place(x = 50, y = 590)
button_stamp2.place(x = 165, y = 590)
button_stamp3.place(x = 50, y = 725)
button_stamp4.place(x = 165, y = 725)
# ----------- frame4 ----------- #
canvas2_4 = tkinter.Canvas(frame4,width=800,height=880, highlightthickness=0)
canvas2_4.pack()
canvas2_4.bind("<ButtonPress-1>", lambda event:on_pressed(event,1))
canvas2_4.bind("<B1-Motion>", lambda event:on_dragged(event,1))
canvas2_4.bind("<Motion>", lambda event:on_moved(event,1))
frame1b_GUI()
# ------------------ Scene3 ------------------ #
scene3 = tk.Frame(root, width=1920, height=1080)
scene3.grid(row=0, column=0, sticky="nsew")
scene3.propagate(False) #Frameサイズを固定
canvas3_1 = tk.Canvas(scene3,width=1920,height=1080, highlightthickness=0)
canvas3_1.pack(padx=0, pady=0)
scene3_1=tk.PhotoImage(file='scene3_1.png')
scene3_2=tk.PhotoImage(file='scene3_2.png')
# -------------------------------------------- #
show_scene1()
world_timer()
root.mainloop()
さいごに
ここまで読んでいただきありがとうございます。
初めての制作ということもあって有識者の方から見たな至らぬところがたくさんあると思いまが、来年度へ向けて改善していきたいと考えています。
もしアドバイスや改善案などありましたらコメントいただけますと大変うれしいです。
よろしくお願いいたします。