1+ import sys , cv2 , shutil , time , os
2+ import numpy as np
3+ from skimage .metrics import structural_similarity as compare_ssim
4+ from PyQt5 .QtWidgets import *
5+ from PyQt5 import uic ,QtCore
6+
7+ form_class = uic .loadUiType ("./src/UI.ui" )[0 ]
8+ class MCS (QtCore .QThread ,QtCore .QObject ):
9+ result = QtCore .pyqtSignal (str )
10+ label = QtCore .pyqtSignal (str )
11+ pbar_value = QtCore .pyqtSignal (float )
12+ go_stop = QtCore .pyqtSignal (bool )
13+ def __init__ (self ,p1 ,p2 ,p3 ,st ,c1 ,c2 ,parent = None ):
14+ super (MCS ,self ).__init__ (parent )
15+ self .p1 = p1
16+ self .p2 = p2
17+ self .p3 = p3
18+ self .st = st
19+ self .c1 = c1
20+ self .c2 = c2
21+ self .thread_type = ''
22+ self .working = True
23+ self .go_stop .emit (True )
24+ def monster_search (self ,sPath ):
25+ source = cv2 .imread (sPath ,cv2 .IMREAD_COLOR ) # 검사 대상
26+ if source .shape [1 ]== 1366 :
27+ source = source [268 :345 ,369 :959 ] # 1366 * 768 에서 출력되는 위치 자르기
28+ elif source .shape [1 ]== 800 :
29+ source = source [100 :177 ,86 :676 ]
30+ elif source .shape [1 ]== 1024 :
31+ source = source [268 :345 ,198 :788 ]
32+ elif source .shape [1 ]== 1280 :
33+ source = source [220 :297 ,326 :916 ]
34+ elif source .shape [1 ]== 1920 :
35+ source = source [424 :501 ,646 :1236 ]
36+ else :
37+ print ("지원되지 않는 형식!" )
38+ return 0
39+
40+ target = np .load ('src//target.npy' ) # 탐색 목표 이미지
41+ mask = target [:,:,- 1 ] #타겟의 알파 마스크 출력
42+ tmp ,mask_r = cv2 .threshold (mask ,254 ,255 ,cv2 .THRESH_BINARY ) # tmp는 사용하지 않음, 유사 부울린 마스크(mask_r) 생성
43+ target = cv2 .cvtColor (target ,cv2 .COLOR_RGBA2RGB )
44+
45+ w ,h = source .shape [:2 ]
46+
47+ tgt = np .zeros ((w ,h ,3 ),np .uint8 )
48+ cv2 .copyTo (target ,mask_r ,tgt )
49+
50+ src = np .zeros ((w ,h ,3 ),np .uint8 )
51+ cv2 .copyTo (source ,mask_r ,src )
52+
53+ score , tmp = compare_ssim (src , tgt , full = True ,multichannel = True )
54+ # full=True: 이미지 전체에 대해서 구조비교를 수행한다.
55+ return score * 100
56+ def file_list (self ,root_dir ,listbool ):
57+ img_list = []
58+ img_name = ['.jpg' , '.jpeg' , '.JPG' , '.PNG' , '.png' ]
59+ if listbool == 2 :
60+ for (root , dirs , files ) in os .walk (root_dir ):
61+ if len (files ) > 0 :
62+ for file_name in files :
63+ if file_name .startswith ('Maple_A' ) and os .path .splitext (file_name )[1 ] in img_name :
64+ img_path = root + "\\ " + file_name
65+ img_list .append (img_path )
66+ else :
67+ for files in os .listdir (root_dir ):
68+ if files .startswith ('Maple_A' ) and '.' + files .split ('.' )[- 1 ] in img_name :
69+ img_path = root_dir + "\\ " + files
70+ img_list .append (img_path )
71+ return (img_list )
72+ def run (self ):
73+ timestr = time .strftime ("%y-%m-%d_%H-%M-%S " )
74+ if self .thread_type == 'class' and self .working :
75+ not_mon_log = "\n \n 몬컬이 아닌 캡쳐 목록:"
76+ mon_log = "\n \n 몬컬 캡처 목록:"
77+ cap_list = self .file_list (self .p1 ,self .c1 )
78+ all_n = len (cap_list )
79+ i = 0
80+ for source in cap_list :
81+ filename = source .split ('\\ ' )[- 1 ]
82+ score = self .monster_search (source )
83+ if score < self .st :
84+ shutil .move (source ,self .p2 + '\\ ' + filename )
85+ not_mon_log = not_mon_log + '\n ' + filename + ':' + f"{ score :.1f} " + '%'
86+ else :
87+ shutil .move (source ,self .p3 + '\\ ' + filename )
88+ mon_log = mon_log + '\n ' + filename + ':' + f"{ score :.1f} " + '%'
89+ i = i + 1
90+ self .label .emit (f'{ i } ' + '/' + f'{ all_n } ' )
91+ self .result .emit (filename + ':' + f"{ score :.1f} " + '%' )
92+ self .pbar_value .emit ((i + 1 )/ all_n )
93+ if self .c2 :
94+ f = open (f"{ os .getcwd ()} \\ log-{ timestr } .txt" ,'w' ,encoding = 'UTF-8' )
95+ f .write ("시작시간: " + timestr + not_mon_log + mon_log )
96+ f .close ()
97+ self .go_stop .emit (False )
98+ elif self .thread_type == 'log' and self .working :
99+ not_mon_log = "\n \n 몬컬이 아닌 캡쳐 목록:"
100+ mon_log = "\n \n 몬컬 캡처 목록:"
101+ cap_list = self .file_list (self .p1 ,self .c1 )
102+ all_n = len (cap_list )
103+ i = 0
104+ for source in cap_list :
105+ filename = source .split ('\\ ' )[- 1 ]
106+ score = self .monster_search (source )
107+ if score < self .st :
108+ not_mon_log = not_mon_log + '\n ' + filename + ':' + f"{ score :.1f} " + '%'
109+ else :
110+ mon_log = mon_log + '\n ' + filename + ':' + f"{ score :.1f} " + '%'
111+ i = i + 1
112+ self .label .emit (f'{ i } ' + '/' + f'{ all_n } ' )
113+ self .result .emit (filename + ':' + f"{ score :.1f} " + '%' )
114+ self .pbar_value .emit ((i + 1 )/ all_n )
115+ if self .c2 :
116+ f = open (f"{ os .getcwd ()} \\ log-{ timestr } .txt" ,'w' ,encoding = 'UTF-8' )
117+ f .write ("시작시간: " + timestr + not_mon_log + mon_log )
118+ f .close ()
119+ self .go_stop .emit (False )
120+ else :
121+ self .terminate ()
122+ self .quit ()
123+ class MyWindow (QMainWindow , form_class ):
124+ path_signal = QtCore .pyqtSignal (str )
125+ def __init__ (self ):
126+ super ().__init__ ()
127+ self .setupUi (self )
128+
129+ self .pushButton .clicked .connect (self .getFilepath1 )
130+ self .pushButton_2 .clicked .connect (self .getFilepath2 )
131+ self .pushButton_3 .clicked .connect (self .getFilepath3 )
132+
133+ self .pushButton_4 .clicked .connect (self .classifying )
134+ self .pushButton_5 .clicked .connect (self .logonly )
135+ def getFilepath1 (self ):
136+ path_name = QFileDialog .getExistingDirectory (self )
137+ self .lineEdit .setText (path_name )
138+ if path_name :
139+ self .pushButton_5 .setEnabled (True )
140+ if self .lineEdit_3 .text () and self .lineEdit_2 .text () and self .lineEdit .text ():
141+ self .pushButton_4 .setEnabled (True )
142+ def getFilepath2 (self ):
143+ path_name = QFileDialog .getExistingDirectory (self )
144+ self .lineEdit_2 .setText (path_name )
145+ if self .lineEdit_3 .text () and self .lineEdit_2 .text () and self .lineEdit .text ():
146+ self .pushButton_4 .setEnabled (True )
147+ def getFilepath3 (self ):
148+ path_name = QFileDialog .getExistingDirectory (self )
149+ self .lineEdit_3 .setText (path_name )
150+ if self .lineEdit_3 .text () and self .lineEdit_2 .text () and self .lineEdit .text ():
151+ self .pushButton_4 .setEnabled (True )
152+ def classifying (self ):
153+
154+ self .progressBar .setEnabled (True )
155+ self .textEdit .setText ("" )
156+
157+ check1 = self .checkBox .checkState ()
158+ check2 = self .checkBox_2 .checkState ()
159+ p1 = self .lineEdit .text ()
160+ p2 = self .lineEdit_2 .text ()
161+ p3 = self .lineEdit_3 .text ()
162+ st = self .spinBox .value ()
163+ self .switch_widgets (True )
164+ self .th = MCS (p1 ,p2 ,p3 ,st ,check1 ,check2 ,parent = self )
165+ self .th .result .connect (self .setResultBox )
166+ self .th .pbar_value .connect (self .pBarUpdate )
167+ self .th .label .connect (self .label5update )
168+ self .th .go_stop .connect (self .thread_stop )
169+ self .th .start ()
170+ self .th .thread_type = 'class'
171+ def logonly (self ):
172+ self .progressBar .setEnabled (True )
173+ self .textEdit .setText ("" )
174+ self .switch_widgets (True )
175+
176+ check1 = self .checkBox .checkState ()
177+ check2 = self .checkBox_2 .checkState ()
178+ p1 = self .lineEdit .text ()
179+ st = self .spinBox .value ()
180+
181+ self .th = MCS (p1 ,'' ,'' ,st ,check1 ,check2 ,parent = self )
182+ self .th .result .connect (self .setResultBox )
183+ self .th .pbar_value .connect (self .pBarUpdate )
184+ self .th .label .connect (self .label5update )
185+ self .th .go_stop .connect (self .thread_stop )
186+ self .th .start ()
187+ self .th .thread_type = 'log'
188+ def setResultBox (self , result ):
189+ self .textEdit .append (result )
190+ def switch_widgets (self ,onoff ):
191+ if onoff :
192+ self .pushButton .setDisabled (True )
193+ self .pushButton_2 .setDisabled (True )
194+ self .pushButton_3 .setDisabled (True )
195+ self .pushButton_4 .setDisabled (True )
196+ self .pushButton_5 .setDisabled (True )
197+ self .checkBox .setDisabled (True )
198+ self .checkBox_2 .setDisabled (True )
199+ self .spinBox .setDisabled (True )
200+ else :
201+ self .pushButton .setEnabled (True )
202+ self .pushButton_2 .setEnabled (True )
203+ self .pushButton_3 .setEnabled (True )
204+ if self .lineEdit_3 .text () and self .lineEdit_2 .text () and self .lineEdit .text ():
205+ self .pushButton_4 .setEnabled (True )
206+ self .pushButton_5 .setEnabled (True )
207+ self .checkBox .setEnabled (True )
208+ self .checkBox_2 .setEnabled (True )
209+ self .spinBox .setEnabled (True )
210+ @QtCore .pyqtSlot (float )
211+ def pBarUpdate (self ,val ):
212+ self .progressBar .setValue (val * 100 )
213+ @QtCore .pyqtSlot (str )
214+ def label5update (self ,val ):
215+ self .label_5 .setText (val )
216+ @QtCore .pyqtSlot (bool )
217+ def thread_stop (self ,val ):
218+ if val == False :
219+ self .th .terminate ()
220+ self .th .working = False
221+ self .switch_widgets (False )
222+ if __name__ == "__main__" :
223+ app = QApplication (sys .argv )
224+ myWindow = MyWindow ()
225+ myWindow .show ()
226+ app .exec_ ()
0 commit comments