相机为basler,logic
balser相机识别条码,进行拍照
args[0] 为logging的参数保证log实时传输到GUI界面
调用方法:
main_process(args[0]).camera_run()
import sys
import errno
import cv2
import numpy as np
import json
import logging
import threading
import logging.handlers
from datetime import datetime
import subprocess
DEBUG = False
# 條碼解析庫
if not DEBUG:
from dbr import *
from pyzbar import pyzbar
# basler相機
from pypylon import pylon
sys.path.append('../')
# 刷槍串口通訊
import serial # 导入串口通信库
from time import sleep
ser = serial.Serial()
# define config variable
config = {}
# 获取当前日期
testdate = datetime.now().strftime('%Y%m%d')
class main_process:
flag = True
def __init__(self, loger):
self.logging = loger
# 读取治具编号
if not os.path.exists(r'D:\LabelAOI\Config\FIXID.INI'):
print('FIXID INI FILE NOT EXIST')
sys.exit(255)
self.fixid = self.Readfile(r'D:\LabelAOI\Config\FIXID.INI')
# 读取jason配置档
if DEBUG:
cfg_path = 'BOXAOI.json'
else:
cfg_path = 'D:\\LabelAOI\\Config\\BOXAOI_baslor.json'
self.config = main_process.ReadConfig(cfg_path)
self.outpath = self.config[self.fixid]['out_path']
webcams = self.config[self.fixid]['webcam']
# 扫码相机
self.scancams = [s for s in webcams if s.startswith('S') and s != 'S_main']
# scancams=[s for s in webcams if s.startswith('S')]
# 拍照相机
self.capcams = [s for s in webcams if s.startswith('L')]
# 主相机以外的相机
self.subcams = [s for s in webcams if s != 'S_main']
# log初始化
# self.InitLog(outpath=self.outpath)
# 导入jason config配置档
# logging = self.logging
@staticmethod
def ReadConfig(cfg_name):
with open(cfg_name, "r") as reader:
cfg = json.loads(reader.read())
return cfg
# 初始化log
# def InitLog(self, outpath='', level=logging.DEBUG):
# """ Generate log file
#
# Keyword Arguments:
# folder {str} -- log of folder (default: logs)
# file {str} -- log name (default: filename + .log)
# level object -- log level setup
#
# Returns:
# True -- Generate logging successful
# """
# # log 输出
# LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
# DATE_FORMAT = "%Y/%m/%d %H:%M:%S %p"
# formatter = logging.Formatter(fmt=LOG_FORMAT, datefmt=DATE_FORMAT)
# if DEBUG:
# log_path = 'capture.log'
# else:
# log_path = os.path.join(outpath, 'capture.log')
# fh = logging.handlers.RotatingFileHandler(log_path,
# maxBytes=20 * 1024 * 1024, # Maximum file size 20MB,
# backupCount=20,
# encoding="utf-8") # added support UTF-8
# fh.setFormatter(formatter)
# fh.setLevel(logging.DEBUG)
# logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT, level=logging.DEBUG)
# logging.getLogger('').addHandler(fh) # '' is root logger name
# logging.getLogger('').setLevel(logging.DEBUG)
# print("InitLog() function execute successful.")
# print("")
# return True
# 判断字串由字母和数字组成
@staticmethod
def strtype_check(teststr):
checkstrs = str(teststr)
for chkstr in checkstrs:
if chkstr.isupper() or chkstr.islower() or chkstr.isdigit():
continue
else:
return False
return True
# 导入配置档
def Readfile(self, file):
with open(file, "r") as f:
content = f.readlines()
content1 = content[0].strip('\n')
return content1
@staticmethod
def getintcount(teststr):
intcount = 0
for i in teststr:
if i.isdigit():
intcount += 1
return intcount
# 图片裁剪
def cutimg(self, test_pic, testfun):
cuth, cutw, cutno = self.config[self.fixid][testfun][4:7]
img = cv2.imread(test_pic)
H, W, A = img.shape # 获取图片信息,高和宽
cut_h = int(cuth) # 高裁剪2
cut_w = int(cutw) # 宽裁剪2
cut_no = int(cutno) # 取裁剪3
a = H // cut_h
b = W // cut_w
count = 0
for i in range(0, H, a):
for j in range(0, W, b):
count += 1
if cut_no != None and count != cut_no:
continue
result = img[i:i + a, j:j + b]
savename = os.path.splitext(test_pic)[0] + "_cut_" + "%d.jpg" % count
cv2.imwrite(savename, result)
return savename
# 同步时间
@staticmethod
def synctime(testdate):
year = int(testdate[:4])
month = int(testdate[4:6])
day = int(testdate[6:8])
subprocess.run('date %d-%d-%d' % (year, month, day), shell=True)
@staticmethod
def read_dbr(logger, test_pic):
reader = BarcodeReader()
# DBR 试用key,试用期30天
# 试用时将电脑时间更改为安装DBR的初始时间,防止过期
reader.init_license(
"t0068MgAAACGuAdndQ2rd3So2yZZr57l4NkJaDYw/c/pyy3rX9XGkmtoig+P/CmfsV0CTg7mEVwLHQz1XRtmxl/i4LYhNaIk=")
subprocess.run('date %d-%d-%d' % (2020, 12, 25), shell=True)
text_results = reader.decode_file(test_pic)
# 將系統時間改回來
main_process.synctime(testdate)
if text_results != None:
for text_result in text_results:
print(
"Barcode Format :" + text_result.barcode_format_string + "," + "Barcode Text :" + text_result.barcode_text)
logger.info("Barcode Format :%s,Barcode Text :%s", text_result.barcode_format_string,
text_result.barcode_text)
# 解析15码的SSN条码或者ADID或者OA改机SSN
if (len(text_result.barcode_text)) == 15 and (
text_result.barcode_text[4:6] == 'CV' or text_result.barcode_text[
6:8] == 'CV' or text_result.barcode_text[
3:7] == 'OACV') and main_process.strtype_check(text_result.barcode_text) == True:
logger.info("SSN IS :%s", text_result.barcode_text)
return text_result.barcode_text
# 解析12码的MAC条码
if text_result.barcode_format_string == 'CODE_128' and (
len(text_result.barcode_text)) == 12 and text_result.barcode_text[
:3] != '90N' and text_result.barcode_text[
:4] != 'ASUN' and main_process.strtype_check(
text_result.barcode_text) == True:
# if text_result.barcode_format_string=='CODE_128' and (len(text_result.barcode_text))==12 and getintcount(text_result.barcode_text) <10 and text_result.barcode_text[:3]!='90N' and text_result.barcode_text[:4]!='ASUN' and strtype_check(text_result.barcode_text)==True:
logger.info("MAC IS :%s", text_result.barcode_text)
return text_result.barcode_text
# 解析13码的Microsoft KEY条码
if text_result.barcode_format_string == 'CODE_128' and (
len(text_result.barcode_text)) == 13 and main_process.getintcount(
text_result.barcode_text) == 13 and main_process.strtype_check(
text_result.barcode_text) == True:
logger.info("Microsoft KEY IS :%s", text_result.barcode_text)
return text_result.barcode_text
return False
# 将字符串写入文件
@staticmethod
def save_words(save_path, words):
f = open(save_path, 'a+', encoding='utf-8')
f.write(words)
f.write('\n')
f.close()
# pyzbar解析图片条码
@staticmethod
def read_pyzbar(logger, test_pic):
image = cv2.imread(test_pic)
barcodes = pyzbar.decode(image)
# 判断原图能否解析到条码
if barcodes != None:
for barcode in barcodes:
barcodeData = barcode.data.decode("utf-8")
barcodeType = barcode.type
print("[INFO] Found {} barcode: {}".format(barcodeType, barcodeData))
logger.info("Barcode Format :%s,Barcode Text :%s", barcodeType, barcodeData)
# 解析15码的SSN条码或者ADID或者OA改机SSN
if (len(barcodeData)) == 15 and (barcodeData[4:6] == 'CV' or barcodeData[6:8] == 'CV' or barcodeData[
3:7] == 'OACV') and main_process.strtype_check(
barcodeData) == True:
logger.info("SSN IS :%s", barcodeData)
return barcodeData
# 解析12码的MAC条码
if (len(barcodeData)) == 12 and barcodeType == 'CODE128' and barcodeData[:3] != '90N' and barcodeData[
:4] != 'ASUN' and main_process.strtype_check(
barcodeData) == True:
# if (len(barcodeData))==12 and barcodeType=='CODE128' and getintcount(barcodeData) <10 and barcodeData[:3]!='90N' and barcodeData[:4]!='ASUN' and strtype_check(barcodeData)==True:
logger.info("MAC IS :%s", barcodeData)
return barcodeData
# 解析13码的Microsoft KEY条码
if (len(barcodeData)) == 13 and barcodeType == 'CODE128' and main_process.getintcount(
barcodeData) == 13 and main_process.strtype_check(barcodeData) == True:
logger.info("Microsoft KEY IS :%s", barcodeData)
return barcodeData
# 当原图解析不到条码时对原图进行卷积运算,变换更清晰
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
dst = cv2.filter2D(image, -1, kernel=kernel)
barcodes1 = pyzbar.decode(dst)
if barcodes1 != None:
for barcode in barcodes1:
barcodeData = barcode.data.decode("utf-8")
barcodeType = barcode.type
print("[INFO] Found {} barcode: {}".format(barcodeType, barcodeData))
logging.info("Barcode Format :%s,Barcode Text :%s", barcodeType, barcodeData)
# 解析15码的SSN条码或者ADID或者OA改机SSN
if (len(barcodeData)) == 15 and (barcodeData[4:6] == 'CV' or barcodeData[6:8] == 'CV' or barcodeData[
3:7] == 'OACV') and main_process.strtype_check(
barcodeData) == True:
logger.info("SSN IS :%s", barcodeData)
return barcodeData
# 解析12码的MAC条码
if (len(barcodeData)) == 12 and barcodeType == 'CODE128' and barcodeData[:3] != '90N' and barcodeData[
:4] != 'ASUN' and main_process.strtype_check(
barcodeData) == True:
# if (len(barcodeData))==12 and barcodeType=='CODE128' and getintcount(barcodeData) <10 and barcodeData[:3]!='90N' and barcodeData[:4]!='ASUN' and strtype_check(barcodeData)==True:
logger.info("MAC IS :%s", barcodeData)
return barcodeData
# 解析13码的Microsoft KEY条码
if (len(barcodeData)) == 13 and barcodeType == 'CODE128' and main_process.getintcount(
barcodeData) == 13 and main_process.strtype_check(barcodeData) == True:
logger.info("Microsoft KEY IS :%s", barcodeData)
return barcodeData
return False
# basler相机拍照扫码
# baslercam('S_main', 'SSN.DAT')
def baslercam(self, testfun, snfile):
try:
# conecting to the first available camera
camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice())
camera.Open()
# The name of the pylon file handle,导入相机设定
# baslercfg="acA5472-17uc_23728738_ssn.pfs"
baslercfg = self.config[self.fixid][testfun][3]
nodeFile = r"D:\\LabelAOI\\Config\\" + baslercfg
pylon.FeaturePersistence.Load(nodeFile, camera.GetNodeMap(), True)
camera.Close()
# Grabing Continusely (video) with minimal delay
camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly)
converter = pylon.ImageFormatConverter()
# converting to opencv bgr format
converter.OutputPixelFormat = pylon.PixelType_BGR8packed
converter.OutputBitAlignment = pylon.OutputBitAlignment_MsbAligned
windowName = testfun + " Barcode Reader"
ret = True
while camera.IsGrabbing():
grabResult = camera.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)
if grabResult.GrabSucceeded():
# Access the image data
image = converter.Convert(grabResult)
img = image.GetArray()
# cv2.imshow(windowName, img)
picname = self.outpath + '\\' + testfun + '_' + 'CAM' + '_basler' + '.jpg'
self.logging.info('picture name is %s', picname)
cv2.imwrite(picname, img)
if snfile == "NA":
ret = False
break
testpic = self.cutimg(picname, testfun)
ssncode = 1111
ssncode = main_process.read_dbr(self.logging, testpic)
if ssncode:
file = open(self.outpath + '\\' + snfile, 'w')
file.write(ssncode)
file.close()
ret = False
break
ssncode = 1111
ssncode = main_process.read_pyzbar(self.logging, testpic)
if ssncode:
file = open(self.outpath + '\\' + snfile, 'w')
file.write(ssncode)
file.close()
ret = False
break
# 'ESC' for quit
k = cv2.waitKey(1)
if k == 27:
break
grabResult.Release()
# Releasing the resource
camera.StopGrabbing()
camera.Close()
# cv2.destroyWindow(windowName)
# cv2.destroyAllWindows()
return picname
except Exception as e:
self.logging.error(e)
return None
def logitechcam(self, camindex, focallen, testfun, snfile):
try:
if DEBUG:
# return 255 # test fail
return "abcd5545555555" # test pass
vc = cv2.VideoCapture(camindex, cv2.CAP_DSHOW)
vc.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) # 设置图像宽
vc.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) # 设置图像高
vc.set(28, focallen) # 设置相机焦距
# cap.set(15,75) #设置相机曝光
# vc.set(10,100)#设置相机亮度
if vc.isOpened():
self.logging.info("Initial the Camera ...")
for i in range(1):
rval, frame = vc.read()
else:
self.logging.info('cannot open camera %s', str(camindex))
print('cannot open camera' + str(camindex))
return 255
windowName = testfun + " Barcode Reader"
ret = True
code = ""
while ret:
# cv2.imshow(windowName, frame)
rval, frame = vc.read()
# picname = testfun+'_'+'CAM' + str(camindex) + '_' + testdate + str(get_time()) + '.jpg'
picname = self.outpath + '\\' + testfun + '_' + 'CAM' + str(camindex) + '.jpg'
self.logging.info('picture name is %s', picname)
cv2.imwrite(picname, frame)
if snfile == "NA":
ret = False
break
if os.path.exists(self.outpath + '\\' + 'noside.dat') and not testfun == 'S_main':
ret = False
break
if os.path.exists(self.outpath + '\\' + snfile):
ret = False
break
ssncode = 1111
ssncode = main_process.read_dbr(self.logging, picname)
if ssncode:
main_process.save_words(self.outpath + '\\' + 'snjpg.txt', picname)
file = open(self.outpath + '\\' + snfile, 'w')
file.write(ssncode)
file.close()
ret = False
break
ssncode = 1111
ssncode = main_process.read_pyzbar(self.logging, picname)
if ssncode:
main_process.save_words(self.outpath + '\\' + 'snjpg.txt', picname)
file = open(self.outpath + '\\' + snfile, 'w')
file.write(ssncode)
file.close()
ret = False
break
# 'ESC' for quit
key = cv2.waitKey(20)
if key == 27:
cv2.destroyAllWindows()
break
vc.release()
# cv2.destroyWindow(windowName)
cv2.destroyAllWindows()
return picname
except Exception as e:
self.logging.error(e)
return None
def mulrun(self, testfuns):
threads = []
# Create new threads
# testfuns is: 'L_main', 'S_left', 'S_right'
# outpath is: D:\LabelAOI\TEST
# testdate = datetime.now().strftime('%Y%m%d')
# fixid : LABELAOI-BN28
for t in testfuns:
d = DoProcess(out_path=self.outpath,
test_fun=t,
test_date=testdate,
fixid=self.fixid,
logger = self.logging)
d.start() # Start new Threads
threads.append(d)
# Wait for all threads to complete
for t in threads:
t.join()
# parse results
for t in threads:
if t.ret == 255:
sys.exit(t.ret) # return fail
# sys.exit(0) # return successful
def camera_run(self):
# S_main 扫SSN条码
# if self.config[self.fixid]['S_main'][0] == "basler":
# self.baslercam('S_main', 'SSN.DAT')
# else:
# camindex, focallen, snfile = self.config[self.fixid]['S_main'][:3]
# # ['basler', '0000', 'SSN.DAT']
# self.logitechcam(int(camindex), int(focallen), 'S_main', snfile)
if len(self.subcams) <= 4:
self.mulrun(self.subcams)
else:
if len(self.scancams) != 0:
self.mulrun(self.scancams)
if len(self.capcams) != 0:
self.mulrun(self.capcams)
class DoProcess(threading.Thread, main_process):
"""[Executing camera function]
Keyword Arguments:
cam_fun -- have "S_main", "L_main", "S_left", "S_right"
out_path -- output path
test_fun -- test function name
test_date -- test date
Returns:
ret -- 255 is fail
# testfuns is: 'L_main', 'S_left', 'S_right'
# outpath is: D:\LabelAOI\TEST
# testdate = datetime.now().strftime('%Y%m%d')
# fixid : LABELAOI-BN28
"""
def __init__(self, out_path, test_fun, test_date, fixid, logger):
threading.Thread.__init__(self)
# super().__init__()
self.out_path,self.outpath = out_path, out_path
self.test_fun = test_fun
self.test_date = test_date
self.fixid = fixid
self.logging = logger
# 读取jason配置档
if DEBUG:
cfg_path = 'BOXAOI.json'
else:
cfg_path = 'D:\\LabelAOI\\Config\\BOXAOI_baslor.json'
self.config = main_process.ReadConfig(cfg_path)
# "S_left" : ["0","50","NA"],
# "L_main" : ["basler","0000","NA",
self.port, self.focus, self.snfile = self.config[self.fixid][self.test_fun][:3]
self.ret = -1 # return code
self.result = "FAIL"
def Output(self, f_path, data):
if not os.path.exists(os.path.dirname(f_path)):
try:
os.makedirs(os.path.dirname(f_path)) # create folder
except OSError as exc: # Guard against race condition
if exc.errno != errno.EEXIST:
raise
f = open(f_path, 'w')
f.write(data)
f.close()
def run(self):
if self.port == 'basler':
# self.test_fun:'L_main'
# self.port:0000
self.logging.info('camera %s scan %s barcode start:', self.port, self.test_fun)
self.ret = self.baslercam(self.test_fun, self.snfile)
self.logging.info('Camera %s return %s', self.port, self.ret)
if self.ret == 255:
self.logging.error('camera %s not found,capture FAIL!', self.port)
self.result = 'FAIL'
self.ret = 255
main_process.flag = False
else:
self.logging.info('camera %s take photo %s label Finish!', self.port, self.test_fun)
self.result = 'PASS'
self.ret = 0
elif self.port == 'DATALOGIC':
self.logging.info('scanbarner %s scan %s barcode start:', self.port, self.test_fun)
self.logging.info('scanbarner %s return %s', self.port, self.ret)
if self.ret == 255:
self.logging.error('scanbarner %s not found,test FAIL!', self.port)
self.result = 'FAIL'
self.ret = 255
main_process.flag = False
else:
self.logging.info('scanbarner %s scan barcode %s Finish!', self.port, self.test_fun)
self.result = 'PASS'
self.ret = 0
else:
# self.port, self.focus, self.snfile, self.test_fun
# '0', '45', 'NA' 'S_left'
self.logging.info('camera %s scan %s barcode start:', self.port, self.test_fun)
self.ret = self.logitechcam(int(self.port), int(self.focus), self.test_fun, self.snfile)
self.logging.info('Camera %s return %s', self.port, self.ret)
if self.ret == 255:
self.logging.error('camera %s not found,capture FAIL!', self.port)
self.result = 'FAIL'
self.ret = 255
main_process.flag = False
else:
self.logging.info('camera %s take photo %s label Finish!', self.port, self.test_fun)
self.result = 'PASS'
self.ret = 0
# write pass log
f_path = os.path.join(self.out_path, self.test_fun + '_' + self.result + '.log')
self.Output(f_path, self.result)