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_()
