From 85ffc57fff28902d0cbcc586385847fba4abe5da Mon Sep 17 00:00:00 2001 From: karakurai Date: Tue, 25 Jun 2024 22:45:23 +0900 Subject: [PATCH] v1.2.0 --- main.py | 66 ++++++++++++++++++++++++++++-- main_screen.kv | 34 +++++++++++++++- main_screen.py | 87 ++++++++++++++++++++++++++++++++++++---- making_dataset_screen.kv | 2 +- preprocessing_screen.kv | 4 +- text.ini | 16 +++++--- 6 files changed, 188 insertions(+), 21 deletions(-) diff --git a/main.py b/main.py index a2340bc..0db2561 100644 --- a/main.py +++ b/main.py @@ -7,7 +7,7 @@ from kivy.core.text import DEFAULT_FONT, LabelBase from kivy.core.window import Window from kivy.lang import Builder -from kivy.properties import ObjectProperty +from kivy.properties import BooleanProperty, ObjectProperty from kivy.uix.popup import Popup from kivy.uix.tabbedpanel import TabbedPanel from kivymd.app import MDApp @@ -27,9 +27,19 @@ Window.left = 0 Window.top = 30 Window.size = (1600, 900) -LabelBase.register( - DEFAULT_FONT, "./adfi_client_app_data/fonts/BIZUDPGothic-Regular.ttf" -) + +WINDOWS_FONT_PATH_1 = "C:/Windows/Fonts/meiryo.ttc" +WINDOWS_FONT_PATH_2 = "C:/Windows/Fonts/YuGothM.ttc" +FONT_PATH = "./adfi_client_app_data/fonts/BIZUDPGothic-Regular.ttf" +try: + if os.path.exists(WINDOWS_FONT_PATH_1): + LabelBase.register(DEFAULT_FONT, WINDOWS_FONT_PATH_1) + elif os.path.exists(WINDOWS_FONT_PATH_2): + LabelBase.register(DEFAULT_FONT, WINDOWS_FONT_PATH_2) + elif os.path.exists(FONT_PATH): + LabelBase.register(DEFAULT_FONT, FONT_PATH) +except Exception as e: + print(str(e)) Builder.load_file("./main.kv") Builder.load_file("./camera_setting_screen.kv") Builder.load_file("./target_area_screen.kv") @@ -80,6 +90,7 @@ class InspectionApp(MDApp): current_ratio2 = [[0.0, 1.0]] * 5 current_inspection_dict = None icon = "adfi_client_app_data/logo/logo.png" + popup_is_open = BooleanProperty(False) def build(self): self.theme_cls.theme_style = "Dark" @@ -100,8 +111,55 @@ def build(self): + ")" ) Window.bind(on_request_close=self.popup_open) + Window.bind(on_key_down=self.on_key_down) return self.sm + def on_key_down(self, window, keycode, scancode, codepoint, modifier): + return_flag = True + if self.sm.current == "main": + screen = self.sm.current_screen + if self.popup_is_open: + if ( + codepoint == "a" + or codepoint == "0" + or codepoint == "1" + or codepoint == "2" + or codepoint == "3" + or codepoint == "4" + ): + screen.dismiss_popup() + elif keycode == 13: + screen.dismiss_popup() + else: + return_flag = False + else: + if codepoint == "a": + screen.ids["main_image_view"].get_images(-1) + elif codepoint == "0": + screen.ids["main_image_view"].get_images(0) + elif codepoint == "1": + screen.ids["main_image_view"].get_images(1) + elif codepoint == "2": + screen.ids["main_image_view"].get_images(2) + elif codepoint == "3": + screen.ids["main_image_view"].get_images(3) + elif codepoint == "4": + screen.ids["main_image_view"].get_images(4) + elif keycode == 13: + screen.ids["main_image_view"].get_images(-1) + else: + return_flag = False + + elif self.sm.current == "making_dataset": + screen = self.sm.current_screen + if codepoint == "a": + screen.ids["dataset_image_view"].save_images(0) + elif codepoint == "b": + screen.ids["dataset_image_view"].save_images(1) + else: + return_flag = False + return return_flag + def get_cameras(self): self.camera_count = 0 for i in range(0, 5): diff --git a/main_screen.kv b/main_screen.kv index d7a4ec9..33a467b 100644 --- a/main_screen.kv +++ b/main_screen.kv @@ -187,7 +187,7 @@ font_size: "14sp" MDSwitch: id: save_results - active: False + active: True disabled: False MDFloatLayout: MDGridLayout: @@ -255,3 +255,35 @@ md_bg_color: "black" font_size: "18sp" text: app.textini[app.lang]["main_massage_no_inspection"] + + + id: popup_image_screen + orientation: 'vertical' + MDBoxLayout: + size_hint: 1, .1 + MDRaisedButton: + id: result + text_color: "white" + md_bg_color: "black" + font_size: "24sp" + MDLabel: + id: popup_title + size_hint: .8, .1 + halign: "center" + adaptive_height: True + text: app.textini[app.lang]["main_result_image_title"] + MDLabel: + size_hint: 1, .05 + text: "" + MDBoxLayout: + size_hint: 1, .75 + Image: + id: popup_image + size: 800, 800 + allow_stretch: True + keep_ratio: True + MDBoxLayout: + size_hint: 1, .1 + MDFillRoundFlatButton: + text: app.textini[app.lang]["ok_a"] + on_release: root.dismiss_popup() \ No newline at end of file diff --git a/main_screen.py b/main_screen.py index 3a4e9da..98b06df 100644 --- a/main_screen.py +++ b/main_screen.py @@ -3,6 +3,8 @@ import glob import os import pickle +import platform +import subprocess import time import webbrowser from concurrent.futures import ThreadPoolExecutor @@ -11,10 +13,12 @@ from kivy.clock import Clock from kivy.graphics import Color, Line, Rectangle from kivy.graphics.texture import Texture +from kivy.properties import NumericProperty, ObjectProperty +from kivy.uix.popup import Popup from kivymd.app import MDApp from kivymd.toast import toast +from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.button import MDFlatButton -from kivymd.uix.dialog import MDDialog from kivymd.uix.floatlayout import MDFloatLayout from kivymd.uix.screen import MDScreen @@ -29,6 +33,7 @@ def __init__(self, **kwargs): self.api_list = [] self.aimodel_list = [] self.inspection_model_num = -1 + self.popup = None def on_enter(self): self.start_screen() @@ -166,6 +171,37 @@ def finish_inspection(self): self.ids["message"].text_color = "white" self.ids["message"].md_bg_color = "black" + def show_image_popup(self, image_path, title="Image", result=None): + if self.popup is None: + new_popup = Popup( + title=title, + content=PopupImageScreen(dismiss_popup=self.dismiss_popup), + size_hint=(0.9, 0.9), + ) + new_popup.content.set_image_path(image_path) + new_popup.title = title + new_popup.content.ids["result"].opacity = 1 + if result == "Anomaly": + new_popup.content.ids["result"].text = self.app.textini[self.app.lang][ + "main_result_ng" + ] + new_popup.content.ids["result"].md_bg_color = "red" + elif result == "Not-clear": + new_popup.content.ids["result"].text = self.app.textini[self.app.lang][ + "main_result_not_clear" + ] + new_popup.content.ids["result"].md_bg_color = "gray" + else: + new_popup.content.ids["result"].opacity = 0 + self.popup = new_popup + self.app.popup_is_open = True + self.popup.open() + + def dismiss_popup(self): + self.popup.dismiss() + self.popup = None + self.app.popup_is_open = False + class MainImageView(MDFloatLayout): def __init__(self, **kwargs): @@ -434,11 +470,19 @@ def do_inspection( self.app.lang ]["main_result_ng"] self.screen.ids["result_" + str(index)].md_bg_color = "red" + if result_image_save_path is not None: + self.show_result_image( + str(index), result_image_save_path, "Anomaly" + ) elif "Not-clear" in result_json["result"]: self.screen.ids["result_" + str(index)].text = self.app.textini[ self.app.lang ]["main_result_not_clear"] self.screen.ids["result_" + str(index)].md_bg_color = "gray" + if result_image_save_path is not None: + self.show_result_image( + str(index), result_image_save_path, "Not-clear" + ) else: self.screen.ids["result_" + str(index)].text = self.app.textini[ self.app.lang @@ -468,11 +512,40 @@ def do_inspection( def show_image(self, result_num): inspection_img_path = self.inspection_image_path_list[int(result_num)] if inspection_img_path is not None and os.path.exists(inspection_img_path): - img = cv2.imread(inspection_img_path) - cv2.imshow("Inspection Image " + str(result_num), img) - cv2.waitKey(1) + open_image(inspection_img_path) result_img_path = self.result_image_path_list[int(result_num)] if result_img_path is not None and os.path.exists(result_img_path): - img = cv2.imread(result_img_path) - cv2.imshow("Result Image " + str(result_num), img) - cv2.waitKey(1) + self.show_result_image(result_num, result_img_path) + + def show_result_image(self, result_num, result_img_path, result=None): + if result_img_path is not None and os.path.exists(result_img_path): + self.screen.show_image_popup( + result_img_path, title="Result Image " + str(result_num), result=result + ) + + +class PopupImageScreen(MDBoxLayout): + dismiss_popup = ObjectProperty(None) + + def set_image_path(self, value): + if os.path.exists(value): + self.ids.popup_image.source = value + else: + print(f"Image path does not exist: {value}") + + +def open_image(image_path): + try: + image_path = os.path.abspath(image_path) + if not os.path.exists(image_path): + print(f"Image path does not exist: {image_path}") + return + system = platform.system() + if system == "Windows": + os.startfile(image_path) + elif system == "Darwin": + subprocess.call(["open", image_path]) + else: + subprocess.call(["xdg-open", image_path]) + except Exception as e: + print(str(e)) diff --git a/making_dataset_screen.kv b/making_dataset_screen.kv index a6e8bcc..d25560a 100644 --- a/making_dataset_screen.kv +++ b/making_dataset_screen.kv @@ -39,7 +39,7 @@ title: app.textini[app.lang]["label_copyright"] icon: "close" type: "bottom" - mode: "end" + mode: "end" on_action_button: app.popup_open() DatasetImageView: id: dataset_image_view diff --git a/preprocessing_screen.kv b/preprocessing_screen.kv index c8a423a..e5c31fd 100644 --- a/preprocessing_screen.kv +++ b/preprocessing_screen.kv @@ -10,7 +10,7 @@ id: message halign: "center" size_hint: 1, .1 - color: 1, 1, 1, 1 + color: 1, 1, 1, 1 text: app.textini[app.lang]["preprocessing_settings"] + " " + app.textini[app.lang]["pp_top_message"] padding: "4dp", "4dp" MDBoxLayout: @@ -95,7 +95,7 @@ title: app.textini[app.lang]["label_copyright"] icon: "close" type: "bottom" - mode: "end" + mode: "end" on_action_button: app.popup_open() PreprocessingImageView: id: image_view diff --git a/text.ini b/text.ini index 8303092..ea87cdd 100644 --- a/text.ini +++ b/text.ini @@ -8,6 +8,7 @@ label_choose = Choose Your Language! language = English quit_app_text = Do you want to quit the application? ok = OK +ok_a = OK (A key) cansel = CANCEL delete = DELETE load = LOAD @@ -128,8 +129,8 @@ is_run_inspection = Run Selected Inspection is_stop_inspection = Stop Running Inspection md_change = Change Displayed Image md_message = Take images for training and testing. Take multiple normal and anomalous images. (Dozens or more recommended) -md_normal = Take Normal Image -md_anomaly = Take Anomalous Image +md_normal = Take Normal Image (A key) +md_anomaly = Take Anomalous Image (B key) md_error_message = Error. No inspection running. Run your inspection in Inspection Settings. md_toast_save_image = Image saved. md_inspection_name = Inspection Name @@ -165,7 +166,7 @@ as_online_plan = Online Plan as_api_key_or_path = API Key or AI Model Path main_inspection_name = Inspection Name main_preprocessing_name = Preprocessing of Displayed Image -main_inspect_image = Inspect +main_inspect_image = Inspect (A key) main_change = Change Displayed Image main_save_inspected_image = Save Inspected Image main_save_inspection_results = Save Inspection Result Image @@ -181,6 +182,7 @@ main_result_error = ERROR main_result_ok = OK main_result_ng = NG main_result_not_clear = Not Clear +main_result_image_title = Areas with higher anomaly scores are displayed in red. ta_x1 = x1 ta_y1 = y1 ta_x2 = x2 @@ -205,6 +207,7 @@ non_editable = Non-Editable [ja] language = 日本語 quit_app_text = 終了しますか? +ok_a = OK (「A」キー) cansel = キャンセル delete = 削除 load = 読込 @@ -323,8 +326,8 @@ is_stop_inspection = 実行中の検査を停止 md_change = 表示画像を変更 md_message = 学習用とテスト用の画像を撮影します。正常画像と異常画像をそれぞれ複数撮影してください。(数十枚以上を推奨) md_error_message = エラー。実行中の検査がありません。検査設定画面で検査を実行してください。 -md_normal = 正常画像を撮影 -md_anomaly = 異常画像を撮影 +md_normal = 正常画像を撮影 (「A」キー) +md_anomaly = 異常画像を撮影 (「B」キー) md_toast_save_image = 画像を保存しました。 md_inspection_name = 検査名 md_preprocessing_name = 表示画像の前処理名 @@ -356,7 +359,7 @@ as_online_plan = オンライン実行 as_api_key_or_path = API Key または AIモデルのパス main_inspection_name = 検査名 main_preprocessing_name = 表示画像の前処理名 -main_inspect_image = 検査実行 +main_inspect_image = 検査実行 (「A」キー) main_change = 表示画像を変更 main_save_inspected_image = 検査した画像を保存 main_save_inspection_results = 検査結果画像を保存 @@ -372,6 +375,7 @@ main_result_error = エラー main_result_ok = OK main_result_ng = NG main_result_not_clear = Not Clear +main_result_image_title = 異常スコアが高い領域ほど赤く表示されます。 previous = 前へ next = 次へ param_width = 幅