├── .gitattributes ├── cutted.avi ├── README.md ├── .gitignore ├── FrameProcessor.py ├── main.py ├── design.py └── design.ui /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /cutted.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demidovd98/conveyorObjCounterRT_demo/HEAD/cutted.avi -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ________________________ 2 | Description: 3 | 4 | Real-time counting objects on the conveyor belt, made with Python code. 5 | 6 | Libraries used: NumPy, OpenCV, PyQT5, os. 7 | 8 | Demo code is available on GitHub: https://github.com/demidovd98/conveyorObjCounterRT_demo 9 | 10 | 11 | 12 | ________________________ 13 | Requirements: 14 | - Python 3.7 or higher 15 | - to_add 16 | 17 | 18 | ________________________ 19 | Videos of using: 20 | - https://www.youtube.com/watch?v=pRXxsDlcPG4 21 | - https://www.youtube.com/watch?v=G564yYj2PzY 22 | 23 | 24 | ________________________ 25 | For further development: 26 | 27 | I. How to install PyQT_5 library: 28 | 29 | Requirements: 30 | - Python 3.7 or higher 31 | 32 | Steps: 33 | 1) Open CMD 34 | 35 | 2) Past this command: 36 | pip3 install pyqt5 37 | or 38 | python -m pip intrall pyqt5 39 | 40 | 41 | P.S. For more instructions visit this page: https://python-scripts.com/pyqt5 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | #My folders and files: 29 | old/ 30 | old2/ 31 | designChanges.txt 32 | pyqt5designer.exe 33 | 34 | 35 | MANIFEST 36 | 37 | # PyInstaller 38 | # Usually these files are written by a python script from a template 39 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 40 | *.manifest 41 | *.spec 42 | 43 | # Installer logs 44 | pip-log.txt 45 | pip-delete-this-directory.txt 46 | 47 | # Unit test / coverage reports 48 | htmlcov/ 49 | .tox/ 50 | .nox/ 51 | .coverage 52 | .coverage.* 53 | .cache 54 | nosetests.xml 55 | coverage.xml 56 | *.cover 57 | *.py,cover 58 | .hypothesis/ 59 | .pytest_cache/ 60 | cover/ 61 | 62 | # Translations 63 | *.mo 64 | *.pot 65 | 66 | # Django stuff: 67 | *.log 68 | local_settings.py 69 | db.sqlite3 70 | db.sqlite3-journal 71 | 72 | # Flask stuff: 73 | instance/ 74 | .webassets-cache 75 | 76 | # Scrapy stuff: 77 | .scrapy 78 | 79 | # Sphinx documentation 80 | docs/_build/ 81 | 82 | # PyBuilder 83 | .pybuilder/ 84 | target/ 85 | 86 | # Jupyter Notebook 87 | .ipynb_checkpoints 88 | 89 | # IPython 90 | profile_default/ 91 | ### Python: 92 | ipython_config.py 93 | 94 | # pyenv 95 | # For a library or package, you might want to ignore these files since the code is 96 | # intended to run in multiple environments; otherwise, check them in: 97 | # .python-version 98 | 99 | # pipenv 100 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 101 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 102 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 103 | # install all needed dependencies. 104 | #Pipfile.lock 105 | 106 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 107 | __pypackages__/ 108 | 109 | # Celery stuff 110 | celerybeat-schedule 111 | celerybeat.pid 112 | 113 | # SageMath parsed files 114 | *.sage.py 115 | 116 | # Environments 117 | .env 118 | .venv 119 | env/ 120 | venv/ 121 | ENV/ 122 | env.bak/ 123 | venv.bak/ 124 | 125 | # Spyder project settings 126 | .spyderproject 127 | .spyproject 128 | 129 | # Rope project settings 130 | .ropeproject 131 | 132 | # mkdocs documentation 133 | /site 134 | 135 | # mypy 136 | .mypy_cache/ 137 | .dmypy.json 138 | dmypy.json 139 | 140 | # Pyre type checker 141 | .pyre/ 142 | 143 | # pytype static type analyzer 144 | .pytype/ 145 | 146 | # Cython debug symbols 147 | cython_debug/ 148 | 149 | 150 | 151 | ### C++: 152 | # Prerequisites 153 | *.d 154 | 155 | # Compiled Object files 156 | *.slo 157 | *.lo 158 | *.o 159 | *.obj 160 | 161 | # Precompiled Headers 162 | *.gch 163 | *.pch 164 | 165 | # Compiled Dynamic libraries 166 | *.so 167 | *.dylib 168 | *.dll 169 | 170 | # Fortran module files 171 | *.mod 172 | *.smod 173 | 174 | # Compiled Static libraries 175 | *.lai 176 | *.la 177 | *.a 178 | *.lib 179 | 180 | # Executables 181 | *.exe 182 | *.out 183 | *.app 184 | 185 | # Windows shortcuts 186 | *.lnk -------------------------------------------------------------------------------- /FrameProcessor.py: -------------------------------------------------------------------------------- 1 | ##### Comments: 2 | ''' 3 | Символ G в комментариях - старый код 4 | Символ GUI в комментариях - добавить в gui 5 | Символ + в комментариях - регулировка точности 6 | ''' 7 | #-#-# 8 | 9 | 10 | ##### Imports: 11 | 12 | ### Video parsing: 13 | import cv2 as cv 14 | import numpy as np 15 | 16 | 17 | ### General: 18 | # Time: 19 | import time 20 | #from time import time 21 | from datetime import timedelta 22 | 23 | #-#-# 24 | 25 | 26 | ##### Variables + Initialisations: 27 | 28 | def Initialize(): 29 | ### Global variables list: 30 | global start_time, timer, \ 31 | ref_size, ref_x, ref_y, \ 32 | calc_zone, \ 33 | numbBox, numbCons, numbAll, boxSize, \ 34 | prodOld, prodCurr, \ 35 | isWork, \ 36 | inFrame, \ 37 | sens_lower, sens_upper, \ 38 | noise_lower, noise_upper, \ 39 | pixels_h, ref_hsv, \ 40 | bound_lower, bound_upper 41 | 42 | ### Start time counting: 43 | start_time = time.time() #Момент времени когда програма была запущена 44 | #timer = 0 #Инициализация таймера (с нуля) GUI old 45 | timer = 0 #Инициализация таймера (с нуля) GUI new 46 | 47 | ###Положение опорного кадра цвета фона (место где нет продукта и только лента конвейера): 48 | #ref_size = 50 #Size (by x and y) G 49 | ref_size = 50 #Size (by x and y) + 50 | 51 | #ref_x = 160 #Start point by x G 52 | ref_x = 215 #Start point by x + 53 | 54 | #ref_y = 10 #Start point by y G 55 | ref_y = 5 #Start point by y + 56 | 57 | 58 | ### Зона подсчета пикселей: 59 | calc_zone = ((0,225),(220,255)) # + 60 | 61 | pixels_h = 0 62 | 63 | ref_hsv = 0 64 | 65 | 66 | ### Counting: 67 | #boxCounter = 0 #количество объектов в коробке G 68 | numbBox = 0 #количество продукции в коробке GUI 69 | 70 | #typeCounter = 0 #количество объектов одного типа G 71 | numbCons = 0 #количество продукции в текущей партии (один тип продукта) GUI 72 | 73 | #counter = 0 #количество объектов за смену G 74 | numbAll = 0 #количество всей продукции с момента включения GUI 75 | 76 | boxSize = 3 #вместимость коробки GUI 77 | 78 | #oldType = "sosage" #предыдущий тип продукта G 79 | prodOld = " " #предыдущий тип продукта GUI 80 | 81 | #newType = "sosage" #настоящий тип продукта G 82 | prodCurr = " " #текущий тип продукта GUI 83 | 84 | #stop = 0 #0 - конвейер работает, 1 - конвейер остановлен G 85 | isWork = False #True - конвейер работает, False - конвейер не работает GUI 86 | 87 | 88 | ### Object finding: 89 | inFrame = False #True - объект в области обнаружен, False - объект в области не обнаружен GUI 90 | 91 | #level = 10 #порог наличия объекта G 92 | sens_lower = 300 #нижний порог наличия объекта (min = noise_upper+1) + 93 | sens_upper = 6600 #верхний порог наличия объекта (max = 6600) + 94 | 95 | noise_lower = 1 #нижний порог наличия шумов (min = 1) + 96 | noise_upper = 299 #верхний порог наличия шумов (max = sens_lower-1) + 97 | 98 | bound_lower = [] 99 | bound_upper = [] 100 | 101 | ### Not in use: 102 | #workTime = 0 #время работы конвейера GUI 103 | #stopTime = 0 #время останова конвейера GUI 104 | 105 | 106 | ### From GUI file: 107 | #IDlist = [] #список типов продукции old 108 | prodList = [] #список типов продукции new 109 | #next = False # удалить 110 | 111 | #-#-# 112 | 113 | 114 | ##### Functions: 115 | 116 | def FrameProcess(frame, isRet): 117 | ### Global variables list: 118 | global start_time, timer, \ 119 | ref_size, ref_x, ref_y, \ 120 | calc_zone, \ 121 | numbBox, numbCons, numbAll, boxSize, \ 122 | prodOld, prodCurr, \ 123 | isWork, \ 124 | inFrame, \ 125 | sens_lower, sens_upper, \ 126 | noise_lower, noise_upper, \ 127 | pixels_h, ref_hsv, \ 128 | bound_lower, bound_upper 129 | 130 | 131 | ### Function: 132 | #while(cap.isOpened()): old 133 | 134 | ### Time counting: 135 | timer = (time.time()-start_time)// 1 #Время с момента запуска программы (// - целое от деления) 136 | #print(timedelta(seconds=int(timer))) 137 | #timerDHS = str(timedelta(seconds = int(timer)))) new +++ 138 | 139 | 140 | ### Video source processing: 141 | if isRet == True: 142 | #_, frame = cap.read() #Main Frame (video source in colour), Take each frame old 143 | 144 | #hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) #Convert BGR to HSV (whole Frame zone) G 145 | frame_hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) #Convert BGR to HSV (whole Frame zone) 146 | 147 | #(источник https://docs.opencv.org/4.2.0/df/d9d/tutorial_py_colorspaces.html) 148 | #bgr_ref = np.median(frame[ref_x:ref_x+ref_size,ref_y:ref_y+ref_size],axis=[0,1]) #Medium colour (RGB) in ref zone G 149 | ref_bgr = np.median(frame[ref_x:ref_x+ref_size,ref_y:ref_y+ref_size],axis=[0,1]) #Medium colour (RGB) in ref zone 150 | 151 | #bgr_ref = np.uint8([[bgr_ref]]) #Convert type to unsigned int G 152 | ref_bgr = np.uint8([[ref_bgr]]) #Convert type to unsigned int 153 | 154 | #hsv_ref = cv.cvtColor(bgr_ref,cv.COLOR_BGR2HSV) #Convert BGR to HSV (only ref zone) G 155 | ref_hsv = cv.cvtColor(ref_bgr,cv.COLOR_BGR2HSV) #Convert BGR to HSV (only ref zone) 156 | 157 | #hsv_ref = hsv_ref[0,0] # Extract HSV from massive (only ref zone) G 158 | ref_hsv = ref_hsv[0,0] # Extract HSV from massive (only ref zone) + 159 | #Reference colour ~ (100, 20, 190 +_10), Default HSV = (0-255, 0-255, 0-255) + 160 | ''' 161 | print (ref_hsv) # For debugging 162 | ''' 163 | 164 | # Define range of ref color in HSV: 165 | 166 | ''' 167 | #вот так по-идее правильно: 168 | #lower_bound = np.transpose(cv.subtract(hsv_ref, np.uint8([10,100,100])))[0] G 169 | #lower_bound = np.transpose(cv.subtract(ref_hsv, np.uint8([10,100,100])))[0] 170 | #upper_bound = np.transpose(cv.add(hsv_ref, np.uint8([10,255,255])))[0] G 171 | #upper_bound = np.transpose(cv.add(ref_hsv, np.uint8([10,255,255])))[0] 172 | 173 | #но вот так работает: 174 | ''' 175 | 176 | #lower_bound = np.uint8([hsv_ref[0]-10,50,50]) G 177 | bound_lower = np.uint8([ref_hsv[0]-10,50,50]) #Lower bound of reference colour + 178 | #bound_lower_s = ref_hsv-[10,20,30] #Lower bound of reference colour + 179 | 180 | print (bound_lower) #For debugging 181 | 182 | 183 | #upper_bound = np.uint8([hsv_ref[0]+10,255,255]) G 184 | bound_upper = np.uint8([ref_hsv[0]+10,255,255]) #Upper bound of reference colour + 185 | #bound_upper_s = ref_hsv+[10,20,30] #Lower bound of reference colour + 186 | 187 | print (bound_upper) #For debugging 188 | 189 | 190 | # Threshold the HSV image to get only reference colours: 191 | #mask = cv.inRange(hsv, lower_bound, upper_bound) G 192 | mask = cv.inRange(frame_hsv, bound_lower, bound_upper) #Mask frame (only products, black and white) 193 | 194 | # Counting zone processing: 195 | sample = mask[calc_zone[0][1]:calc_zone[1][1], calc_zone[0][0]:calc_zone[1][0]] #Mask in counting zone 196 | #pixels = sum(sum(sample))//255 #Среднее значение цвета в каждом пикселе G 197 | #pixels_m = sum(sum(sample))//255 #???Среднее значение цвета пикселей в области счёта 198 | #pixels = sum(sum(sample))#//255 #???Сумма всех пикселей в области счёта 199 | 200 | ''' 201 | # For debugging: 202 | sum0 = 0 203 | sum255 = 0 204 | for i in range (len(sample) ): 205 | for j in range (len(sample[i]) ): 206 | if (sample[i][j] == 0): 207 | sum0 += 1 208 | if (sample[i][j] == 255): 209 | sum255 += 1 210 | print (sum0) 211 | print (sum255) 212 | print (sum0 + sum255) 213 | ''' 214 | 215 | # Number of pixels (pixels_h) which = 255 in counting zone on Mask frame (white colour): 216 | pixels_h = 0 217 | for row in sample: 218 | pixels_h += sum(row) 219 | pixels_h /= 255 # + 220 | 221 | 222 | ### Product checking: 223 | #if (pixels > level): G 224 | if (pixels_h >= sens_lower and pixels_h <= sens_upper): 225 | inFrame = True # +++ 226 | ''' 227 | print("inFrame") 228 | ''' 229 | #sleep(1000) 230 | elif (pixels_h >= noise_lower and pixels_h <= noise_upper): 231 | ''' 232 | print("Noise") 233 | ''' 234 | else: 235 | if inFrame: 236 | ''' 237 | print("Added +1") 238 | ''' 239 | #boxCounter += 1 G 240 | numbBox += 1 241 | 242 | #if (boxCounter > boxSize): G 243 | #boxCounter = 1 G 244 | if (numbBox >= boxSize): 245 | #typeCounter += 1 G 246 | numbCons += 1 247 | numbBox = 0 248 | 249 | #counter += 1 G 250 | numbAll += 1 251 | 252 | inFrame = False 253 | 254 | #if (newType != oldType): G 255 | #typeCounter = 0 G 256 | if (prodCurr != prodOld): 257 | numbCons = 0 258 | 259 | 260 | ### Screens output: 261 | # Bitwise-AND mask and original image ??? 262 | res = cv.bitwise_and(frame,frame, mask= mask) #Result frame (mask in colour) 263 | DrawCustom(frame, numbBox, numbCons, numbAll, timer) #Text output 264 | 265 | 266 | ''' 267 | # For debugging: 268 | #cv.imshow('ref',frame[ref_x:ref_x+ref_size,ref_y:ref_y+ref_size]) #Screen: Reference zone frame 269 | #cv.imshow('frame',frame) #Screen: Main Frame 270 | #cv.imshow('mask',mask) #Screen: Mask frame 271 | #cv.imshow('res',res) #Screen: Result frame 272 | 273 | #print(sample.shape) # frame: Resolution 274 | #print(sample.size) # frame: Number of pixels (Если RGB, то ещё делим на 3, т. к. 3 канала) 275 | 276 | #print (pixels_h) #Number of 277 | #print() 278 | 279 | #if cv.waitKey(20) == ord('q'): # При нажатии клавиши Q - завершать цикл While 280 | # break 281 | ''' 282 | 283 | 284 | return frame 285 | 286 | else: 287 | cv.destroyAllWindows() 288 | #return 0 289 | 290 | def DrawTextInRect(frame, pos, text): # Вывод готового текста в рамке 291 | if pos==1: #In Box 292 | r_pos=(0, 20) 293 | r_size=(220,40) 294 | elif pos==2: #In Consignment 295 | r_pos=(0, 40) 296 | r_size=(220,60) 297 | elif pos==3: #Total 298 | r_pos=(0, 60) 299 | r_size=(220,80) 300 | elif pos==4: #Time since start (Runtime) 301 | r_pos=(0, 80) 302 | r_size=(220,100) 303 | else: #Default 304 | r_pos=(0, 0) 305 | r_size=(220,20) 306 | 307 | #Вывод рамки вокруг текста: 308 | cv.rectangle(frame, r_pos, r_size, (255,0,0), -1) 309 | 310 | #Вывод текста: 311 | cv.putText(frame, text, (r_pos[0],r_pos[1]+12), 312 | cv.FONT_HERSHEY_SIMPLEX, 0.5 , (255,255,255)) 313 | 314 | 315 | def DrawCustom(frame, numbBox, numbCons, numbAll, timer): # Задание текста для вывода 316 | #DrawTextInRect(frame, 0, str(cap.get(cv.CAP_PROP_POS_FRAMES))) 317 | #DrawTextInRect(mask, 1, str(frame.shape)) 318 | #DrawTextInRect(mask, 1, str(pixels)) 319 | 320 | #DrawTextInRect(frame, 0, "Products in Box: " + str(boxCounter)) G 321 | DrawTextInRect(frame, 0, "Products in Box: " + str(numbBox)) 322 | 323 | #DrawTextInRect(frame, 1, "Products of This Type: " + str(typeCounter)) G 324 | DrawTextInRect(frame, 1, "Products in Consignment: " + str(numbCons)) 325 | 326 | #DrawTextInRect(frame, 2, "Products per Shift: " + str(counter)) G 327 | DrawTextInRect(frame, 2, "Total products: " + str(numbAll)) 328 | 329 | #DrawTextInRect(frame, 3, "Work Time: " + str(workTime)) G 330 | DrawTextInRect(frame, 3, "Runtime: " + str(timer)) 331 | 332 | #DrawTextInRect(frame, 4, "Stop Time: " + str(stopTime)) #Добавить позднее 333 | 334 | cv.rectangle(frame,calc_zone[0],calc_zone[1],(255,0,0),2) #Рамка области подсчета 335 | 336 | 337 | def GetVariable(): 338 | ### Global variables list: 339 | global start_time, timer, \ 340 | ref_size, ref_x, ref_y, \ 341 | calc_zone, \ 342 | numbBox, numbCons, numbAll, boxSize, \ 343 | prodOld, prodCurr, \ 344 | isWork, \ 345 | inFrame, \ 346 | sens_lower, sens_upper, \ 347 | noise_lower, noise_upper, \ 348 | pixels_h, ref_hsv, \ 349 | bound_lower, bound_upper 350 | 351 | 352 | guiVars = [numbBox, numbCons, numbAll, #0, 1, 2 353 | timer, #3 354 | pixels_h, ref_hsv, #4, 5 355 | sens_lower, sens_upper, # 6, 7 356 | noise_lower, noise_upper,# 8, 9 357 | calc_zone, # 10 358 | ref_x, ref_y, ref_size,# 11, 12, 13 359 | bound_lower, bound_upper # 14, 15 360 | ] 361 | return guiVars 362 | 363 | #-#-# 364 | 365 | 366 | ##### Main: 367 | 368 | #cap = cv.VideoCapture('cutted.avi') #Video source (нужно ли это???) 369 | 370 | #cv.destroyAllWindows() #Закрыть все окна (нужно ли это???) 371 | 372 | #-#-# 373 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | ##### Comments: 2 | ''' 3 | # pyuic5 design.ui -o design.py 4 | 5 | # pyinstaller --onefile -w main.py 6 | ''' 7 | #-#-# 8 | 9 | 10 | ##### Imports: 11 | 12 | ### Video parsing: 13 | import cv2 as cv # OpenCV 14 | #import numpy as np 15 | import FrameProcessor # Наш python файл с обработкой видео 16 | 17 | ### GUI: 18 | from PyQt5 import QtWidgets, QtGui, QtCore #PyQT5 19 | from PyQt5.QtWidgets import QTableWidgetItem 20 | #from PyQt5 import QApplication, QMainWindow, QGridLayout, QWidget, QTableWidget, QTableWidgetItem ? 21 | 22 | import design #Наш конвертированный файл дизайна 23 | from design import Ui_MainWindow # Наш сгенерированный файл дизайна 24 | 25 | ### General: 26 | # Time: 27 | #import time 28 | #from time import time 29 | #from datetime import timedelta 30 | 31 | # Additional GUI: 32 | import sys #Для передачи argv в QApplication 33 | import os # Для отображения содержимого директории 34 | 35 | #-#-# 36 | 37 | 38 | ##### Variables + Initialisations: 39 | 40 | ### Global variables list: 41 | global prodList, prodListNumb, \ 42 | prodOld, prodCurr 43 | 44 | # GUI: 45 | prodList = [] #Массив типов продукции 46 | prodListNumb = 0 #Количество типов продукции 47 | 48 | prodOld = '' 49 | prodCurr = '' 50 | 51 | #-#-# 52 | 53 | 54 | ##### Classes: 55 | 56 | ### Вставка обработанного видео: 57 | # Адаптировано из ответа на вопрос https://stackoverflow.com/questions/39303008/load-an-opencv-video-frame-by-frame-using-pyqt 58 | class VideoCapture(QtWidgets.QWidget): 59 | def __init__(self, filename, parent): 60 | #super(QtWidgets.QWidget, self).__init__() 61 | super(VideoCapture, self).__init__(parent) 62 | self.cap = cv.VideoCapture(str(filename)) 63 | self.video_frame = QtWidgets.QLabel() 64 | parent.layout.addWidget(self.video_frame) 65 | 66 | def nextFrameSlot(self): 67 | ret, frame = self.cap.read() 68 | if ret == True: 69 | isRet = True 70 | frame = FrameProcessor.FrameProcess(frame, isRet) 71 | frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB) 72 | img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888) 73 | pix = QtGui.QPixmap.fromImage(img) 74 | self.video_frame.setPixmap(pix) 75 | else: 76 | isRet = False 77 | FrameProcessor.FrameProcess(frame, isRet) 78 | 79 | #else: 80 | #return 0 81 | 82 | def start(self, parent): 83 | # Timer for Frame update: 84 | self.timer = QtCore.QTimer() 85 | self.timer.timeout.connect(self.nextFrameSlot) 86 | self.timer.start(30) # Warning float => int ??? 87 | 88 | # Timer for Text update: 89 | self.timer2 = QtCore.QTimer() 90 | self.timer2.timeout.connect(parent.changeText) 91 | self.timer2.start(30) # Warning float => int ??? 92 | 93 | def pause(self): 94 | self.timer.stop() 95 | 96 | def deleteLater(self): 97 | self.cap.release() 98 | super(QtWidgets.QWidget, self).deleteLater() 99 | 100 | 101 | ### Шаблон экрана: 102 | class ExampleApp(QtWidgets.QMainWindow, design.Ui_MainWindow): 103 | def __init__(self): 104 | global tableIsObjectData 105 | 106 | # Для доступа к переменным, методам и т.д. в файле design.py 107 | super(ExampleApp, self).__init__() 108 | self.setupUi(self) # Для инициализации нашего дизайна 109 | 110 | # Инициализация переменных: 111 | FrameProcessor.Initialize() # Переход на файл с обработкой видео 112 | 113 | 114 | ### Собственные привязки в GUI: 115 | # Кнопки: 116 | self.btnStart.clicked.connect(self.startCount) #Начать счёт 117 | self.btnStop.clicked.connect(self.stopCount) #Остановить счёт 118 | 119 | self.btnEnCalibrParam.clicked.connect(self.showParamList) #Показать/Скрыть параметры калибровки 120 | self.btnCatalog.clicked.connect(self.updateProdList) #Обновить каталог(В будущем открыть каталог) 121 | 122 | # Строки: 123 | #self.numberProductInBox.setFont(QtGui.QFont('SansSerif', 30)) # Изменение шрифта и размера 124 | #self.numberProductCons.setFont(QtGui.QFont('SansSerif', 20)) # Изменение шрифта и размера 125 | #self.numberProductAll.setFont(QtGui.QFont('SansSerif', 15)) # Изменение шрифта и размера 126 | #self.timer.setFont(QtGui.QFont('SansSerif', 20)) # Изменение шрифта и размера 127 | #self.label.setGeometry(QtCore.QRect(10, 10, 200, 200)) # Размеры 128 | 129 | # Таблицы: 130 | self.tableIsObject.clear() # Очистить ячейки таблицы 131 | tableIsObjectData = ['hi', 'hi'] # Подготовка данных для ввода в таблицу 132 | for id,text in enumerate(tableIsObjectData): # Ввод данных в таблицу 133 | # Enumerate - Индексирование (id) элементов списка (text) 134 | text = str(text) # Преобразование в текст (т. к. enumerate преобразует текст в последоват-ть знаков) 135 | item = QTableWidgetItem(text) # item = значение text в текущем id 136 | self.tableIsObject.setItem(0, id, item) # Присваивание item в ячейку таблицы 137 | 138 | self.tableIsNoise.clear() # Очистить ячейки таблицы 139 | tableIsNoiseData = ['hi', 'hi'] # Подготовка данных для ввода в таблицу 140 | for id,text in enumerate(tableIsNoiseData): # Ввод данных в таблицу 141 | # Enumerate - Индексирование (id) элементов списка (text) 142 | text = str(text) # Преобразование в текст (т. к. enumerate преобразует текст в последоват-ть знаков) 143 | item = QTableWidgetItem(text) # item = значение text в текущем id 144 | self.tableIsNoise.setItem(0, id, item) # Присваивание item в ячейку таблицы 145 | 146 | self.tableZoneCount.clear() # Очистить ячейки таблицы 147 | tableZoneCountData = [['hi', 'hi'], 148 | ['hi', 'hi']] # Подготовка данных для ввода в таблицу 149 | for id1,text1 in enumerate(tableZoneCountData): # Ввод данных в таблицу 150 | # Enumerate - Индексирование (id) элементов списка (text) 151 | for id2,text2 in enumerate(text1): # Ввод данных в таблицу 152 | # Enumerate - Индексирование (id) элементов списка (text) 153 | text2 = str(text2) # Преобразование в текст (т. к. enumerate преобразует текст в последоват-ть знаков) 154 | item = QTableWidgetItem(text2) # item = значение text в текущем id 155 | self.tableZoneCount.setItem(id1, id2, item) # Присваивание item в ячейку таблицы 156 | 157 | self.tableZoneRef.clear() # Очистить ячейки таблицы 158 | tableZoneRefData = ['hi', 'hi', 'hi'] # Подготовка данных для ввода в таблицу 159 | for id,text in enumerate(tableZoneRefData): # Ввод данных в таблицу 160 | # Enumerate - Индексирование (id) элементов списка (text) 161 | text = str(text) # Преобразование в текст (т. к. enumerate преобразует текст в последоват-ть знаков) 162 | item = QTableWidgetItem(text) # item = значение text в текущем id 163 | self.tableZoneRef.setItem(0, id, item) # Присваивание item в ячейку таблицы 164 | 165 | self.tableRefColourBord.clear() # Очистить ячейки таблицы 166 | tableRefColourBordData = [['hi', 'hi', 'hi'], 167 | ['hi', 'hi', 'hi']] # Подготовка данных для ввода в таблицу 168 | for id1,text1 in enumerate(tableRefColourBordData): # Ввод данных в таблицу 169 | # Enumerate - Индексирование (id) элементов списка (text) 170 | for id2,text2 in enumerate(text1): # Ввод данных в таблицу 171 | # Enumerate - Индексирование (id) элементов списка (text) 172 | text2 = str(text2) # Преобразование в текст (т. к. enumerate преобразует текст в последоват-ть знаков) 173 | item = QTableWidgetItem(text2) # item = значение text в текущем id 174 | self.tableRefColourBord.setItem(id1, id2, item) # Присваивание item в ячейку таблицы 175 | 176 | 177 | ### Запуск функций для инициализации окна GUI: 178 | self.updateProdList() 179 | self.changeText() 180 | 181 | # Скрыть параметры калибровки: 182 | self.showParamList() 183 | 184 | 185 | ### Инициализация видеофрейма: 186 | self.videoFileName = "cutted.avi" 187 | self.capture = None 188 | self.startCapture() 189 | 190 | 191 | def changeText(self): 192 | global tableIsObjectData 193 | 194 | ### Обновить текст в GUI: 195 | # Получить текст из файла FrameProcessor: 196 | guiVars = FrameProcessor.GetVariable() 197 | ''' 198 | print (guiVars) # For debugging 199 | ''' 200 | 201 | # Обновить текст в окнах: 202 | self.numberProductInBox.setText(str(guiVars[0])) # Количество продукта в коробке 203 | self.numberProductCons.setText(str(guiVars[1])) # Количество продукта в партии 204 | self.numberProductAll.setText(str(guiVars[2])) # Количество продукта всего 205 | self.timer.setText(str(guiVars[3])) # Время с момента запуска программы 206 | 207 | self.numberPixels.setText(str(guiVars[4])) # Количество "белых" пикселей 208 | self.refColourHSV.setText(str(guiVars[5])) # Опорный цвет (HSV) 209 | 210 | 211 | # Обновить текст в таблицах: 212 | #Порог наличия объекта: 213 | self.tableIsObject.setItem(0, 0, QTableWidgetItem(str(guiVars[6]))) 214 | self.tableIsObject.setItem(0, 1, QTableWidgetItem(str(guiVars[7]))) 215 | 216 | #Порог наличия шумов: 217 | self.tableIsNoise.setItem(0, 0, QTableWidgetItem(str(guiVars[8]))) 218 | self.tableIsNoise.setItem(0, 1, QTableWidgetItem(str(guiVars[9]))) 219 | 220 | #Положение Зоны подсчёта: 221 | for id1,text1 in enumerate(guiVars[10]): # Ввод данных в таблицу 222 | # Enumerate - Индексирование (id) элементов списка (text) 223 | for id2,text2 in enumerate(text1): # Ввод данных в таблицу 224 | # Enumerate - Индексирование (id) элементов списка (text) 225 | text2 = str(text2) # Преобразование в текст (т. к. enumerate преобразует текст в последоват-ть знаков) 226 | item = QTableWidgetItem(text2) # item = значение text в текущем id 227 | self.tableZoneCount.setItem(id1, id2, item) # Присваивание item в ячейку таблицы 228 | 229 | #Положение Опорной зоны 230 | self.tableZoneRef.setItem(0, 0, QTableWidgetItem(str(guiVars[11]))) 231 | self.tableZoneRef.setItem(0, 1, QTableWidgetItem(str(guiVars[12]))) 232 | self.tableZoneRef.setItem(0, 2, QTableWidgetItem(str(guiVars[13]))) 233 | 234 | 235 | #Границы опорного цвета: 236 | for id,text in enumerate(guiVars[14]): # Ввод данных в таблицу 237 | # Enumerate - Индексирование (id) элементов списка (text) 238 | text = str(text) # Преобразование в текст (т. к. enumerate преобразует текст в последоват-ть знаков) 239 | item = QTableWidgetItem(text) # item = значение text в текущем id 240 | self.tableRefColourBord.setItem(0, id, item) # Присваивание item в ячейку таблицы 241 | 242 | for id,text in enumerate(guiVars[15]): # Ввод данных в таблицу 243 | # Enumerate - Индексирование (id) элементов списка (text) 244 | text = str(text) # Преобразование в текст (т. к. enumerate преобразует текст в последоват-ть знаков) 245 | item = QTableWidgetItem(text) # item = значение text в текущем id 246 | self.tableRefColourBord.setItem(1, id, item) # Присваивание item в ячейку таблицы 247 | 248 | 249 | ### Текущий выбранный продукт: 250 | global prodList, prodListNumb, \ 251 | prodCurr, prodOld 252 | prodOld = prodCurr 253 | prodCurr = self.listProduct.currentText() #Текущий выбранный из списка в GUI (listProduct) продукт 254 | ''' 255 | print (prodCurr) # For debugging 256 | ''' 257 | 258 | 259 | def startCapture(self): 260 | if not self.capture: 261 | self.capture = VideoCapture(self.videoFileName, self.videoContainer) 262 | self.capture.start(self) 263 | 264 | 265 | def updateProdList(self): # Обновить список типов продукции: 266 | global prodList, prodListNumb, \ 267 | prodCurr, prodOld 268 | 269 | #directory = QtWidgets.QFileDialog.getExistingDirectory(self, 'IDlist directory', 'IDlist/') 270 | directory = os.getcwd() + '\prodList' #Выбор директории расположения списка продукции: 271 | #Текущая директория скрипта + \папка хранения файлов продукции 272 | 273 | #if directory: # не продолжать выполнение, если нет директории (Что-то проверить) 274 | prodList.clear() #Очистка массива типов продукции (от старого и на всякий случай) 275 | self.listProduct.clear() # Очистка списка типов продукции в GUI (listProduct - из design.py) (от старого и на всякий случай) 276 | 277 | for file_name in os.listdir(directory): #Для каждого файла в директории 278 | x = file_name 279 | x = x.partition('.')[0] 280 | prodList.append(x) 281 | self.listProduct.addItem(x) 282 | 283 | prodListNumb = len(prodList) # Количество найденных типов продуктов 284 | 285 | self.changeText() 286 | 287 | #prodOld = prodCurr 288 | #prodCurr = self.listProduct.currentText() #Текущий выбранный из списка в GUI (listProduct) продукт 289 | 290 | #currN = self.listID.currentIndex() #Номер выбранного продукта (порядковый номер из списка) 291 | #print (prodList[currN]) 292 | 293 | ''' 294 | print (prodListNumb) #For debugging 295 | print (prodList) #For debugging 296 | print (prodCurr) #For debugging 297 | ''' 298 | 299 | #curr = IDlist[self.listID.currentIndex()] 300 | #curr = IDlist[currN] 301 | #print (curr) 302 | 303 | 304 | 305 | def showParamList(self): # Показать/Скрыть панель параметров калибровки 306 | if self.btnEnCalibrParam.isChecked(): 307 | self.tableIsObject.show() 308 | self.label_10.show() 309 | self.tableZoneCount.show() 310 | self.label_17.show() 311 | self.tableRefColourBord.show() 312 | self.label_18.show() 313 | # 314 | self.label_16.show() 315 | self.tableIsNoise.show() 316 | self.label_11.show() 317 | self.tableZoneRef.show() 318 | self.label_13.show() 319 | self.numberPixels.show() 320 | self.label_12.show() 321 | self.refColourHSV.show() 322 | else: 323 | self.tableIsObject.hide() 324 | self.label_10.hide() 325 | self.tableZoneCount.hide() 326 | self.label_17.hide() 327 | self.tableRefColourBord.hide() 328 | self.label_18.hide() 329 | # 330 | self.label_16.hide() 331 | self.tableIsNoise.hide() 332 | self.label_11.hide() 333 | self.tableZoneRef.hide() 334 | self.label_13.hide() 335 | self.numberPixels.hide() 336 | self.label_12.hide() 337 | self.refColourHSV.hide() 338 | 339 | self.adjustSize() 340 | 341 | 342 | def startCount(self): # Начать счёт 343 | 344 | self.adjustSize() 345 | 346 | #self.adjustSize() 347 | #return 0 348 | 349 | 350 | def stopCount(self): # Остановка по введённому коду 351 | #self.widget.show() 352 | self.centralwidget.adjustSize() 353 | 354 | 355 | return 0 356 | 357 | #sys.exit() 358 | 359 | #-#-# 360 | 361 | 362 | ##### Main: 363 | 364 | def main(): 365 | app = QtWidgets.QApplication(sys.argv) # Новый экземпляр QApplication 366 | window = ExampleApp() # Создаём объект класса ExampleApp 367 | #window.setWindowTitle("ОмБекон: Счёт продукции, конвейер №х") 368 | window.show() # Показываем окно 369 | window.inputProductNumber.setFocus() 370 | 371 | #adjustSize() 372 | 373 | sys.exit(app.exec_()) # и запускаем приложение ??? 374 | 375 | #-#-# 376 | 377 | 378 | ##### Доп штуки: 379 | 380 | if __name__ == '__main__': # Если мы запускаем файл напрямую, а не импортируем 381 | main() # то запускаем функцию main() 382 | 383 | def keyPressEvent(self, e): # НЕ РАБОТАЕТ 384 | if e.key() == Qt.Key_F12: 385 | self.close() 386 | 387 | #-#-# 388 | -------------------------------------------------------------------------------- /design.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'design.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.14.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | 10 | from PyQt5 import QtCore, QtGui, QtWidgets 11 | 12 | 13 | # Class for video stream 14 | class VideoDisplayWidget(QtWidgets.QWidget): 15 | def __init__(self,parent): 16 | super(VideoDisplayWidget, self).__init__(parent) 17 | self.layout = QtWidgets.QFormLayout(self) 18 | self.setLayout(self.layout) 19 | 20 | 21 | class Ui_MainWindow(object): 22 | def setupUi(self, MainWindow): 23 | MainWindow.setObjectName("MainWindow") 24 | MainWindow.resize(920, 640) 25 | MainWindow.setMinimumSize(QtCore.QSize(920, 640)) 26 | MainWindow.setMaximumSize(QtCore.QSize(1280, 1024)) 27 | palette = QtGui.QPalette() 28 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 29 | brush.setStyle(QtCore.Qt.SolidPattern) 30 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush) 31 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 32 | brush.setStyle(QtCore.Qt.SolidPattern) 33 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush) 34 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 35 | brush.setStyle(QtCore.Qt.SolidPattern) 36 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush) 37 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 38 | brush.setStyle(QtCore.Qt.SolidPattern) 39 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush) 40 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 41 | brush.setStyle(QtCore.Qt.SolidPattern) 42 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush) 43 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 44 | brush.setStyle(QtCore.Qt.SolidPattern) 45 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush) 46 | MainWindow.setPalette(palette) 47 | MainWindow.setAutoFillBackground(True) 48 | self.centralwidget = QtWidgets.QWidget(MainWindow) 49 | self.centralwidget.setObjectName("centralwidget") 50 | self.verticalLayoutWidget_7 = QtWidgets.QWidget(self.centralwidget) 51 | self.verticalLayoutWidget_7.setGeometry(QtCore.QRect(10, 10, 901, 621)) 52 | self.verticalLayoutWidget_7.setObjectName("verticalLayoutWidget_7") 53 | self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_7) 54 | self.verticalLayout_7.setContentsMargins(0, 0, 0, 0) 55 | self.verticalLayout_7.setSpacing(10) 56 | self.verticalLayout_7.setObjectName("verticalLayout_7") 57 | self.horizontalLayout_4 = QtWidgets.QHBoxLayout() 58 | self.horizontalLayout_4.setSpacing(20) 59 | self.horizontalLayout_4.setObjectName("horizontalLayout_4") 60 | self.verticalLayout_10 = QtWidgets.QVBoxLayout() 61 | self.verticalLayout_10.setSpacing(6) 62 | self.verticalLayout_10.setObjectName("verticalLayout_10") 63 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout() 64 | self.horizontalLayout_2.setSpacing(20) 65 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 66 | self.verticalLayout_11 = QtWidgets.QVBoxLayout() 67 | self.verticalLayout_11.setSpacing(2) 68 | self.verticalLayout_11.setObjectName("verticalLayout_11") 69 | self.label_10 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 70 | self.label_10.setMinimumSize(QtCore.QSize(50, 20)) 71 | self.label_10.setMaximumSize(QtCore.QSize(200, 20)) 72 | font = QtGui.QFont() 73 | font.setFamily("Segoe UI") 74 | font.setPointSize(8) 75 | self.label_10.setFont(font) 76 | self.label_10.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 77 | self.label_10.setObjectName("label_10") 78 | self.verticalLayout_11.addWidget(self.label_10) 79 | self.tableIsObject = QtWidgets.QTableWidget(self.verticalLayoutWidget_7) 80 | self.tableIsObject.setMinimumSize(QtCore.QSize(200, 50)) 81 | self.tableIsObject.setMaximumSize(QtCore.QSize(200, 50)) 82 | self.tableIsObject.setFrameShape(QtWidgets.QFrame.StyledPanel) 83 | self.tableIsObject.setTabKeyNavigation(False) 84 | self.tableIsObject.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) 85 | self.tableIsObject.setObjectName("tableIsObject") 86 | self.tableIsObject.setColumnCount(2) 87 | self.tableIsObject.setRowCount(1) 88 | item = QtWidgets.QTableWidgetItem() 89 | self.tableIsObject.setVerticalHeaderItem(0, item) 90 | item = QtWidgets.QTableWidgetItem() 91 | self.tableIsObject.setHorizontalHeaderItem(0, item) 92 | item = QtWidgets.QTableWidgetItem() 93 | self.tableIsObject.setHorizontalHeaderItem(1, item) 94 | item = QtWidgets.QTableWidgetItem() 95 | item.setTextAlignment(QtCore.Qt.AlignCenter) 96 | self.tableIsObject.setItem(0, 0, item) 97 | item = QtWidgets.QTableWidgetItem() 98 | item.setTextAlignment(QtCore.Qt.AlignCenter) 99 | self.tableIsObject.setItem(0, 1, item) 100 | self.tableIsObject.horizontalHeader().setDefaultSectionSize(99) 101 | self.tableIsObject.horizontalHeader().setHighlightSections(False) 102 | self.tableIsObject.horizontalHeader().setMinimumSectionSize(99) 103 | self.tableIsObject.horizontalHeader().setStretchLastSection(False) 104 | self.tableIsObject.verticalHeader().setVisible(False) 105 | self.tableIsObject.verticalHeader().setDefaultSectionSize(30) 106 | self.tableIsObject.verticalHeader().setHighlightSections(False) 107 | self.tableIsObject.verticalHeader().setMinimumSectionSize(30) 108 | self.tableIsObject.verticalHeader().setStretchLastSection(True) 109 | self.verticalLayout_11.addWidget(self.tableIsObject) 110 | self.horizontalLayout_2.addLayout(self.verticalLayout_11) 111 | self.verticalLayout_12 = QtWidgets.QVBoxLayout() 112 | self.verticalLayout_12.setSpacing(2) 113 | self.verticalLayout_12.setObjectName("verticalLayout_12") 114 | self.label_16 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 115 | self.label_16.setMinimumSize(QtCore.QSize(50, 20)) 116 | self.label_16.setMaximumSize(QtCore.QSize(200, 20)) 117 | font = QtGui.QFont() 118 | font.setFamily("Segoe UI") 119 | font.setPointSize(8) 120 | self.label_16.setFont(font) 121 | self.label_16.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 122 | self.label_16.setObjectName("label_16") 123 | self.verticalLayout_12.addWidget(self.label_16) 124 | self.tableIsNoise = QtWidgets.QTableWidget(self.verticalLayoutWidget_7) 125 | self.tableIsNoise.setMinimumSize(QtCore.QSize(200, 50)) 126 | self.tableIsNoise.setMaximumSize(QtCore.QSize(200, 50)) 127 | self.tableIsNoise.setFrameShape(QtWidgets.QFrame.StyledPanel) 128 | self.tableIsNoise.setTabKeyNavigation(False) 129 | self.tableIsNoise.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) 130 | self.tableIsNoise.setObjectName("tableIsNoise") 131 | self.tableIsNoise.setColumnCount(2) 132 | self.tableIsNoise.setRowCount(1) 133 | item = QtWidgets.QTableWidgetItem() 134 | self.tableIsNoise.setVerticalHeaderItem(0, item) 135 | item = QtWidgets.QTableWidgetItem() 136 | self.tableIsNoise.setHorizontalHeaderItem(0, item) 137 | item = QtWidgets.QTableWidgetItem() 138 | self.tableIsNoise.setHorizontalHeaderItem(1, item) 139 | item = QtWidgets.QTableWidgetItem() 140 | item.setTextAlignment(QtCore.Qt.AlignCenter) 141 | self.tableIsNoise.setItem(0, 0, item) 142 | item = QtWidgets.QTableWidgetItem() 143 | item.setTextAlignment(QtCore.Qt.AlignCenter) 144 | self.tableIsNoise.setItem(0, 1, item) 145 | self.tableIsNoise.horizontalHeader().setDefaultSectionSize(99) 146 | self.tableIsNoise.horizontalHeader().setHighlightSections(False) 147 | self.tableIsNoise.horizontalHeader().setMinimumSectionSize(99) 148 | self.tableIsNoise.horizontalHeader().setStretchLastSection(False) 149 | self.tableIsNoise.verticalHeader().setVisible(False) 150 | self.tableIsNoise.verticalHeader().setDefaultSectionSize(30) 151 | self.tableIsNoise.verticalHeader().setHighlightSections(False) 152 | self.tableIsNoise.verticalHeader().setMinimumSectionSize(30) 153 | self.tableIsNoise.verticalHeader().setStretchLastSection(True) 154 | self.verticalLayout_12.addWidget(self.tableIsNoise) 155 | self.horizontalLayout_2.addLayout(self.verticalLayout_12) 156 | self.verticalLayout_10.addLayout(self.horizontalLayout_2) 157 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout() 158 | self.horizontalLayout_3.setSpacing(20) 159 | self.horizontalLayout_3.setObjectName("horizontalLayout_3") 160 | self.verticalLayout_13 = QtWidgets.QVBoxLayout() 161 | self.verticalLayout_13.setSpacing(2) 162 | self.verticalLayout_13.setObjectName("verticalLayout_13") 163 | self.label_17 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 164 | self.label_17.setMinimumSize(QtCore.QSize(50, 20)) 165 | self.label_17.setMaximumSize(QtCore.QSize(200, 20)) 166 | font = QtGui.QFont() 167 | font.setFamily("Segoe UI") 168 | font.setPointSize(8) 169 | self.label_17.setFont(font) 170 | self.label_17.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 171 | self.label_17.setObjectName("label_17") 172 | self.verticalLayout_13.addWidget(self.label_17) 173 | self.tableZoneCount = QtWidgets.QTableWidget(self.verticalLayoutWidget_7) 174 | self.tableZoneCount.setMinimumSize(QtCore.QSize(200, 90)) 175 | self.tableZoneCount.setMaximumSize(QtCore.QSize(200, 90)) 176 | self.tableZoneCount.setFrameShape(QtWidgets.QFrame.StyledPanel) 177 | self.tableZoneCount.setTabKeyNavigation(False) 178 | self.tableZoneCount.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) 179 | self.tableZoneCount.setObjectName("tableZoneCount") 180 | self.tableZoneCount.setColumnCount(2) 181 | self.tableZoneCount.setRowCount(2) 182 | item = QtWidgets.QTableWidgetItem() 183 | self.tableZoneCount.setVerticalHeaderItem(0, item) 184 | item = QtWidgets.QTableWidgetItem() 185 | self.tableZoneCount.setVerticalHeaderItem(1, item) 186 | item = QtWidgets.QTableWidgetItem() 187 | self.tableZoneCount.setHorizontalHeaderItem(0, item) 188 | item = QtWidgets.QTableWidgetItem() 189 | self.tableZoneCount.setHorizontalHeaderItem(1, item) 190 | item = QtWidgets.QTableWidgetItem() 191 | item.setTextAlignment(QtCore.Qt.AlignCenter) 192 | self.tableZoneCount.setItem(0, 0, item) 193 | item = QtWidgets.QTableWidgetItem() 194 | item.setTextAlignment(QtCore.Qt.AlignCenter) 195 | self.tableZoneCount.setItem(0, 1, item) 196 | item = QtWidgets.QTableWidgetItem() 197 | item.setTextAlignment(QtCore.Qt.AlignCenter) 198 | self.tableZoneCount.setItem(1, 0, item) 199 | item = QtWidgets.QTableWidgetItem() 200 | item.setTextAlignment(QtCore.Qt.AlignCenter) 201 | self.tableZoneCount.setItem(1, 1, item) 202 | self.tableZoneCount.horizontalHeader().setDefaultSectionSize(90) 203 | self.tableZoneCount.horizontalHeader().setMinimumSectionSize(90) 204 | self.tableZoneCount.horizontalHeader().setStretchLastSection(True) 205 | self.tableZoneCount.verticalHeader().setVisible(True) 206 | self.tableZoneCount.verticalHeader().setCascadingSectionResizes(False) 207 | self.tableZoneCount.verticalHeader().setDefaultSectionSize(30) 208 | self.tableZoneCount.verticalHeader().setHighlightSections(True) 209 | self.tableZoneCount.verticalHeader().setMinimumSectionSize(30) 210 | self.tableZoneCount.verticalHeader().setSortIndicatorShown(False) 211 | self.tableZoneCount.verticalHeader().setStretchLastSection(True) 212 | self.verticalLayout_13.addWidget(self.tableZoneCount) 213 | self.horizontalLayout_3.addLayout(self.verticalLayout_13) 214 | self.verticalLayout_15 = QtWidgets.QVBoxLayout() 215 | self.verticalLayout_15.setSpacing(2) 216 | self.verticalLayout_15.setObjectName("verticalLayout_15") 217 | self.label_11 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 218 | self.label_11.setMinimumSize(QtCore.QSize(50, 20)) 219 | self.label_11.setMaximumSize(QtCore.QSize(200, 20)) 220 | font = QtGui.QFont() 221 | font.setFamily("Segoe UI") 222 | font.setPointSize(8) 223 | self.label_11.setFont(font) 224 | self.label_11.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 225 | self.label_11.setObjectName("label_11") 226 | self.verticalLayout_15.addWidget(self.label_11) 227 | self.tableZoneRef = QtWidgets.QTableWidget(self.verticalLayoutWidget_7) 228 | self.tableZoneRef.setMinimumSize(QtCore.QSize(200, 50)) 229 | self.tableZoneRef.setMaximumSize(QtCore.QSize(200, 50)) 230 | self.tableZoneRef.setTabKeyNavigation(False) 231 | self.tableZoneRef.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) 232 | self.tableZoneRef.setObjectName("tableZoneRef") 233 | self.tableZoneRef.setColumnCount(3) 234 | self.tableZoneRef.setRowCount(1) 235 | item = QtWidgets.QTableWidgetItem() 236 | self.tableZoneRef.setVerticalHeaderItem(0, item) 237 | item = QtWidgets.QTableWidgetItem() 238 | self.tableZoneRef.setHorizontalHeaderItem(0, item) 239 | item = QtWidgets.QTableWidgetItem() 240 | self.tableZoneRef.setHorizontalHeaderItem(1, item) 241 | item = QtWidgets.QTableWidgetItem() 242 | self.tableZoneRef.setHorizontalHeaderItem(2, item) 243 | item = QtWidgets.QTableWidgetItem() 244 | item.setTextAlignment(QtCore.Qt.AlignCenter) 245 | self.tableZoneRef.setItem(0, 0, item) 246 | item = QtWidgets.QTableWidgetItem() 247 | item.setTextAlignment(QtCore.Qt.AlignCenter) 248 | self.tableZoneRef.setItem(0, 1, item) 249 | item = QtWidgets.QTableWidgetItem() 250 | item.setTextAlignment(QtCore.Qt.AlignCenter) 251 | self.tableZoneRef.setItem(0, 2, item) 252 | self.tableZoneRef.horizontalHeader().setDefaultSectionSize(66) 253 | self.tableZoneRef.horizontalHeader().setMinimumSectionSize(66) 254 | self.tableZoneRef.horizontalHeader().setStretchLastSection(True) 255 | self.tableZoneRef.verticalHeader().setVisible(False) 256 | self.tableZoneRef.verticalHeader().setMinimumSectionSize(30) 257 | self.tableZoneRef.verticalHeader().setStretchLastSection(True) 258 | self.verticalLayout_15.addWidget(self.tableZoneRef) 259 | self.horizontalLayout_3.addLayout(self.verticalLayout_15) 260 | self.verticalLayout_10.addLayout(self.horizontalLayout_3) 261 | self.horizontalLayout_5 = QtWidgets.QHBoxLayout() 262 | self.horizontalLayout_5.setSpacing(20) 263 | self.horizontalLayout_5.setObjectName("horizontalLayout_5") 264 | self.verticalLayout_14 = QtWidgets.QVBoxLayout() 265 | self.verticalLayout_14.setSpacing(2) 266 | self.verticalLayout_14.setObjectName("verticalLayout_14") 267 | self.label_18 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 268 | self.label_18.setMinimumSize(QtCore.QSize(50, 20)) 269 | self.label_18.setMaximumSize(QtCore.QSize(200, 20)) 270 | font = QtGui.QFont() 271 | font.setFamily("Segoe UI") 272 | font.setPointSize(8) 273 | self.label_18.setFont(font) 274 | self.label_18.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 275 | self.label_18.setObjectName("label_18") 276 | self.verticalLayout_14.addWidget(self.label_18) 277 | self.tableRefColourBord = QtWidgets.QTableWidget(self.verticalLayoutWidget_7) 278 | self.tableRefColourBord.setMinimumSize(QtCore.QSize(200, 90)) 279 | self.tableRefColourBord.setMaximumSize(QtCore.QSize(200, 90)) 280 | self.tableRefColourBord.setFrameShape(QtWidgets.QFrame.StyledPanel) 281 | self.tableRefColourBord.setTabKeyNavigation(False) 282 | self.tableRefColourBord.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) 283 | self.tableRefColourBord.setGridStyle(QtCore.Qt.SolidLine) 284 | self.tableRefColourBord.setObjectName("tableRefColourBord") 285 | self.tableRefColourBord.setColumnCount(3) 286 | self.tableRefColourBord.setRowCount(2) 287 | item = QtWidgets.QTableWidgetItem() 288 | self.tableRefColourBord.setVerticalHeaderItem(0, item) 289 | item = QtWidgets.QTableWidgetItem() 290 | self.tableRefColourBord.setVerticalHeaderItem(1, item) 291 | item = QtWidgets.QTableWidgetItem() 292 | self.tableRefColourBord.setHorizontalHeaderItem(0, item) 293 | item = QtWidgets.QTableWidgetItem() 294 | self.tableRefColourBord.setHorizontalHeaderItem(1, item) 295 | item = QtWidgets.QTableWidgetItem() 296 | self.tableRefColourBord.setHorizontalHeaderItem(2, item) 297 | item = QtWidgets.QTableWidgetItem() 298 | item.setTextAlignment(QtCore.Qt.AlignCenter) 299 | self.tableRefColourBord.setItem(0, 0, item) 300 | item = QtWidgets.QTableWidgetItem() 301 | item.setTextAlignment(QtCore.Qt.AlignCenter) 302 | self.tableRefColourBord.setItem(0, 1, item) 303 | item = QtWidgets.QTableWidgetItem() 304 | item.setTextAlignment(QtCore.Qt.AlignCenter) 305 | self.tableRefColourBord.setItem(0, 2, item) 306 | item = QtWidgets.QTableWidgetItem() 307 | item.setTextAlignment(QtCore.Qt.AlignCenter) 308 | self.tableRefColourBord.setItem(1, 0, item) 309 | item = QtWidgets.QTableWidgetItem() 310 | item.setTextAlignment(QtCore.Qt.AlignCenter) 311 | self.tableRefColourBord.setItem(1, 1, item) 312 | item = QtWidgets.QTableWidgetItem() 313 | item.setTextAlignment(QtCore.Qt.AlignCenter) 314 | self.tableRefColourBord.setItem(1, 2, item) 315 | self.tableRefColourBord.horizontalHeader().setDefaultSectionSize(55) 316 | self.tableRefColourBord.horizontalHeader().setMinimumSectionSize(55) 317 | self.tableRefColourBord.horizontalHeader().setStretchLastSection(True) 318 | self.tableRefColourBord.verticalHeader().setVisible(True) 319 | self.tableRefColourBord.verticalHeader().setDefaultSectionSize(30) 320 | self.tableRefColourBord.verticalHeader().setMinimumSectionSize(30) 321 | self.tableRefColourBord.verticalHeader().setStretchLastSection(True) 322 | self.verticalLayout_14.addWidget(self.tableRefColourBord) 323 | self.horizontalLayout_5.addLayout(self.verticalLayout_14) 324 | self.verticalLayout_16 = QtWidgets.QVBoxLayout() 325 | self.verticalLayout_16.setSpacing(2) 326 | self.verticalLayout_16.setObjectName("verticalLayout_16") 327 | self.horizontalLayout_7 = QtWidgets.QHBoxLayout() 328 | self.horizontalLayout_7.setSpacing(6) 329 | self.horizontalLayout_7.setObjectName("horizontalLayout_7") 330 | self.label_13 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 331 | self.label_13.setMinimumSize(QtCore.QSize(120, 20)) 332 | self.label_13.setMaximumSize(QtCore.QSize(145, 20)) 333 | font = QtGui.QFont() 334 | font.setFamily("Segoe UI") 335 | font.setPointSize(8) 336 | self.label_13.setFont(font) 337 | self.label_13.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) 338 | self.label_13.setObjectName("label_13") 339 | self.horizontalLayout_7.addWidget(self.label_13) 340 | self.numberPixels = QtWidgets.QLabel(self.verticalLayoutWidget_7) 341 | self.numberPixels.setMinimumSize(QtCore.QSize(80, 30)) 342 | self.numberPixels.setMaximumSize(QtCore.QSize(80, 30)) 343 | font = QtGui.QFont() 344 | font.setFamily("Segoe UI") 345 | self.numberPixels.setFont(font) 346 | self.numberPixels.setObjectName("numberPixels") 347 | self.horizontalLayout_7.addWidget(self.numberPixels) 348 | self.verticalLayout_16.addLayout(self.horizontalLayout_7) 349 | self.horizontalLayout_8 = QtWidgets.QHBoxLayout() 350 | self.horizontalLayout_8.setSpacing(6) 351 | self.horizontalLayout_8.setObjectName("horizontalLayout_8") 352 | self.label_12 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 353 | self.label_12.setMinimumSize(QtCore.QSize(120, 20)) 354 | self.label_12.setMaximumSize(QtCore.QSize(145, 20)) 355 | font = QtGui.QFont() 356 | font.setFamily("Segoe UI") 357 | font.setPointSize(8) 358 | self.label_12.setFont(font) 359 | self.label_12.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 360 | self.label_12.setObjectName("label_12") 361 | self.horizontalLayout_8.addWidget(self.label_12) 362 | self.refColourHSV = QtWidgets.QLabel(self.verticalLayoutWidget_7) 363 | self.refColourHSV.setMinimumSize(QtCore.QSize(80, 30)) 364 | self.refColourHSV.setMaximumSize(QtCore.QSize(80, 30)) 365 | font = QtGui.QFont() 366 | font.setFamily("Segoe UI") 367 | self.refColourHSV.setFont(font) 368 | self.refColourHSV.setObjectName("refColourHSV") 369 | self.horizontalLayout_8.addWidget(self.refColourHSV) 370 | self.verticalLayout_16.addLayout(self.horizontalLayout_8) 371 | self.horizontalLayout_5.addLayout(self.verticalLayout_16) 372 | self.verticalLayout_10.addLayout(self.horizontalLayout_5) 373 | self.btnEnCalibrParam = QtWidgets.QPushButton(self.verticalLayoutWidget_7) 374 | self.btnEnCalibrParam.setMinimumSize(QtCore.QSize(150, 20)) 375 | self.btnEnCalibrParam.setMaximumSize(QtCore.QSize(200, 30)) 376 | font = QtGui.QFont() 377 | font.setFamily("Segoe UI") 378 | self.btnEnCalibrParam.setFont(font) 379 | self.btnEnCalibrParam.setCheckable(True) 380 | self.btnEnCalibrParam.setAutoRepeatDelay(50) 381 | self.btnEnCalibrParam.setAutoRepeatInterval(50) 382 | self.btnEnCalibrParam.setObjectName("btnEnCalibrParam") 383 | self.verticalLayout_10.addWidget(self.btnEnCalibrParam) 384 | self.horizontalLayout_4.addLayout(self.verticalLayout_10) 385 | 386 | 387 | # Video stream: 388 | self.videoContainer = VideoDisplayWidget(self) 389 | self.videoContainer.setObjectName("videoContainer") 390 | 391 | self.horizontalLayout_4.addWidget(self.videoContainer) 392 | 393 | 394 | self.verticalLayout_4 = QtWidgets.QVBoxLayout() 395 | self.verticalLayout_4.setSpacing(6) 396 | self.verticalLayout_4.setObjectName("verticalLayout_4") 397 | self.verticalLayout_8 = QtWidgets.QVBoxLayout() 398 | self.verticalLayout_8.setSpacing(2) 399 | self.verticalLayout_8.setObjectName("verticalLayout_8") 400 | self.label_7 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 401 | self.label_7.setMinimumSize(QtCore.QSize(50, 30)) 402 | self.label_7.setMaximumSize(QtCore.QSize(200, 30)) 403 | font = QtGui.QFont() 404 | font.setFamily("Segoe UI") 405 | font.setPointSize(12) 406 | self.label_7.setFont(font) 407 | self.label_7.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 408 | self.label_7.setObjectName("label_7") 409 | self.verticalLayout_8.addWidget(self.label_7) 410 | self.productCurr = QtWidgets.QLabel(self.verticalLayoutWidget_7) 411 | self.productCurr.setMinimumSize(QtCore.QSize(200, 50)) 412 | self.productCurr.setMaximumSize(QtCore.QSize(200, 50)) 413 | font = QtGui.QFont() 414 | font.setFamily("Segoe UI") 415 | font.setPointSize(12) 416 | self.productCurr.setFont(font) 417 | self.productCurr.setFrameShape(QtWidgets.QFrame.Box) 418 | self.productCurr.setAlignment(QtCore.Qt.AlignCenter) 419 | self.productCurr.setObjectName("productCurr") 420 | self.verticalLayout_8.addWidget(self.productCurr) 421 | self.verticalLayout_4.addLayout(self.verticalLayout_8) 422 | self.verticalLayout = QtWidgets.QVBoxLayout() 423 | self.verticalLayout.setSpacing(2) 424 | self.verticalLayout.setObjectName("verticalLayout") 425 | self.label_3 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 426 | self.label_3.setMinimumSize(QtCore.QSize(50, 30)) 427 | self.label_3.setMaximumSize(QtCore.QSize(200, 30)) 428 | font = QtGui.QFont() 429 | font.setFamily("Segoe UI") 430 | font.setPointSize(12) 431 | self.label_3.setFont(font) 432 | self.label_3.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 433 | self.label_3.setObjectName("label_3") 434 | self.verticalLayout.addWidget(self.label_3) 435 | self.numberProductInBox = QtWidgets.QLabel(self.verticalLayoutWidget_7) 436 | self.numberProductInBox.setMinimumSize(QtCore.QSize(200, 50)) 437 | self.numberProductInBox.setMaximumSize(QtCore.QSize(200, 50)) 438 | font = QtGui.QFont() 439 | font.setFamily("Segoe UI") 440 | font.setPointSize(14) 441 | self.numberProductInBox.setFont(font) 442 | self.numberProductInBox.setFrameShape(QtWidgets.QFrame.Box) 443 | self.numberProductInBox.setAlignment(QtCore.Qt.AlignCenter) 444 | self.numberProductInBox.setObjectName("numberProductInBox") 445 | self.verticalLayout.addWidget(self.numberProductInBox) 446 | self.verticalLayout_4.addLayout(self.verticalLayout) 447 | self.verticalLayout_3 = QtWidgets.QVBoxLayout() 448 | self.verticalLayout_3.setSpacing(2) 449 | self.verticalLayout_3.setObjectName("verticalLayout_3") 450 | self.label_4 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 451 | self.label_4.setMinimumSize(QtCore.QSize(50, 20)) 452 | self.label_4.setMaximumSize(QtCore.QSize(200, 20)) 453 | font = QtGui.QFont() 454 | font.setFamily("Segoe UI") 455 | font.setPointSize(10) 456 | self.label_4.setFont(font) 457 | self.label_4.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 458 | self.label_4.setObjectName("label_4") 459 | self.verticalLayout_3.addWidget(self.label_4) 460 | self.numberProductCons = QtWidgets.QLabel(self.verticalLayoutWidget_7) 461 | self.numberProductCons.setMinimumSize(QtCore.QSize(200, 30)) 462 | self.numberProductCons.setMaximumSize(QtCore.QSize(200, 30)) 463 | font = QtGui.QFont() 464 | font.setFamily("Segoe UI") 465 | font.setPointSize(12) 466 | self.numberProductCons.setFont(font) 467 | self.numberProductCons.setFrameShape(QtWidgets.QFrame.Box) 468 | self.numberProductCons.setFrameShadow(QtWidgets.QFrame.Plain) 469 | self.numberProductCons.setAlignment(QtCore.Qt.AlignCenter) 470 | self.numberProductCons.setObjectName("numberProductCons") 471 | self.verticalLayout_3.addWidget(self.numberProductCons) 472 | self.verticalLayout_4.addLayout(self.verticalLayout_3) 473 | self.verticalLayout_2 = QtWidgets.QVBoxLayout() 474 | self.verticalLayout_2.setSpacing(2) 475 | self.verticalLayout_2.setObjectName("verticalLayout_2") 476 | self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 477 | self.label_2.setMinimumSize(QtCore.QSize(50, 20)) 478 | self.label_2.setMaximumSize(QtCore.QSize(200, 20)) 479 | font = QtGui.QFont() 480 | font.setFamily("Segoe UI") 481 | font.setPointSize(10) 482 | self.label_2.setFont(font) 483 | self.label_2.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 484 | self.label_2.setObjectName("label_2") 485 | self.verticalLayout_2.addWidget(self.label_2) 486 | self.numberProductAll = QtWidgets.QLabel(self.verticalLayoutWidget_7) 487 | self.numberProductAll.setMinimumSize(QtCore.QSize(200, 30)) 488 | self.numberProductAll.setMaximumSize(QtCore.QSize(200, 30)) 489 | font = QtGui.QFont() 490 | font.setFamily("Segoe UI") 491 | font.setPointSize(12) 492 | self.numberProductAll.setFont(font) 493 | self.numberProductAll.setFrameShape(QtWidgets.QFrame.Box) 494 | self.numberProductAll.setAlignment(QtCore.Qt.AlignCenter) 495 | self.numberProductAll.setObjectName("numberProductAll") 496 | self.verticalLayout_2.addWidget(self.numberProductAll) 497 | self.verticalLayout_4.addLayout(self.verticalLayout_2) 498 | self.verticalLayout_5 = QtWidgets.QVBoxLayout() 499 | self.verticalLayout_5.setSpacing(2) 500 | self.verticalLayout_5.setObjectName("verticalLayout_5") 501 | self.label_6 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 502 | self.label_6.setMinimumSize(QtCore.QSize(50, 20)) 503 | self.label_6.setMaximumSize(QtCore.QSize(200, 20)) 504 | font = QtGui.QFont() 505 | font.setFamily("Segoe UI") 506 | font.setPointSize(10) 507 | self.label_6.setFont(font) 508 | self.label_6.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 509 | self.label_6.setObjectName("label_6") 510 | self.verticalLayout_5.addWidget(self.label_6) 511 | self.timer = QtWidgets.QLabel(self.verticalLayoutWidget_7) 512 | self.timer.setMinimumSize(QtCore.QSize(200, 30)) 513 | self.timer.setMaximumSize(QtCore.QSize(200, 30)) 514 | font = QtGui.QFont() 515 | font.setFamily("Segoe UI") 516 | font.setPointSize(12) 517 | self.timer.setFont(font) 518 | self.timer.setFrameShape(QtWidgets.QFrame.Box) 519 | self.timer.setAlignment(QtCore.Qt.AlignCenter) 520 | self.timer.setObjectName("timer") 521 | self.verticalLayout_5.addWidget(self.timer) 522 | self.verticalLayout_4.addLayout(self.verticalLayout_5) 523 | self.horizontalLayout_4.addLayout(self.verticalLayout_4) 524 | self.verticalLayout_7.addLayout(self.horizontalLayout_4) 525 | self.horizontalLayout = QtWidgets.QHBoxLayout() 526 | self.horizontalLayout.setObjectName("horizontalLayout") 527 | self.verticalLayout_9 = QtWidgets.QVBoxLayout() 528 | self.verticalLayout_9.setObjectName("verticalLayout_9") 529 | self.label_5 = QtWidgets.QLabel(self.verticalLayoutWidget_7) 530 | self.label_5.setMinimumSize(QtCore.QSize(350, 20)) 531 | self.label_5.setMaximumSize(QtCore.QSize(450, 20)) 532 | font = QtGui.QFont() 533 | font.setFamily("Segoe UI") 534 | font.setPointSize(12) 535 | self.label_5.setFont(font) 536 | self.label_5.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 537 | self.label_5.setObjectName("label_5") 538 | self.verticalLayout_9.addWidget(self.label_5) 539 | self.listProduct = QtWidgets.QComboBox(self.verticalLayoutWidget_7) 540 | self.listProduct.setMinimumSize(QtCore.QSize(350, 30)) 541 | self.listProduct.setMaximumSize(QtCore.QSize(450, 30)) 542 | font = QtGui.QFont() 543 | font.setPointSize(10) 544 | self.listProduct.setFont(font) 545 | self.listProduct.setObjectName("listProduct") 546 | self.verticalLayout_9.addWidget(self.listProduct) 547 | self.horizontalLayout.addLayout(self.verticalLayout_9) 548 | self.verticalLayout_6 = QtWidgets.QVBoxLayout() 549 | self.verticalLayout_6.setObjectName("verticalLayout_6") 550 | self.label = QtWidgets.QLabel(self.verticalLayoutWidget_7) 551 | self.label.setMinimumSize(QtCore.QSize(300, 20)) 552 | self.label.setMaximumSize(QtCore.QSize(450, 20)) 553 | font = QtGui.QFont() 554 | font.setFamily("Segoe UI") 555 | font.setPointSize(12) 556 | self.label.setFont(font) 557 | self.label.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter) 558 | self.label.setObjectName("label") 559 | self.verticalLayout_6.addWidget(self.label) 560 | self.inputProductNumber = QtWidgets.QLineEdit(self.verticalLayoutWidget_7) 561 | self.inputProductNumber.setMinimumSize(QtCore.QSize(300, 30)) 562 | self.inputProductNumber.setMaximumSize(QtCore.QSize(450, 30)) 563 | font = QtGui.QFont() 564 | font.setFamily("GOST type B") 565 | font.setPointSize(14) 566 | font.setBold(False) 567 | font.setWeight(50) 568 | self.inputProductNumber.setFont(font) 569 | self.inputProductNumber.setAlignment(QtCore.Qt.AlignCenter) 570 | self.inputProductNumber.setObjectName("inputProductNumber") 571 | self.verticalLayout_6.addWidget(self.inputProductNumber) 572 | self.horizontalLayout.addLayout(self.verticalLayout_6) 573 | self.verticalLayout_7.addLayout(self.horizontalLayout) 574 | self.horizontalLayout_10 = QtWidgets.QHBoxLayout() 575 | self.horizontalLayout_10.setObjectName("horizontalLayout_10") 576 | self.horizontalLayout_6 = QtWidgets.QHBoxLayout() 577 | self.horizontalLayout_6.setSpacing(10) 578 | self.horizontalLayout_6.setObjectName("horizontalLayout_6") 579 | self.btnCatalog = QtWidgets.QPushButton(self.verticalLayoutWidget_7) 580 | self.btnCatalog.setMinimumSize(QtCore.QSize(150, 20)) 581 | self.btnCatalog.setMaximumSize(QtCore.QSize(240, 30)) 582 | font = QtGui.QFont() 583 | font.setFamily("Segoe UI") 584 | self.btnCatalog.setFont(font) 585 | self.btnCatalog.setObjectName("btnCatalog") 586 | self.horizontalLayout_6.addWidget(self.btnCatalog) 587 | self.horizontalLayout_10.addLayout(self.horizontalLayout_6) 588 | self.horizontalLayout_9 = QtWidgets.QHBoxLayout() 589 | self.horizontalLayout_9.setSpacing(10) 590 | self.horizontalLayout_9.setObjectName("horizontalLayout_9") 591 | self.btnStop = QtWidgets.QPushButton(self.verticalLayoutWidget_7) 592 | self.btnStop.setMinimumSize(QtCore.QSize(100, 20)) 593 | self.btnStop.setMaximumSize(QtCore.QSize(140, 30)) 594 | font = QtGui.QFont() 595 | font.setFamily("Segoe UI") 596 | self.btnStop.setFont(font) 597 | self.btnStop.setStyleSheet("background-color: rgb(255, 0, 51);") 598 | self.btnStop.setObjectName("btnStop") 599 | self.horizontalLayout_9.addWidget(self.btnStop) 600 | self.btnStart = QtWidgets.QPushButton(self.verticalLayoutWidget_7) 601 | self.btnStart.setMinimumSize(QtCore.QSize(100, 20)) 602 | self.btnStart.setMaximumSize(QtCore.QSize(140, 30)) 603 | font = QtGui.QFont() 604 | font.setFamily("Segoe UI") 605 | self.btnStart.setFont(font) 606 | self.btnStart.setStyleSheet("background-color: rgb(51, 204, 153);") 607 | self.btnStart.setObjectName("btnStart") 608 | self.horizontalLayout_9.addWidget(self.btnStart) 609 | self.horizontalLayout_10.addLayout(self.horizontalLayout_9) 610 | self.verticalLayout_7.addLayout(self.horizontalLayout_10) 611 | MainWindow.setCentralWidget(self.centralwidget) 612 | 613 | self.retranslateUi(MainWindow) 614 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 615 | 616 | def retranslateUi(self, MainWindow): 617 | _translate = QtCore.QCoreApplication.translate 618 | MainWindow.setWindowTitle(_translate("MainWindow", "Омский Бекон. Счёт продукции")) 619 | self.label_10.setText(_translate("MainWindow", "Порог наличия объекта (Pix):")) 620 | item = self.tableIsObject.verticalHeaderItem(0) 621 | item.setText(_translate("MainWindow", "Px")) 622 | item = self.tableIsObject.horizontalHeaderItem(0) 623 | item.setText(_translate("MainWindow", "Min")) 624 | item = self.tableIsObject.horizontalHeaderItem(1) 625 | item.setText(_translate("MainWindow", "Max")) 626 | __sortingEnabled = self.tableIsObject.isSortingEnabled() 627 | self.tableIsObject.setSortingEnabled(False) 628 | self.tableIsObject.setSortingEnabled(__sortingEnabled) 629 | self.label_16.setText(_translate("MainWindow", "Порог наличия шумов (Pix):")) 630 | item = self.tableIsNoise.verticalHeaderItem(0) 631 | item.setText(_translate("MainWindow", "Px")) 632 | item = self.tableIsNoise.horizontalHeaderItem(0) 633 | item.setText(_translate("MainWindow", "Min")) 634 | item = self.tableIsNoise.horizontalHeaderItem(1) 635 | item.setText(_translate("MainWindow", "Max")) 636 | __sortingEnabled = self.tableIsNoise.isSortingEnabled() 637 | self.tableIsNoise.setSortingEnabled(False) 638 | self.tableIsNoise.setSortingEnabled(__sortingEnabled) 639 | self.label_17.setText(_translate("MainWindow", "Положение Зоны подсчёта (Pix):")) 640 | item = self.tableZoneCount.verticalHeaderItem(0) 641 | item.setText(_translate("MainWindow", "X")) 642 | item = self.tableZoneCount.verticalHeaderItem(1) 643 | item.setText(_translate("MainWindow", "Y")) 644 | item = self.tableZoneCount.horizontalHeaderItem(0) 645 | item.setText(_translate("MainWindow", "Start")) 646 | item = self.tableZoneCount.horizontalHeaderItem(1) 647 | item.setText(_translate("MainWindow", "End")) 648 | __sortingEnabled = self.tableZoneCount.isSortingEnabled() 649 | self.tableZoneCount.setSortingEnabled(False) 650 | self.tableZoneCount.setSortingEnabled(__sortingEnabled) 651 | self.label_11.setText(_translate("MainWindow", "Положение Опорной зоны (Pix):")) 652 | item = self.tableZoneRef.verticalHeaderItem(0) 653 | item.setText(_translate("MainWindow", "Px")) 654 | item = self.tableZoneRef.horizontalHeaderItem(0) 655 | item.setText(_translate("MainWindow", "X")) 656 | item = self.tableZoneRef.horizontalHeaderItem(1) 657 | item.setText(_translate("MainWindow", "Y")) 658 | item = self.tableZoneRef.horizontalHeaderItem(2) 659 | item.setText(_translate("MainWindow", "Size")) 660 | __sortingEnabled = self.tableZoneRef.isSortingEnabled() 661 | self.tableZoneRef.setSortingEnabled(False) 662 | self.tableZoneRef.setSortingEnabled(__sortingEnabled) 663 | self.label_18.setText(_translate("MainWindow", "Границы опорного цвета (0-255):")) 664 | item = self.tableRefColourBord.verticalHeaderItem(0) 665 | item.setText(_translate("MainWindow", "Min")) 666 | item = self.tableRefColourBord.verticalHeaderItem(1) 667 | item.setText(_translate("MainWindow", "Max")) 668 | item = self.tableRefColourBord.horizontalHeaderItem(0) 669 | item.setText(_translate("MainWindow", "H")) 670 | item = self.tableRefColourBord.horizontalHeaderItem(1) 671 | item.setText(_translate("MainWindow", "S")) 672 | item = self.tableRefColourBord.horizontalHeaderItem(2) 673 | item.setText(_translate("MainWindow", "V")) 674 | __sortingEnabled = self.tableRefColourBord.isSortingEnabled() 675 | self.tableRefColourBord.setSortingEnabled(False) 676 | self.tableRefColourBord.setSortingEnabled(__sortingEnabled) 677 | self.label_13.setText(_translate("MainWindow", "Пикселей в зоне:")) 678 | self.numberPixels.setText(_translate("MainWindow", "numberPixels_h")) 679 | self.label_12.setText(_translate("MainWindow", "Опорный цвет HSV:")) 680 | self.refColourHSV.setText(_translate("MainWindow", "ref_hsv")) 681 | self.btnEnCalibrParam.setText(_translate("MainWindow", "Параметры калибровки")) 682 | self.label_7.setText(_translate("MainWindow", "Текущий продукт:")) 683 | self.productCurr.setText(_translate("MainWindow", "ProdCurr")) 684 | self.label_3.setText(_translate("MainWindow", "Всего в коробке:")) 685 | self.numberProductInBox.setText(_translate("MainWindow", "Box")) 686 | self.label_4.setText(_translate("MainWindow", "Коробок текущего продукта:")) 687 | self.numberProductCons.setText(_translate("MainWindow", "Cons")) 688 | self.label_2.setText(_translate("MainWindow", "Всего за смену:")) 689 | self.numberProductAll.setText(_translate("MainWindow", "All")) 690 | self.label_6.setText(_translate("MainWindow", "Время смены:")) 691 | self.timer.setText(_translate("MainWindow", "Время")) 692 | self.label_5.setText(_translate("MainWindow", "Выберите продукт из списка:")) 693 | self.label.setText(_translate("MainWindow", "Или введите артикул продукта:")) 694 | self.btnCatalog.setText(_translate("MainWindow", "Каталог")) 695 | self.btnStop.setText(_translate("MainWindow", "Стоп")) 696 | self.btnStart.setText(_translate("MainWindow", "Старт")) 697 | -------------------------------------------------------------------------------- /design.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 920 10 | 640 11 | 12 | 13 | 14 | 15 | 920 16 | 640 17 | 18 | 19 | 20 | 21 | 1280 22 | 1024 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 255 32 | 255 33 | 255 34 | 35 | 36 | 37 | 38 | 39 | 40 | 255 41 | 255 42 | 255 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 255 52 | 255 53 | 255 54 | 55 | 56 | 57 | 58 | 59 | 60 | 255 61 | 255 62 | 255 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 255 72 | 255 73 | 255 74 | 75 | 76 | 77 | 78 | 79 | 80 | 255 81 | 255 82 | 255 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | Омский Бекон. Счёт продукции 91 | 92 | 93 | true 94 | 95 | 96 | 97 | 98 | 99 | 10 100 | 10 101 | 901 102 | 621 103 | 104 | 105 | 106 | 107 | 10 108 | 109 | 110 | 111 | 112 | 20 113 | 114 | 115 | 116 | 117 | 6 118 | 119 | 120 | 121 | 122 | 20 123 | 124 | 125 | 126 | 127 | 2 128 | 129 | 130 | 131 | 132 | 133 | 50 134 | 20 135 | 136 | 137 | 138 | 139 | 200 140 | 20 141 | 142 | 143 | 144 | 145 | Segoe UI 146 | 8 147 | 148 | 149 | 150 | Порог наличия объекта (Pix): 151 | 152 | 153 | Qt::AlignBottom|Qt::AlignHCenter 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 200 162 | 50 163 | 164 | 165 | 166 | 167 | 200 168 | 50 169 | 170 | 171 | 172 | QFrame::StyledPanel 173 | 174 | 175 | false 176 | 177 | 178 | QAbstractItemView::NoSelection 179 | 180 | 181 | Qt::ElideMiddle 182 | 183 | 184 | 99 185 | 186 | 187 | 99 188 | 189 | 190 | false 191 | 192 | 193 | false 194 | 195 | 196 | false 197 | 198 | 199 | 30 200 | 201 | 202 | 30 203 | 204 | 205 | false 206 | 207 | 208 | true 209 | 210 | 211 | 212 | Px 213 | 214 | 215 | 216 | 217 | Min 218 | 219 | 220 | 221 | 222 | Max 223 | 224 | 225 | 226 | 227 | AlignCenter 228 | 229 | 230 | 231 | 232 | AlignCenter 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 2 243 | 244 | 245 | 246 | 247 | 248 | 50 249 | 20 250 | 251 | 252 | 253 | 254 | 200 255 | 20 256 | 257 | 258 | 259 | 260 | Segoe UI 261 | 8 262 | 263 | 264 | 265 | Порог наличия шумов (Pix): 266 | 267 | 268 | Qt::AlignBottom|Qt::AlignHCenter 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 200 277 | 50 278 | 279 | 280 | 281 | 282 | 200 283 | 50 284 | 285 | 286 | 287 | QFrame::StyledPanel 288 | 289 | 290 | false 291 | 292 | 293 | QAbstractItemView::NoSelection 294 | 295 | 296 | 99 297 | 298 | 299 | 99 300 | 301 | 302 | false 303 | 304 | 305 | false 306 | 307 | 308 | false 309 | 310 | 311 | 30 312 | 313 | 314 | 30 315 | 316 | 317 | false 318 | 319 | 320 | true 321 | 322 | 323 | 324 | Px 325 | 326 | 327 | 328 | 329 | Min 330 | 331 | 332 | 333 | 334 | Max 335 | 336 | 337 | 338 | 339 | AlignCenter 340 | 341 | 342 | 343 | 344 | AlignCenter 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 20 357 | 358 | 359 | 360 | 361 | 2 362 | 363 | 364 | 365 | 366 | 367 | 50 368 | 20 369 | 370 | 371 | 372 | 373 | 200 374 | 20 375 | 376 | 377 | 378 | 379 | Segoe UI 380 | 8 381 | 382 | 383 | 384 | Положение Зоны подсчёта (Pix): 385 | 386 | 387 | Qt::AlignBottom|Qt::AlignHCenter 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 200 396 | 90 397 | 398 | 399 | 400 | 401 | 200 402 | 90 403 | 404 | 405 | 406 | QFrame::StyledPanel 407 | 408 | 409 | false 410 | 411 | 412 | QAbstractItemView::NoSelection 413 | 414 | 415 | 90 416 | 417 | 418 | 90 419 | 420 | 421 | true 422 | 423 | 424 | true 425 | 426 | 427 | false 428 | 429 | 430 | 30 431 | 432 | 433 | 30 434 | 435 | 436 | true 437 | 438 | 439 | false 440 | 441 | 442 | true 443 | 444 | 445 | 446 | X 447 | 448 | 449 | 450 | 451 | Y 452 | 453 | 454 | 455 | 456 | Start 457 | 458 | 459 | 460 | 461 | End 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | AlignCenter 470 | 471 | 472 | 473 | 474 | AlignCenter 475 | 476 | 477 | 478 | 479 | AlignCenter 480 | 481 | 482 | 483 | 484 | AlignCenter 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 2 495 | 496 | 497 | 498 | 499 | 500 | 50 501 | 20 502 | 503 | 504 | 505 | 506 | 200 507 | 20 508 | 509 | 510 | 511 | 512 | Segoe UI 513 | 8 514 | 515 | 516 | 517 | Положение Опорной зоны (Pix): 518 | 519 | 520 | Qt::AlignBottom|Qt::AlignHCenter 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 200 529 | 50 530 | 531 | 532 | 533 | 534 | 200 535 | 50 536 | 537 | 538 | 539 | false 540 | 541 | 542 | QAbstractItemView::NoSelection 543 | 544 | 545 | 66 546 | 547 | 548 | 66 549 | 550 | 551 | true 552 | 553 | 554 | false 555 | 556 | 557 | 30 558 | 559 | 560 | true 561 | 562 | 563 | 564 | Px 565 | 566 | 567 | 568 | 569 | X 570 | 571 | 572 | 573 | 574 | Y 575 | 576 | 577 | 578 | 579 | Size 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | AlignCenter 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | AlignCenter 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | AlignCenter 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 20 616 | 617 | 618 | 619 | 620 | 2 621 | 622 | 623 | 624 | 625 | 626 | 50 627 | 20 628 | 629 | 630 | 631 | 632 | 200 633 | 20 634 | 635 | 636 | 637 | 638 | Segoe UI 639 | 8 640 | 641 | 642 | 643 | Границы опорного цвета (0-255): 644 | 645 | 646 | Qt::AlignBottom|Qt::AlignHCenter 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 200 655 | 90 656 | 657 | 658 | 659 | 660 | 200 661 | 90 662 | 663 | 664 | 665 | QFrame::StyledPanel 666 | 667 | 668 | false 669 | 670 | 671 | QAbstractItemView::NoSelection 672 | 673 | 674 | Qt::SolidLine 675 | 676 | 677 | 55 678 | 679 | 680 | 55 681 | 682 | 683 | true 684 | 685 | 686 | true 687 | 688 | 689 | 30 690 | 691 | 692 | 30 693 | 694 | 695 | true 696 | 697 | 698 | 699 | Min 700 | 701 | 702 | 703 | 704 | Max 705 | 706 | 707 | 708 | 709 | H 710 | 711 | 712 | 713 | 714 | S 715 | 716 | 717 | 718 | 719 | V 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | AlignCenter 728 | 729 | 730 | 731 | 732 | AlignCenter 733 | 734 | 735 | 736 | 737 | AlignCenter 738 | 739 | 740 | 741 | 742 | AlignCenter 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | AlignCenter 751 | 752 | 753 | 754 | 755 | AlignCenter 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 2 766 | 767 | 768 | 769 | 770 | 6 771 | 772 | 773 | 774 | 775 | 776 | 120 777 | 20 778 | 779 | 780 | 781 | 782 | 145 783 | 20 784 | 785 | 786 | 787 | 788 | Segoe UI 789 | 8 790 | 791 | 792 | 793 | Пикселей в зоне: 794 | 795 | 796 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 80 805 | 30 806 | 807 | 808 | 809 | 810 | 80 811 | 30 812 | 813 | 814 | 815 | 816 | Segoe UI 817 | 818 | 819 | 820 | numberPixels_h 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 6 830 | 831 | 832 | 833 | 834 | 835 | 120 836 | 20 837 | 838 | 839 | 840 | 841 | 145 842 | 20 843 | 844 | 845 | 846 | 847 | Segoe UI 848 | 8 849 | 850 | 851 | 852 | Опорный цвет HSV: 853 | 854 | 855 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 80 864 | 30 865 | 866 | 867 | 868 | 869 | 80 870 | 30 871 | 872 | 873 | 874 | 875 | Segoe UI 876 | 877 | 878 | 879 | ref_hsv 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 150 894 | 20 895 | 896 | 897 | 898 | 899 | 200 900 | 30 901 | 902 | 903 | 904 | 905 | Segoe UI 906 | 907 | 908 | 909 | Параметры калибровки 910 | 911 | 912 | true 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 6 922 | 923 | 924 | 925 | 926 | 2 927 | 928 | 929 | 930 | 931 | 932 | 50 933 | 30 934 | 935 | 936 | 937 | 938 | 200 939 | 30 940 | 941 | 942 | 943 | 944 | Segoe UI 945 | 12 946 | 947 | 948 | 949 | Текущий продукт: 950 | 951 | 952 | Qt::AlignBottom|Qt::AlignHCenter 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 200 961 | 50 962 | 963 | 964 | 965 | 966 | 200 967 | 50 968 | 969 | 970 | 971 | 972 | Segoe UI 973 | 12 974 | 975 | 976 | 977 | QFrame::Box 978 | 979 | 980 | ProdCurr 981 | 982 | 983 | Qt::AlignCenter 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 2 993 | 994 | 995 | 996 | 997 | 998 | 50 999 | 30 1000 | 1001 | 1002 | 1003 | 1004 | 200 1005 | 30 1006 | 1007 | 1008 | 1009 | 1010 | Segoe UI 1011 | 12 1012 | 1013 | 1014 | 1015 | Всего в коробке: 1016 | 1017 | 1018 | Qt::AlignBottom|Qt::AlignHCenter 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 200 1027 | 50 1028 | 1029 | 1030 | 1031 | 1032 | 200 1033 | 50 1034 | 1035 | 1036 | 1037 | 1038 | Segoe UI 1039 | 14 1040 | 1041 | 1042 | 1043 | QFrame::Box 1044 | 1045 | 1046 | Box 1047 | 1048 | 1049 | Qt::AlignCenter 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 2 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 50 1065 | 20 1066 | 1067 | 1068 | 1069 | 1070 | 200 1071 | 20 1072 | 1073 | 1074 | 1075 | 1076 | Segoe UI 1077 | 10 1078 | 1079 | 1080 | 1081 | Коробок текущего продукта: 1082 | 1083 | 1084 | Qt::AlignBottom|Qt::AlignHCenter 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 200 1093 | 30 1094 | 1095 | 1096 | 1097 | 1098 | 200 1099 | 30 1100 | 1101 | 1102 | 1103 | 1104 | Segoe UI 1105 | 12 1106 | 1107 | 1108 | 1109 | QFrame::Box 1110 | 1111 | 1112 | QFrame::Plain 1113 | 1114 | 1115 | Cons 1116 | 1117 | 1118 | Qt::AlignCenter 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 2 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 50 1134 | 20 1135 | 1136 | 1137 | 1138 | 1139 | 200 1140 | 20 1141 | 1142 | 1143 | 1144 | 1145 | Segoe UI 1146 | 10 1147 | 1148 | 1149 | 1150 | Всего за смену: 1151 | 1152 | 1153 | Qt::AlignBottom|Qt::AlignHCenter 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 200 1162 | 30 1163 | 1164 | 1165 | 1166 | 1167 | 200 1168 | 30 1169 | 1170 | 1171 | 1172 | 1173 | Segoe UI 1174 | 12 1175 | 1176 | 1177 | 1178 | QFrame::Box 1179 | 1180 | 1181 | All 1182 | 1183 | 1184 | Qt::AlignCenter 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 2 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 50 1200 | 20 1201 | 1202 | 1203 | 1204 | 1205 | 200 1206 | 20 1207 | 1208 | 1209 | 1210 | 1211 | Segoe UI 1212 | 10 1213 | 1214 | 1215 | 1216 | Время смены: 1217 | 1218 | 1219 | Qt::AlignBottom|Qt::AlignHCenter 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 200 1228 | 30 1229 | 1230 | 1231 | 1232 | 1233 | 200 1234 | 30 1235 | 1236 | 1237 | 1238 | 1239 | Segoe UI 1240 | 12 1241 | 1242 | 1243 | 1244 | QFrame::Box 1245 | 1246 | 1247 | Время 1248 | 1249 | 1250 | Qt::AlignCenter 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 350 1269 | 20 1270 | 1271 | 1272 | 1273 | 1274 | 450 1275 | 20 1276 | 1277 | 1278 | 1279 | 1280 | Segoe UI 1281 | 12 1282 | 1283 | 1284 | 1285 | Выберите продукт из списка: 1286 | 1287 | 1288 | Qt::AlignBottom|Qt::AlignHCenter 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | 350 1297 | 30 1298 | 1299 | 1300 | 1301 | 1302 | 450 1303 | 30 1304 | 1305 | 1306 | 1307 | 1308 | 10 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | 1321 | 300 1322 | 20 1323 | 1324 | 1325 | 1326 | 1327 | 450 1328 | 20 1329 | 1330 | 1331 | 1332 | 1333 | Segoe UI 1334 | 12 1335 | 1336 | 1337 | 1338 | Или введите артикул продукта: 1339 | 1340 | 1341 | Qt::AlignBottom|Qt::AlignHCenter 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 300 1350 | 30 1351 | 1352 | 1353 | 1354 | 1355 | 450 1356 | 30 1357 | 1358 | 1359 | 1360 | 1361 | GOST type B 1362 | 14 1363 | 50 1364 | false 1365 | 1366 | 1367 | 1368 | Qt::AlignCenter 1369 | 1370 | 1371 | 1372 | 1373 | 1374 | 1375 | 1376 | 1377 | 1378 | 1379 | 1380 | 1381 | 10 1382 | 1383 | 1384 | 1385 | 1386 | 1387 | 150 1388 | 20 1389 | 1390 | 1391 | 1392 | 1393 | 240 1394 | 30 1395 | 1396 | 1397 | 1398 | 1399 | Segoe UI 1400 | 1401 | 1402 | 1403 | Каталог 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 10 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 100 1419 | 20 1420 | 1421 | 1422 | 1423 | 1424 | 140 1425 | 30 1426 | 1427 | 1428 | 1429 | 1430 | Segoe UI 1431 | 1432 | 1433 | 1434 | background-color: rgb(255, 0, 51); 1435 | 1436 | 1437 | Стоп 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1445 | 100 1446 | 20 1447 | 1448 | 1449 | 1450 | 1451 | 140 1452 | 30 1453 | 1454 | 1455 | 1456 | 1457 | Segoe UI 1458 | 1459 | 1460 | 1461 | background-color: rgb(51, 204, 153); 1462 | 1463 | 1464 | Старт 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 | 1479 | --------------------------------------------------------------------------------