Jul-21-2020, 07:53 AM
Hi.
This is my first thread. So please forgive if any mistake on my part. I have developed an application using opencv, pyqt5 and python. I am trying to capture live images from Flir Camera which comes with it's own SDK.
I have already tested this camera and code separately using thread which worked for almost hours. But now, I am am getting issues and I have a doubt if I have understood the threading correctly. This is a huge code that is why I removed the actual code in functions and sort of showing only the heirarchy of the functions and calls. I request help in sorting out this issue. In case any one wants to view the complete code please mention.
Please note I removed the code to make it easy to read and find the issue.
The issue is the code gets stuck after some time and crashes. When using Spyder, I get kernel restart . When i am using an exe created with pyInstaller, the exe crashes and shuts down after some time.
The following is the code
This is my first thread. So please forgive if any mistake on my part. I have developed an application using opencv, pyqt5 and python. I am trying to capture live images from Flir Camera which comes with it's own SDK.
I have already tested this camera and code separately using thread which worked for almost hours. But now, I am am getting issues and I have a doubt if I have understood the threading correctly. This is a huge code that is why I removed the actual code in functions and sort of showing only the heirarchy of the functions and calls. I request help in sorting out this issue. In case any one wants to view the complete code please mention.
Please note I removed the code to make it easy to read and find the issue.
The issue is the code gets stuck after some time and crashes. When using Spyder, I get kernel restart . When i am using an exe created with pyInstaller, the exe crashes and shuts down after some time.
The following is the code
from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5 import QtGui from PyQt5 import QtWidgets from PyQt5 import QtCore import time from time import time as my_timer import traceback, sys from dbqry import * # custom developed python code in another file from dberror import * # custom developed python code in another file import numpy import math import serial #from manual_check123 import * from manual_check123_Spin_ManiHeirarchy import * # custom developed python code in another file import os.path from os import path from Crypto.Cipher import AES import datetime import PDevApi class VisionProcess(QObject): ''' Defines the signals available from a running worker thread. Supported signals are: finished No data error `tuple` (exctype, value, traceback.format_exc() ) result `object` data returned from processing, anything progress `int` indicating % progress ''' finished = pyqtSignal() error = pyqtSignal(tuple) result = pyqtSignal(object) progress = pyqtSignal(numpy.ndarray,str) # modified #240520 class VisionR(QRunnable): ''' VisionR thread Inherits from QRunnable to handler worker thread setup, signals and wrap-up. :param callback: The function callback to run on this worker thread. Supplied args and kwargs will be passed through to the runner. :type callback: function :param args: Arguments to pass to the callback function :param kwargs: Keywords to pass to the callback function ''' def __init__(self, fn, *args, **kwargs): super(VisionR, self).__init__() # Store constructor arguments (re-used for processing) self.fn = fn self.args = args self.kwargs = kwargs self.signals = VisionProcess() # Add the callback to our kwargs self.kwargs['progress_callback'] = self.signals.progress # self.kwargs['progress_callback'] = self.signals.pass_image @pyqtSlot() def run(self): ''' Initialise the runner function with passed args, kwargs. ''' # Retrieve args/kwargs here; and fire processing using them try: result = self.fn(*self.args, **self.kwargs) except: traceback.print_exc() exctype, value = sys.exc_info()[:2] self.signals.error.emit((exctype, value, traceback.format_exc())) else: self.signals.result.emit(result) # Return the result of the processing finally: self.signals.finished.emit() # Done class Color(QWidget): def __init__(self, color, *args, **kwargs): super(Color, self).__init__(*args, **kwargs) self.setAutoFillBackground(True) palette = self.palette() palette.setColor(QPalette.Window, QColor(color)) self.setPalette(palette) class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.counter = 0 self.video_file_exists = False self.frame_counter = 0 self.start_time=my_timer() self.cycle_timeout=my_timer() self.max_time_taken=0 self.min_time_taken=0 self.video_frame_count = 0 self.run_loop = True self.vision_thread_start = False self.worker = None self.video_acq_run = False # doubtul to remove debug used to start and stop the video. Might not be needed for cam self.video_stop_by_button = False # debug need to be removed # self.cap = None # new Display Code pyQT left = 50 top = 50 width = 640 height = 480 self.setGeometry(left, top, width, height) # Modbus Variables Start self.read_modbus_flag = 1 self.write_modbus_flag = 0 self.mb_connected = False # self.client = ModbusClient('192.168.1.131', port=502) #modbusuncomment # self.client = ModbusClient('localhost', port=502) # plc to PC self.curr_plc_command = 0 self.prev_plc_command = 0 self.next_plc_command = 0 self.prevPLCSignal = 0 self.prev_pass_signal=0 self.prev_fail_signal=0 self.prev_motor_fw_signal=0 self.prev_motor_rw_signal=0 self.prev_motor_all_off_signal=0 self.prev_out_home7_signal=0 self.home_pass = False self.lowbeam_fwd_pass = False self.lowbeam_rev_pass = False self.highbeam_pass = False # Modbus write value variables self.motor_fw_rv_off = 0 # 0 is motor stop 1 Motor fwrd 2 motor rev 3 self.lb_on = 1 self.lb_off = 2 self.mot_off = 3 self.mot_fwd = 4 self.mot_rev = 5 self.hb_on = 6 self.hb_off = 7 self.write_mb_test_result = 0 self.mb_connect_tried =0 self.mb_connect_try_stop_at = 3 self.start_time = my_timer() self.start_time2 = my_timer() self.running_time = my_timer()+ 100 self.prev_time = my_timer() self.elapsed_time = 0 self.write_modbus_arr = [0,0] # Modbus Variables End # Vision Variables Start # other variables self.pr_name_in_hmi = "" self.curr_jig_product = 0 # value 12 assigned for testing make it 0 latter self.prev_jig_product = 0 # value 12 assigned for testing make it 0 latter self.envOK = 0 # variables for drawing rectangle self.orig_frame = None self.temp_img = None # self.img = None # self.ix,self.iy=-1,-1 # # final rectangle co ordinates self.fsx,self.fsy = 0,0 # FinalStartX FinalStartY self.fex,self.fey = 0,0 # FinalEndX FinalEndY self.pr_Pos_H,self.pr_Pos_L =0,0 self.pr_Pos_M = 0 self.image_file_path = "../templates/" # Home / Frwd Location 1 , 2 , 3 co ordinates # Home co ords. self.hm_top_x=[0,0,0,0] # first element is dummy self.hm_top_y=[0,0,0,0] self.hm_bot_x=[0,0,0,0] self.hm_bot_y=[0,0,0,0] # tolerance roi self.hm_tol_top_x=[0,0,0,0] # first element is dummy self.hm_tol_top_y=[0,0,0,0] self.hm_tol_bot_x=[0,0,0,0] self.hm_tol_bot_y=[0,0,0,0] # common # Fwrd Co ords self.fw_top_x=[0,0,0,0] self.fw_top_y=[0,0,0,0] self.fw_bot_x=[0,0,0,0] self.fw_bot_y=[0,0,0,0] # tolerance roi co ord self.fw_tol_top_x=[0,0,0,0] # first element is dummy self.fw_tol_top_y=[0,0,0,0] # Template Find ROI Co ordinates self.tm_top_left=[0] # first element is dummy self.tm_bot_right=[0] self.tm_color=[0,0,0,0] self.tm_tolerance = 30 # ROI mid points self.hm1_mtpt_mhl=[0,0,0,0] self.hm2_mtpt_mhl=[0,0,0,0] self.hm3_mtpt_mhl=[0,0,0,0] self.fw1_mtpt_mhl=[0,0,0,0] # self.show_rectangle =0 self.r_color_id = 0 # this is index of r_Color self.show_rect_id = 0 # this is for home, forward, reverse rectangle self.r_Color=[(170,255,0),(0,255,0),(0,0,255),(255,255,)] # 0 Cyan 1 Green 2 Red 3 Yellow self.show_home_rect = False self.top_X,self.top_Y,self.bot_X,self.bot_Y =0,0,0,0 # mod050720 variable declaration self.defined_tol_mtpt1,self.defined_tol_mtpt2 = 0,0 self.fw_line=0 self.com_tol_top_X,self.com_tol_top_Y,self.com_tol_bot_X,self.com_tol_bot_Y =0,0,0,0 self.home_at_fw_start_x,self.home_at_fw_start_y =0,0 ## final home position when home ok and forward starts # the above at_fw_start will be the return to base value when reverse is done self.show_template_rectange_hmfw = 0 # 1 --> hm 2 --> fw self.btn_color = "NA" self.str_ret_val = "NA" self.seq_begin_timer = my_timer() self.home_midpoint_call_spacing = my_timer() # # end variables for drawing rectanlge # variables from manis code for table self.hllareq = 0 self.barcodereq = 0 self.prndata = "" self.hminame = "" self.custcode ="" self.prodcode = "" self.cpartcode = "" self.ctime = None self.lampnametype = "" self.day_of_year = datetime.datetime.now().timetuple().tm_yday self.conn = None self.lastserial_fromtable =0 self.serialtoprint =0 self.print_bc_only_once = 9 self.custprodyydayofyear ="" self.final_test_pass = 0 self.final_test_fail = 0 # Vision Variables End # UI Widgets, layouts etc mainLayout = QVBoxLayout() titleLayout = QHBoxLayout() statusLayout = QHBoxLayout() imgLayout = QVBoxLayout() lblLayout = QVBoxLayout() btnLayout = QVBoxLayout() roundBtnLayout = QHBoxLayout() btnFWRVLayout = QHBoxLayout() plotLayOut = QHBoxLayout() lblLayout.setAlignment(Qt.AlignCenter) btnLayout.setAlignment(Qt.AlignTop) titleLayout.setAlignment(Qt.AlignCenter) statusLayout.setAlignment(Qt.AlignLeft) imgLayout.addStretch() btnLayout.setSpacing(15) plotLayOut.addLayout(imgLayout,20) plotLayOut.addLayout(btnLayout,2) mainLayout.addLayout(titleLayout,1) mainLayout.addLayout(plotLayOut,18) mainLayout.addLayout(statusLayout,1) # self.l = QLabel("Start") self.tm = QLabel("Time") # folloing is a label used to display camera input. Continually updated self.imgdis = QtWidgets.QLabel(self) self.imgdis.setGeometry(QtCore.QRect(150, 100, 1000, 600))#740,512 self.imgdis.setObjectName("imgdis") self.imgdis.setMouseTracking(True) self.imgdis.installEventFilter(self) self.hBeamBtn = QPushButton(self) # self.hBeamBtn.setObjectName("hBeamBtn") self.hBeamBtn.setText("HIGHBEAM") titleLbl = QLabel("Light Beam Testing System") self.prdLbl = QLabel("Product") self.testRunningLbl = QLabel("Test Running") self.mbBtn = QPushButton("PLC") # new buttons self.camBtn = QPushButton("CAMERA") # new buttons self.dumBtn = QPushButton("DUM") # new buttons self.visionStartStop = QPushButton("Start") self.videoStartStop = QPushButton("Video ON") # Debug to remove latter self.lBeamBtn = QPushButton("LOWBEAM") self.hmPassBtn = QPushButton("HOME") self.fwPassBtn = QPushButton("FRWD") self.rvPassBtn = QPushButton("RVRS") self.allTestBtn = QPushButton("ALLPASS") self.prnStatusBtn = QPushButton("PRINT") # startBtn.pressed.connect(self.start_run) self.visionStartStop.pressed.connect(self.start_stop_vision_thread) self.videoStartStop.pressed.connect(self.video_start_stop) # debug to remove latter self.prdLbl.setAlignment( Qt.AlignHCenter) self.testRunningLbl.setAlignment( Qt.AlignHCenter) titleLbl.setAlignment( Qt.AlignHCenter) titleLbl.setStyleSheet("font: bold;background-color: blue;font-size: 36px;height: 60px;width: 250px;") self.prdLbl.setStyleSheet("font: bold;background-color: cyan;font-size: 24px;height: 60px;width: 150px;") self.testRunningLbl.setStyleSheet("font: bold;background-color: yellow;font-size: 24px;height: 60px;width: 150px;") self.hBeamBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.lBeamBtn.setStyleSheet("font: bold;background-color: white;font-size: 12px;height: 14px;width: 80px;") self.hmPassBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.fwPassBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.rvPassBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.allTestBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") self.prnStatusBtn.setStyleSheet("font: bold;background-color: grey;font-size: 12px;height: 28px;width: 80px;") # startBtn.setStyleSheet("font: bold;background-color: green;font-size: 12px;height: 28px;width: 80px;") self.visionStartStop.setStyleSheet("font: bold;background-color: red;font-size: 12px;height: 28px;width: 80px;") # new buttons self.mbBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop: 0 #fff, stop: 1 #888);padding: 5px; font-size: 12px;height: 30px;width: 30px;") self.camBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop: 0 #fff, stop: 1 #888);padding: 5px; font-size: 12px;height: 30px;width: 30px;") self.dumBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop: 0 #fff, stop: 1 #888);padding: 5px; font-size: 12px;height: 30px;width: 30px;") self.tm.setStyleSheet("font:bold:font-size: 20px;height: 30px;width: 30px;") titleLayout.addWidget(titleLbl) # title2Layout.addWidget(prdLbl) # title2Layout.addWidget(testRunningLbl) btnFWRVLayout.addWidget(self.hmPassBtn) btnFWRVLayout.addWidget(self.fwPassBtn) btnFWRVLayout.addWidget(self.rvPassBtn) imgLayout.addWidget(self.imgdis) btnLayout.addWidget(self.prdLbl) # btnLayout.addWidget(self.testRunningLbl) btnLayout.addWidget(self.lBeamBtn) btnLayout.addLayout(btnFWRVLayout) btnLayout.addWidget(self.hBeamBtn) btnLayout.addWidget(self.allTestBtn) btnLayout.addWidget(self.prnStatusBtn) roundBtnLayout.addWidget(self.mbBtn) # new buttons roundBtnLayout.addWidget(self.dumBtn) # new buttons roundBtnLayout.addWidget(self.camBtn) # new buttons btnLayout.addLayout(roundBtnLayout) # btnLayout.addWidget(mbBtn) btnLayout.addWidget(self.visionStartStop) btnLayout.addWidget(self.videoStartStop) # debug to remove # statusLayout.addWidget(self.l) statusLayout.addWidget(self.tm ) # statusLayout.addWidget(self.maxt) widget = QWidget() widget.setLayout(mainLayout) # since only 1 layout is set to the widget. This one must contain others self.setCentralWidget(widget) # new Display Code pyQT END widget = QWidget() widget.setLayout(mainLayout) # since only 1 layout is set to the widget. This one must contain others self.setCentralWidget(widget) self.show() self.threadpool = QThreadPool() #print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) self.timer = QTimer() self.timer.setInterval(1) self.timer.timeout.connect(self.recurring_timer) frame = cv2.imread('../templates/dispimg.png',1) # ============================================================================= Top = cv2.resize(frame, None, fx=0.65, fy=0.65) Top_Image1 = cv2.resize(Top, (1000,600)) # 740, 512 # Top_Image1=cv2.cvtColor(Top_Image1, cv2.COLOR_RGB2BGR) self.imgdisplay1(Top_Image1) self.dumBtn.hide() #print ("starting modbus ") if cam_detected: self.video_acq_run = True self.camBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop:0 white, stop: 0.01 gray, stop:1 green);padding: 5px; font-size: 12px;height: 30px;width: 30px;") Acq_start_one() else: self.video_acq_run = False self.camBtn.setStyleSheet("font: bold; color: black; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop:0 white, stop: 0.01 gray, stop:1 red);padding: 5px; font-size: 12px;height: 30px;width: 30px;") print("no Camera") # self.start_modbus() self.envOK = self.check_environment() # self.modbus_connect() #modbusuncomment # PDevAPI section below PDev_CardNumber = 11 Pdev_Port = 1 Pdev_Line = 0 Pdev_Direction = 1 pinval= PDevApi.RegisterCard(11,0) rd = 0 # PDEV Api section above # init UI # End Init UI # Adlink PDEV code below def read_dio(self): # # # called from run_vision_function once every 5 seconds self.curr_plc_command = 1 # Actually around 20 statements to read an external DAQ Device and set the above value which # can be anything from 1 to 129 def out_home7(self,onOff): #called from run_vision_function once every 15 seconds rd = 0 if onOff==1: out = PDevApi.DOWriteLine(0,0,7,1) # trying to switch off all outputs at a go provide #time.sleep(0.5) print("Home Aiming Ok Signal Sent") elif onOff==2: out = PDevApi.DOWriteLine(0,0,7,0) self.prev_out_home7_signal=1 def out_pass(self): # # called from run_vision_function once every 15 seconds either 1 pass or fail #same as out_home7 to switch on outputs on DAQ # print ("Pass On ") def out_fail(self): # # called from run_vision_function once every 15 seconds either one pass or fail rd = 0 #same as out_home7 to switch on outputs on DAQ def out_motor_fw(self,fw_on_off): # # called from run_vision_function once every 15 seconds rd = 0 #same as out_motor_rv to switch on outputs on DAQ def out_motor_rv(self,rv_on_off): #called from run_vision_function once every 15 seconds rd = 0 # Leaving the original code to give an insight of the code is like if self.prev_motor_rw_signal==0: if rv_on_off ==1 : # forward on out = PDevApi.DOWriteLine(0,0,2,0) # forward off time.sleep(0.3) out = PDevApi.DOWriteLine(0,0,3,1) # reverse on time.sleep(0.3) #print ("Motor Reverse On " ) else: #elif rv_on_off ==2 : # reverse off out = PDevApi.DOWriteLine(0,0,3,0) # reverse off time.sleep(0.3) out = PDevApi.DOWriteLine(0,0,2,0) # forward off time.sleep(0.3) #print ("Motor Reverse Off " ) self.prev_motor_rw_signal=1 def out_motor_off(self): # # called from run_vision_function once every 15 seconds rd = 0 #same as out_motor_rv to switch on outputs on DAQ # called on if condition def imgdisplay1(self, p_TopImage): # called from run_vision_function continously almost every 300 milli seconds # called continously pixmap1 = QPixmap(p_TopImage) self.imgdis.setPixmap(pixmap1) pixmap1.detach()#mod180720 self.imgdis.resize(pixmap1.width(),pixmap1.height()) def check_environment(self): # called only once at start of progam time_expired = 0 # key_location = "F:\\vision37\\envtext.bin" # A safe place to store a key. Can be on a USB or even locally on the machine (not recommended unless it has been further encrypted) key_location = ".\\envtext.bin" # A safe place to store a key. Can be on a USB or even locally on the machine (not recommended unless it has been further encrypted) decoded_val_s=0 str_message = '' file_exists = os.path.exists(key_location) # read a text file process and return values as below # called only once return(time_expired,decoded_val_s,str_message) def progress_fn(self, tp_image, strval): self.imgdisplay1(tp_image) def video_start_stop(self): # invoked by QButton if self.video_stop_by_button == True: self.video_stop_by_button = False else: self.video_stop_by_button = True def draw_rectangles(self,Top_Image1): # called from run_vision_function continously # following code is mostly to draw rectangles, Lines on the image before display # can skip this part of the code. Leaving it for your reference tlr = self.tm_tolerance - 15 # to draw closer if self.show_template_rectange_hmfw == 1:# this is to show home template match boxes # print ("Entered imgdisplay through do_template_check ") for x in range (1,4): # print("imgdisplay point 1" ) if (self.hm_top_x[x] !=0) & (self.hm_top_y[x]-tlr !=0) & \ (self.hm_bot_x[x] !=0) & (self.hm_bot_y[x] !=0 ) : roi_top_left = (self.hm_top_x[x]-tlr,self.hm_top_y[x]-tlr) roi_bot_right = (self.hm_bot_x[x]+tlr,self.hm_bot_y[x]+tlr) cv2.rectangle(Top_Image1,roi_top_left,roi_bot_right,self.r_Color[self.tm_color[x]],thickness=4) else: if ((self.show_rect_id ==1) or(self.show_rect_id ==3)): # mod130720 newly added if statement #if (self.show_rect_id in range (1,4)): #mod130720 this line is commented out c_color = self.r_Color[self.r_color_id] # cv2.rectangle(Top_Image1,(self.top_X,self.top_Y), (self.bot_X,self.bot_Y),c_color,2) cv2.rectangle(Top_Image1,(self.top_X,self.top_Y), (self.bot_X,self.bot_Y),(170,255,0),2) # fixed color # mod050720 drawing circle at the point cv2.circle(Top_Image1,(self.defined_tol_mtpt1,self.defined_tol_mtpt2 ),3,[0,0,255],-1) # self.fw_line=0 Following is for actual tolerance rectangle check Modify this latter with common variables cv2.rectangle(Top_Image1,(self.com_tol_top_X ,self.com_tol_top_Y),(self.com_tol_bot_X,self.com_tol_bot_Y),c_color,2) elif (self.show_rect_id ==5): # show forward line only #130720 latter try to change the 5 to 1 c_color = self.r_Color[self.r_color_id] # drawing a line height, width, channels = Top_Image1.shape line_thickness = 2 x_end = (width) # self.defined_tol_mtpt1 #fw_check draw line self.fw_line=0 cv2.line(Top_Image1, (0, self.fw_line ), (x_end, self.fw_line), c_color, thickness=line_thickness) #mod130720 commented out #cv2.line(Top_Image1, (0, self.defined_tol_mtpt2 ), (x_end, self.defined_tol_mtpt2), c_color, thickness=line_thickness) #mod130720 commented out Top_Image2 = cv2.resize(Top_Image1, (1000,600)) #740, 512 Top_Image2=cv2.cvtColor(Top_Image2, cv2.COLOR_RGB2BGR) height, width, channel = Top_Image2.shape # 190520 in accordance to above lines new # height, width, channel = Top_Image1.shape bytesPerLine = 3 * width ret_QImage = QImage( Top_Image2.data, width, height, bytesPerLine, QImage.Format_RGB888) return(QImage) def run_vision_function(self, progress_callback): # QThread self.elapsed_time = my_timer() prev_mb_timer = my_timer() -2 # so that first time it gets executed frame_set = False seq_running_timer = my_timer() hm_temp_res = [0,0,0,0] fw_temp_res = [0,0,0,0] action_to_do = 0 # set the action_to_do with 1 - 5 of the following act_lb_hm_chk = 1 # do home check act_lb_hm_tmp_chk = 2 # do home template check act_lb_fw_chk = 3 # do forward check act_lb_fw_tmp_chk = 4 # do forward template check act_lb_rv_chk = 5 # do reverse check act_hb_cont_chk = 6 # do reverse check act_all_pass_chk = 10 # do reverse check act_all_fail_chk = 12 # do reverse check act_bc_print_chk = 13 # do reverse check hm_chk_result = False fw_chk_result = False high_beam_result = False rv_chk_result = False hm_template_chk_pass = False fw_template_chk_pass = False # show_rectangle = 0 n = 0 # debug start_high_beam_chk = False # debug img_write_once = True # debug # self.read_table() # debug remove self.curr_plc_command = 0 # debug remove dummy_always_true = True temp_img = self.orig_frame roi_hide_time = 1.00 roi_hide_after_timer = True all_test_timer = False read_daq = False test_time_taken = 0 disp_delay = my_timer() save_image = False # do_template_check_run = False # to control that the template is run only once while self.run_loop: # while True: self.elapsed_time = round(my_timer() - prev_mb_timer) if ((self.curr_plc_command== 16) or (self.curr_plc_command==2) or (self.curr_plc_command==0)): if (self.elapsed_time > 2): #print ("daq bef read ", self.curr_plc_command, " elapsed time ", self.elapsed_time) read_daq = True if (read_daq==True) : prev_mb_timer = round(my_timer()) # bug self.prev_mb_timer modified to prev_mb_timer 080720 self.read_dio() #print ("daq after read ", self.curr_plc_command) read_daq = False #print ("Reading DIO ",self.curr_plc_command,prev_mb_timer, " ", self.elapsed_time) if self.mb_connected == True: # self.execute_modbus() #modbusuncomment pass if(self.prev_jig_product != self.curr_jig_product) & (self.curr_jig_product in range(1,16)): self.prev_jig_product = self.curr_jig_product self.read_table() if (self.curr_plc_command != self.prev_plc_command): self.prev_plc_command = self.curr_plc_command prev_mb_timer = my_timer() self.cycle_timeout = my_timer() # used to timeut cycle # seq_start_timer = my_timer() # reset the start time whenever sequence change from plc self.seq_begin_timer = my_timer() # reset the start time whenever sequence change from plc if self.curr_plc_command == 1: # start home aiming then initialize self.show_rect_id = 1 hm_temp_res = [0,0,0,0] fw_temp_res = [0,0,0,0] hm_chk_result = False fw_chk_result = False rv_chk_result = False high_beam_result = False self.prev_pass_signal=0 self.prev_fail_signal=0 self.prev_motor_fw_signal=0 self.prev_motor_rw_signal=0 self.prev_motor_all_off_signal=0 self.prev_out_home7_signal=0 action_to_do = act_lb_hm_chk self.print_bc_only_once=1 self.out_home7(2) self.start_time = my_timer() # debug for timing #self.cycle_timeout = my_timer() # used to timeut cycle sequence self.btn_color ="ALL_gray" # sets all btns to red initially #print ("curr_command 1 ") save_image = True # debug used to save image as per AJINs request to find the deflector if (self.curr_plc_command == 4): # start low beam sequence check self.prev_pass_signal=0 self.prev_fail_signal=0 #print ("curr_command 4 ") action_to_do == act_lb_hm_chk if (self.curr_plc_command == 8): # start high beam check self.prev_pass_signal=0 self.prev_fail_signal=0 self.show_rect_id = 0 action_to_do = act_hb_cont_chk start_high_beam_chk = True # required in actual run if (self.video_acq_run == True and self.video_stop_by_button == False): # debug this and next line # next 4 lines needed change indent after removing above 1st line # ret_frame_list = self.run_video_loop() # this will be replaced with get from camera # ret_frame_list = self.run_video_loop() # this will be replaced with get from camera ret,frame = grab_image_one() frame_set = ret ret_frame = frame if frame_set == True and self.video_stop_by_button == False : # print("here 1") temp_img = ret_frame self.template_logging(temp_img,self.curr_jig_product,1,2,3) self.orig_frame = ret_frame # just in case to remove if not using temp_img = cv2.resize(ret_frame, None, fx=0.65, fy=0.65) homing_roi_image = ret_frame # check if the following four lines to be done here or on home self.top_X,self.top_Y = self.hm_top_x[1],self.hm_top_y[1] self.bot_X,self.bot_Y = self.hm_bot_x[1],self.hm_bot_y[1] self.com_tol_top_X,self.com_tol_top_Y = self.hm_tol_top_x[1],self.hm_tol_top_y[1] self.com_tol_bot_X,self.com_tol_bot_Y = self.hm_tol_bot_x[1],self.hm_tol_bot_y[1] if (my_timer() - self.seq_begin_timer >= roi_hide_time) & (roi_hide_after_timer==True ): # print ("Hide timer ",my_timer() - self.seq_begin_timer, roi_hide_timer ) self.show_template_rectange_hmfw = 0 if (self.curr_plc_command == 1): # low beam manual aiming mod060720 new code added hm_chk_result = self.do_home_check(temp_img,1) # mod060720 new code added if (hm_chk_result == True): self.out_home7(1) # mod130720 commented out send home signal as pass DAQ Code self.curr_plc_command = 0 self.next_plc_command = 4 if save_image == True: image_time = int(datetime.datetime.now().timestamp()) save_filename = "../templates/deflectorimage/f"+str(image_time)+".png" print ("file name ", save_filename) cv2.imwrite(save_filename,temp_img) save_image = False if (self.curr_plc_command == 4): # start lowbeam Forward Reverse check if (action_to_do == act_lb_hm_chk): if (hm_chk_result == True ): action_to_do = act_lb_hm_tmp_chk # set next action to hm_template check if (action_to_do == act_lb_hm_tmp_chk): # start home template check hm_temp_res = self.do_template_check(temp_img,1) #mod140720 commented out for testing #hm_temp_res = (1,1,1,1) if (hm_temp_res[1] ==1) & (hm_temp_res[2] ==1) & (hm_temp_res[3] ==1): action_to_do = act_lb_fw_chk # set next action to forward check self.seq_begin_timer = my_timer() # store next action begin time hm_template_chk_pass = True roi_hide_after_timer = True self.show_rect_id = 5 # show forward rectangle mod130720 self.r_color_id = 2 # color Red print ("Forward Start ") self.out_motor_fw(1) # send forward signal 1 for forward DAQ Code else: print("Hm Template Fail ",hm_temp_res,self.tm_color) hm_template_chk_pass = False #roi_hide_after_timer = False roi_hide_after_timer = True self.seq_begin_timer = my_timer() self.out_fail() # send fail signal as pass DAQ Code self.curr_plc_command = 0 # to restart action_to_do = 0 if (action_to_do == act_lb_fw_chk): fw_chk_result = self.do_fw_check(temp_img) if (fw_chk_result == True ): self.out_motor_fw(2) # forward motor off signal action_to_do = act_lb_fw_tmp_chk # set next action to hm_template check if (action_to_do == act_lb_fw_tmp_chk): # forward template check # FORWARD POSITION TEMPLATE CHECK AS FOLLOWS -- Bypassed on 060720 # fw_temp_res = self.do_template_check(temp_img,2) # bypassed 060720 #print ("Rverse Start 3 ") fw_temp_res = (1,1,1,1) # print ("Forward Result ",fw_temp_res) if (fw_temp_res[1] ==1) & (fw_temp_res[2] ==1) & (fw_temp_res[3] ==1): # START REVERSE #print ("Rverse Start 4") action_to_do = act_lb_rv_chk # set next action to forward check self.seq_begin_timer = my_timer() # store next action begin time fw_template_chk_pass = True roi_hide_after_timer = True #self.out_pass() self.show_rect_id = 3 # show reverse rectangle self.r_color_id = 2 # color Red self.out_motor_rv(1) # send reverse signal 1 for forward DAQ Code if (action_to_do == act_lb_rv_chk): rv_chk_result = self.do_home_check(temp_img,3) # 3 is for reverse check if (rv_chk_result == True): action_to_do = 0 # read daq self.out_motor_off() # send forward & reverse off signals for DAQ Code self.out_pass() # send reverse pass signal for DAQ Code self.curr_plc_command = 0 # to restart self.next_plc_command = 8 test_time_taken = round(my_timer() - self.cycle_timeout) if (test_time_taken > 15): fw_template_chk_pass = False hm_template_chk_pass = False roi_hide_after_timer = False self.seq_begin_timer = my_timer() self.out_fail() # send forward template fail signal for DAQ Code self.curr_plc_command = 0 # to restart read_daq = True action_to_do = 0 if (self.curr_plc_command == 8) & (start_high_beam_chk == True) : time.sleep(0.5) (high_beam_result,r_contours) = self.do_high_beam_contour(temp_img) if (high_beam_result == True): cv2.drawContours(temp_img, r_contours, -1, (0, 255, 0), 2) self.out_pass() # send high beam pass signal for DAQ Code self.curr_plc_command = 0 # to restart read_daq = True self.next_plc_command = 1 action_to_do = 0 if (test_time_taken > 15): print("High beam Fail " ) self.out_fail() # send forward template fail signal for DAQ Code self.curr_plc_command = 0 # to restart read_daq = True action_to_do = 0 if (self.curr_plc_command == 2) : # do ALL Pass show indicator print ("Bar Code on Pass ", self.print_bc_only_once) if (self.barcodereq == 1) and (self.print_bc_only_once==1): print(" bc print under pass ") self.do_print_barcode() self.btn_color= 'self.prnStatusBtn_green' self.print_bc_only_once=9 self.curr_plc_command = 0 self.btn_color= 'self.allTestBtn_green' if (self.curr_plc_command == 16) : # all Fail show indicator self.btn_color= 'self.allTestBtn_red' if (self.curr_plc_command == 32) : # do barcode print print ("Bar Code on Print Command") if self.barcodereq == 1: #self.do_print_barcode()#commneted mod170720 self.btn_color= 'self.prnStatusBtn_green' self.curr_plc_command = 0 status_message = self.str_ret_val final_image = self.draw_rectangles(temp_img) #mod180720 disp_elapsed = round((my_timer() - disp_delay),2) disp_image = False if disp_elapsed > 0.03: disp_image = True disp_delay = my_timer() if disp_image == True : progress_callback.emit(final_image,status_message) def do_home_check(self,tmp_img, hm_fw_pos):# called from run_vision_function continously until condition met # Leaving code as is for reference home_check_result = False defined_mtptH = 0 defined_mtptL = 0 btn_color_red = '' btn_color_yellow ='' hmtlrx = 8 hmtlry = 12 str_movement = " " do_delayed_check = False tolr = 0 if (hm_fw_pos == 1): # get home ROI 1 self.top_X,self.top_Y = self.hm_top_x[1],self.hm_top_y[1] self.bot_X,self.bot_Y = self.hm_bot_x[1],self.hm_bot_y[1] self.com_tol_top_X,self.com_tol_top_Y = self.hm_tol_top_x[1],self.hm_tol_top_y[1] self.com_tol_bot_X,self.com_tol_bot_Y = self.hm_tol_bot_x[1],self.hm_tol_bot_y[1] defined_mtptH = self.hm1_mtpt_mhl[2] defined_mtptL = self.hm1_mtpt_mhl[3] btn_color_red = 'self.hmPassBtn_red' btn_color_yellow = 'self.hmPassBtn_yellow' str_movement = "Home " do_delayed_check = True tolr = 9 #mod130720 forward rectangle check not done from this part elif (hm_fw_pos == 2): # get FW ROI 1 print ("This part must not run. insteac the do_fw_check should run for the forward movement ") # comment out above section of does nto run #130720 elif (hm_fw_pos == 3): # reverse sequence of low beam use teh HOME 1 ROI (both are same only button different) self.top_X,self.top_Y = self.hm_top_x[1],self.hm_top_y[1] self.bot_X,self.bot_Y = self.hm_bot_x[1],self.hm_bot_y[1] self.com_tol_top_X,self.com_tol_top_Y = self.hm_tol_top_x[1],self.hm_tol_top_y[1] self.com_tol_bot_X,self.com_tol_bot_Y = self.hm_tol_bot_x[1],self.hm_tol_bot_y[1] defined_mtptH = self.hm1_mtpt_mhl[2] # X h is x l is y defined_mtptL = self.hm1_mtpt_mhl[3] # Y h is x l is y # hm_fw_pos = hm_fw_pos - 2 # changing the 3 passed to 1 to allow home based functions like rectangle & color btn_color_red = 'self.rvPassBtn_red' btn_color_yellow = 'self.rvPassBtn_green' # here wil be using green instead of yellow str_movement = "Reverse " do_delayed_check = True tolr = 9 if (self.top_X>0) & (self.top_Y>0) & (self.bot_X>0) & (self.bot_Y >0): homing_roi_image = tmp_img[self.top_Y:self.bot_Y , self.top_X:self.bot_X] else: homing_roi_image = tmp_img.copy() cont_err,mtpt1,mtpt2=self.homing_midpoint(homing_roi_image) tol_mtpt1 = self.top_X + mtpt1 tol_mtpt2 = self.top_Y + mtpt2 # mod050720 following 2 lines self.defined_tol_mtpt1 = self.top_X + defined_mtptH self.defined_tol_mtpt2 = self.top_Y + defined_mtptL self.r_color_id = 2 x_ok = False y_ok = False if ((tol_mtpt1 > self.com_tol_top_X ) & (tol_mtpt1 < self.com_tol_bot_X) & (mtpt1 !=0)): x_ok = True if ((tol_mtpt2> self.com_tol_top_Y ) & (tol_mtpt2 < self.com_tol_bot_Y) & (mtpt2 !=0)): y_ok = True # if (tol_mtpt1 in range (self.com_tol_top_X, self.com_tol_bot_X)) and (tol_mtpt2 in range (self.com_tol_top_Y,self.com_tol_bot_Y)) and (mtpt2!=0): if ((x_ok == True ) and (y_ok==True)): #print (" tol ", self.com_tol_top_X ,tol_mtpt1 ,self.com_tol_bot_X, " 2 ",self.com_tol_top_Y , tol_mtpt2 ,self.com_tol_bot_Y) # self.show_color_arr[hm_fw_pos] = 1 # green self.r_color_id = 1 # mod050720 adding the following if if (do_delayed_check == True): # setting time delay only at initial home if(round(my_timer() - self.seq_begin_timer,2)> 2): self.home_at_fw_start_x,self.home_at_fw_start_y =tol_mtpt1,tol_mtpt2 #mod130720 home_check_result = True self.btn_color= btn_color_yellow #'self.hmPassBtn_yellow' else: home_check_result = True self.btn_color= btn_color_yellow #'self.hmPassBtn_yellow' # above line change 070720 else: #if (mtpt2 < self.hm1_mtpt_mhl[2]) and (mtpt2 > self.hm1_mtpt_mhl[3]) and (mtpt2!=0): self.seq_begin_timer = my_timer() self.r_color_id = 2 # self.show_color_arr[hm_fw_pos] = 2 # red home_check_result = False self.btn_color=btn_color_red # 'self.hmPassBtn_red' # self.str_ret_val = str_movement + " Tolerance Req " + str(defined_mtptH) + " " + str(defined_mtptL) +" Actual TX " + str(self.com_tol_top_X) + " VAL " + str(tol_mtpt1) +" BX " + str( self.com_tol_bot_X) + " TY " + str( self.com_tol_top_Y) + " VAL " + str(tol_mtpt2) +" BY " + str(self.com_tol_bot_Y) + " Final Result " + str(home_check_result) + " X Y Result " + str(x_ok) + " " + str(y_ok) self.str_ret_val = str_movement + " Current Tol X " + str(tol_mtpt1) + " Between " + str(self.com_tol_top_X) + "/" + str(self.com_tol_bot_X) + " Req Tol X " + str(self.defined_tol_mtpt1) + " Current Tol Y " + str(tol_mtpt2) + " Between " + str(self.com_tol_top_Y) + "/" + str(self.com_tol_bot_Y) + " Req Tol Y " + str(self.defined_tol_mtpt2) + " X Y Result " + str(x_ok) + " " + str(y_ok) + " Final Result " + str(home_check_result) return home_check_result #mod130720 do_rv_check added as a new function for reverse check def do_rv_check(self,tmp_img): # called from run_vision_function conditionally once 15 seconds rv_check_result = False # code same as above do_home_check with slight variation return rv_check_result #mod100720 def do_fw_check(self,tmp_img): # called from run_vision_function conditionally once 15 seconds fw_check_result = False # code same as above do_home_check with slight variation return fw_check_result def do_template_check(self,tmp_img,hm_fwd_check): # called from run_vision_function conditionally once 15 seconds self.r_color_id = 0 self.show_rect_id = 0 template_result=[0,0,0,0] # first one dummy # there is for loop here with range 1 to 4 . In sense loop runs 3 times return template_result def template_logging(self,cimg,jigid,tmp_res1,temp_res2,temp_res3): # called by do_template_check above imgpath = "../errtrack/f" image_time = int(datetime.datetime.now().timestamp()) save_filename = imgpath +str(image_time)+".png" cv2.imwrite(save_filename,cimg) next_row_id=0 insert_row((save_filename,image_time,jigid,tmp_res1,temp_res2,temp_res3)) def do_high_beam_contour(self,img1): # called from run_vision_function conditionally once 15 seconds cntr_result = False f if (area > 30000): cntr_result = True self.btn_color= 'self.hBeamBtn_green' return(cntr_result, [contours[0]]) # print routine start def do_print_barcode(self): # called from run_vision_function conditionally once 15 seconds # reads text file and prints to serial port / barcode printer ser.close() def homing_midpoint(self,img1): # used under do_home_check & fw_check and rv_check t1=far[0] t2=far[1] return (cont_try_error,t1,t2) def btn_color_set(self,btn_name_color): # called from recurring_timer continously for changing the color state of the buttons if (btn_name_color != "NA"): btnname_color = btn_name_color.split("_") btn_name = btnname_color[0] s_color = btnname_color[1] s_style = '' # print(btn_name," ", s_color) if s_color == 'red': s_style = '.setStyleSheet("font: bold;background-color: red;font-size: 12px;height: 28px;width: 80px;")' elif s_color == 'green': s_style = '.setStyleSheet("font: bold;background-color: green;font-size: 12px;height: 28px;width: 80px;")' # 230520 change for home and forward color set elif s_color == 'yellow': s_style = '.setStyleSheet("font: bold;background-color: yellow;font-size: 12px;height: 28px;width: 80px;")' elif s_color == 'gray': s_style = '.setStyleSheet("font: bold;background-color: gray;font-size: 12px;height: 28px;width: 80px;")' #'self.lBeamBtn', btns = ['self.hmPassBtn','self.fwPassBtn','self.rvPassBtn','self.hBeamBtn','self.allTestBtn','self.prnStatusBtn'] for btn in btns: if (str(btn_name) == str(btn)) | (str(btn_name) == 'ALL'): styl = btn+'.setStyleSheet("font: bold;background-color: red;font-size: 12px;height: 28px;width: 80px;")' styl = btn+ s_style eval(styl) def print_output(self, s): print(s) def thread_complete(self): print("THREAD COMPLETE!") def closeEvent(self, event): # print ("exit clicked") self.run_loop = False # self.threadpool.stop(self.worker) self.timer.stop() Acq_stop_one() # a call to function from external python file. sys.exit() def start_vision(self): # Pass the function to execute self.worker = VisionR(self.run_vision_function) # Any other args, kwargs are passed to the run function self.worker.signals.result.connect(self.print_output) # commented out by suresh self.worker.signals.finished.connect(self.thread_complete) # commented out by suresh self.worker.signals.progress.connect(self.progress_fn) # commented out by suresh # worker.signals.pass_image.connect(self.progress_fn) # commented out by suresh self.counter =0 #print ("Counter Reset") # Execute self.threadpool.start(self.worker) def modbus_connect(self): if (self.mb_connected==False): print("Connecting ...") # self.mb_connect_tried +=1 mb_connect_tries = 0 while mb_connect_tries <= 3: try: #client = ModbusClient('192.168.1.190', port=502) self.mb_connected = self.client.connect() print ("Connection Status {0}".format(self.mb_connected)) except AssertionError as error: print("Modbus Connection Error") self.mb_connected = False if self.mb_connected == True: mb_connect_tries = 4 else: mb_connect_tries +=1 time.sleep(1) if self.mb_connected: self.mbBtn.setStyleSheet("font: bold;background-color: green; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop:0 white, stop: 0.01 gray, stop:1 green);padding: 5px; font-size: 12px;height: 30px;width: 30px;") else: self.mbBtn.setStyleSheet("font: bold; color: black; border: 2px solid #555; border-radius: 20px; border-style: outset; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,radius: 1.35, stop:0 white, stop: 0.01 gray, stop:1 red);padding: 5px; font-size: 12px;height: 30px;width: 30px;") print("no Camera") def start_stop_vision_thread(self): if self.envOK[0] != 1: self.str_ret_val= self.envOK[2] + str(" Val ") + str(self.envOK[1]) + str(" Error ") + str(self.envOK[0]) #self.tm.setText(self.str_ret_val) #return if self.vision_thread_start == False: # self.start_run() self.visionStartStop.setText("Stop") self.start_time = my_timer() self.start_vision() self.timer.start() # self.run_loop = False # added on 290520 self.vision_thread_start = True else: self.visionStartStop.setText("Start") self.run_loop = False self.vision_thread_start = False # self.threadpool.stop(self.worker) self.timer.stop() Acq_stop_one() sys.exit() def read_table(self): # conditional read. not frequent. From vision_function . Read SQL TAble print ("read table done") # self.draw_rectangle_manual() def vld(self,in_val): # called from read_table for validation # checks if value from field is valid and not equal to None. If none returns 0 applies to numerics only ret_val = 0 if in_val == None: ret_val = 0 else: ret_val = int(in_val) return ret_val def recurring_timer(self): # pass self.btn_color_set(self.btn_color) self.prdLbl.setText(self.pr_name_in_hmi) #self.tm.setText(self.str_ret_val) app = QApplication([]) window = MainWindow() app.exec_()