python 多线程拍照

相机为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)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值