import statistics
import tkinter
import time
from PIL import Image, ImageTk # 外部ライブラリ
import pyautogui # 外部ライブラリ
import cv2
import numpy as np
import os
from tqdm import tqdm
import threading
RESIZE_RATIO = 2 # 縮小倍率の規定
WIDTH = 1024
HEIGHT = 1280
class GuiApplication(tkinter.Frame):
input_folder = None
output_folder = None
data_number = None
data_name = None
img_array = np.empty(1)
resized_img_array = np.empty(1)
start_x = -1
start_y = -1
end_x = -1
end_y = -1
def __init__(self, master=None):
super().__init__(master)
self.master.title('ColorChart')
self.master.attributes("-topmost", True)
self.create_window()
def create_window(self):
files = os.listdir("./Input/")
self.data_name = [f for f in files if os.path.isfile(os.path.join("./Input/", f))]
# print(self.data_name)
self.data_number = 0
self.img_array = np.empty([len(self.data_name), HEIGHT, WIDTH, 3], dtype=np.uint8)
self.resized_img_array = np.empty([len(self.data_name), int(HEIGHT/RESIZE_RATIO), int(WIDTH/RESIZE_RATIO), 3], dtype=np.uint8)
for i, name in enumerate(self.data_name):
img_path = "./Input/" + name
img = cv2.imread(img_path)
copy_img = img.copy()
img_resized = cv2.resize(copy_img, (int(WIDTH/RESIZE_RATIO), int(HEIGHT/RESIZE_RATIO)))
self.img_array[i, :, :, :] = np.asarray(img)
self.resized_img_array[i, :, :, :] = np.asarray(img_resized)
# Canvasウィジェットの描画
self.canvas1 = tkinter.Canvas(self.master,
bg='black',
width=WIDTH / RESIZE_RATIO,
height=HEIGHT / RESIZE_RATIO)
# Canvasウィジェットに取得した画像を描画
# item = canvas1.create_image(0, 0, image=img_tk, anchor=tkinter.NW)
# Canvasウィジェットを配置し、各種イベントを設定
self.canvas1.pack()
self.canvas1.bind("<ButtonPress-1>", self.start_point_get)
self.canvas1.bind("<Button1-Motion>", self.rect_drawing)
self.canvas1.bind("<ButtonRelease-1>", self.release_action)
# ボタンの作成と配置
self.button = tkinter.Button(
self.master,
text="補正",
command=lambda: self.button_click()
)
self.button.pack()
self.change_image()
# root.mainloop()
# ドラッグ開始した時のイベント - - - - - - - - - - - - - - - - - - - - - - - - - -
def start_point_get(self, event=None):
# global start_x, start_y # グローバル変数に書き込みを行なうため宣言
self.canvas1.delete("rect1") # すでに"rect1"タグの図形があれば削除
# canvas1上に四角形を描画(rectangleは矩形の意味)
self.canvas1.create_rectangle(event.x,
event.y,
event.x + 1,
event.y + 1,
outline="red",
tag="rect1")
# グローバル変数に座標を格納
self.start_x, self.start_y = event.x, event.y
# ドラッグ中のイベント - - - - - - - - - - - - - - - - - - - - - - - - - -
def rect_drawing(self, event=None):
# ドラッグ中のマウスポインタが領域外に出た時の処理
if event.x < 0:
self.end_x = 0
else:
self.end_x = min(WIDTH / RESIZE_RATIO, event.x)
if event.y < 0:
self.end_y = 0
else:
self.end_y = min(HEIGHT / RESIZE_RATIO, event.y)
# "rect1"タグの画像を再描画
self.canvas1.coords("rect1", self.start_x, self.start_y, self.end_x, self.end_y)
# ドラッグを離したときのイベント - - - - - - - - - - - - - - - - - - - - - - - - - -
def release_action(self, event=None):
# global end_x, end_y
# "rect1"タグの画像の座標を元の縮尺に戻して取得
self.start_x, self.start_y, self.end_x, self.end_y = [
round(n * RESIZE_RATIO) for n in self.canvas1.coords("rect1")
]
# 取得した座標を表示
# pyautogui.alert("start_x : " + str(self.start_x) + "\n" + "start_y : " +
# str(self.start_y) + "\n" + "end_x : " + str(self.end_x) + "\n" +
# "end_y : " + str(self.end_y))
def button_click(self):
if self.start_x < 0:
pyautogui.alert("please select a black area")
else:
# print(path)
# print(start_x*2, start_y*2, end_x, end_y)
# 画素値の取得
# pyautogui.alert("start_x : " + str(self.start_x) + "\n" + "start_y : " +
# str(self.start_y) + "\n" + "end_x : " + str(self.end_x) + "\n" +
# "end_y : " + str(self.end_y))
image = self.img_array[self.data_number, :, :, :]
out_path = "./Output/" + self.data_name[self.data_number]
m = image[self.start_y:self.end_y, self.start_x:self.end_x]
# cv2.imshow('window', m)
# rsum, gsum, bsum = 0.0, 0.0, 0.0
r_list = []
g_list = []
b_list = []
for raster in m:
for px in raster:
# rsum += px[2]
# gsum += px[1]
# bsum += px[0]
r_list.append(px[2])
g_list.append(px[1])
b_list.append(px[0])
# 平均値
# ravg = rsum / ((self.end_x - self.start_x) * (self.end_y - self.start_y))
# gavg = gsum / ((self.end_x - self.start_x) * (self.end_y - self.start_y))
# bavg = bsum / ((self.end_x - self.start_x) * (self.end_y - self.start_y))
# print(bavg, gavg, ravg)
#中央値
# r_median = statistics.median(r_list)
# g_median = statistics.median(g_list)
# b_median = statistics.median(b_list)
# print(b_median, g_median, r_median)
# 最頻値
r_mode = statistics.mode(r_list)
g_mode = statistics.mode(g_list)
b_mode = statistics.mode(b_list)
# print(b_mode, g_mode, r_mode)
h, w, c = image.shape
copy_img = image.copy()
cv2.rectangle(copy_img, (0, h - 210), (200, h), (int(b_mode), int(g_mode), int(r_mode)), thickness=-1)
cv2.imwrite(out_path, copy_img)
self.data_number = self.data_number + 1
if self.data_number < len(self.data_name):
self.change_image()
self.start_x = -1
self.start_y = -1
self.end_x = -1
self.end_y = -1
else:
pyautogui.alert("finished")
self.master.destroy()
def change_image(self):
cv2_image = self.resized_img_array[self.data_number, :, :, :]
# BGR(opencv) -> RGB(numpy) -> PIL image
pil_image = Image.fromarray(cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB))
# convert PIL.Image to PhotoImage
self.photo_image = ImageTk.PhotoImage(image=pil_image)
# display image to canvas
self.update()
self.canvas1.create_image(self.canvas1.winfo_width() // 2,
self.canvas1.winfo_height() // 2,
image=self.photo_image)
# メイン処理 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if __name__ == "__main__":
root = tkinter.Tk()
app = GuiApplication(master=root)
app.mainloop()