Code128碼識別

        據code128編碼的規則:1、2、3、4黑白相間,寬度不同。數據起始符:211232,數據終止符:2331112,中間六位爲數據00-99,有對應的編碼。如果通過圖像識別出編碼,我們需要黑白框的寬度,判斷數據是否有效需要根據起始符和終止符確定。

如果確定每一個Code128碼框的寬度,首先需要對圖像進行矯正,然後如果圖像是非常清晰的化,簡單的可以直接使用矩形框選確定每一個黑色框的位置大小,再推斷出白色框的位置大小,如果圖像數據過於模糊,且用投影定位矩形框選等難以切割,則可以使用統計的方法進行識別。

"""Code128編碼字典Code128C轉Code128A"""
code128={"00":'sp',"01":'!',"02":'"',"03":'#',"04":'$',"05":'%',"06":'&',"07":'...',"08":'(',"09":')',
         "10":'*',"11":'+',"12":',',"13":'-',"14":'.',"15":'/',"16":'0',"17":'1',"18":'2',"19":'3',
         "20":'4',"21":'5',"22":'6',"23":'7',"24":'8',"25":'9',"26":':',"27":';',"28":'<',"29":'=',
         "30":'>',"31":'?',"32":'@',"33":'A',"34":'B',"35":'C',"36":'D',"37":'E',"38":'F',"39":'G',
         "40":'H',"41":'I',"42":'J',"43":'K',"44":'L',"45":'M',"46":'N',"47":'O',"48":'P',"49":'Q',
         "50":'R',"51":'S',"52":'T',"53":'U',"54":'V',"55":'W',"56":'X',"57":'Y',"58":'Z',"59":'[',
         "60":"\\","61":']',"62":'^',"63":'_',"64":'NUL',"65":'SOH',"66":'STX',"67":'ETX',"68":'EOT',"69":'ENQ',
         "70":'ACK',"71":'BEL',"72":'BS',"73":'HT',"74":'LF',"75":'VT',"76":'FF',"77":'CR',"78":'SO',"79":'SI',
         "80":'DLE',"81":'DC1',"82":'DC2',"83":'DC3',"84":'DC4',"85":'NAK',"86":'SYN',"87":'ETB',"88":'CAN',"89":'EM',
         "90":'SUB',"91":'ESC',"92":'FS',"93":'GS',"94":'RS',"95":'US',"96":'FNC3',"97":'FNC2',"98":'SHIFT',"99":'CodeC',
         "CodeB":'CodeB',"CodeA":'FNC4',"FNC1":'FNC1'}

"""Code128編碼字典轉Code128C"""
Code={'212222': '00', '222122': '01', '222221': '02', '121223': '03', '121322': '04', '131222': '05',
      '122213': '06', '122312': '07', '132212': '08', '221213': '09', '221312': '10', '231212': '11',
      '112232': '12', '122132': '13', '122231': '14', '113222': '15', '123122': '16', '123221': '17',
      '223211': '18', '221132': '19', '221231': '20', '213212': '21', '223112': '22', '312131': '23',
      '311222': '24', '321122': '25', '321221': '26', '312212': '27', '322112': '28', '322211': '29',
      '212123': '30', '212321': '31', '232121': '32', '111323': '33', '131123': '34', '131321': '35',
      '112313': '36', '132113': '37', '132311': '38', '211313': '39', '231113': '40', '231311': '41',
      '112133': '42', '112331': '43', '132131': '44', '113123': '45', '113321': '46', '133121': '47',
      '313121': '48', '211331': '49', '231131': '50', '213113': '51', '213311': '52', '213131': '53',
      '311123': '54', '311321': '55', '331121': '56', '312113': '57', '312311': '58', '332111': '59',
      '314111': '60', '221411': '61', '431111': '62', '111224': '63', '111422': '64', '121124': '65',
      '121421': '66', '141122': '67', '141221': '68', '112214': '69', '112412': '70', '122114': '71',
      '122411': '72', '142112': '73', '142211': '74', '241211': '75', '221114': '76', '413111': '77',
      '241112': '78', '134111': '79', '111242': '80', '121142': '81', '121241': '82', '114212': '83',
      '124112': '84', '124211': '85', '411212': '86', '421112': '87', '421211': '88', '212131': '89',
      '214121': '90', '412121': '91', '111143': '92', '111341': '93', '131141': '94', '114113': '95',
      '114311': '96', '411113': '97', '411311': '98', '113141': '99', "211412":'StartA',"211214":'StartB',
      "211232":'StartC',"2331112":'Stop',"114131":'CodeB',"311141":'CodeA',"411131":'FNC1'}

        基於統計方法實現Code128碼實現源碼:

#!usr/bin/python3
# -*- coding:utf-8 -*-
# author:SingWeek

import cv2
from para import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys, os
import matplotlib.pyplot as plt

def ImgRead(file):
    """
    處理圖像讀取
    :param file:讀取的圖像路徑
    :return:
    """
    img=cv2.imread(file, 0)
    return img

def CalcHist(img):
    """
    將圖像沿着編碼方向投影
    :param img:
    :return: 投影后的波形數值
    """
    w, h = img.shape[:2]  # 180,800
    print(w,h)
    lists = []
    for i in range(h):  # 像素值統計
        tmp = 0
        for j in range(w):
            tmp += img[j][i]
        lists.append(tmp)
    return lists

def Split(lists,means = 16100):
    """
    對投影后的分段波形值進行切分
    :param lists: 投影后的分段波形數值
    :param means:切分值
    :return:
    """
    result=[]
    Flags = False
    Whitenum = 0
    Blacknum = 0
    for i in lists:
        if i > means:  # 白色點
            if Flags == True:
                result.append(Blacknum)
                Whitenum = 0
                Blacknum = 0
            Flags = False
            Whitenum += 1
        else:  # 黑色點
            if Flags == False:
                result.append(Whitenum)
                Whitenum = 0
                Blacknum = 0
            Blacknum += 1
            Flags = True
    return result

def Calc(startC,a1,a2,a3):
    tmpdata=''
    for i in range(len(startC)):
        j=int(startC[i])
        if j<a1*2:#最小
            tmpdata += '1'
        elif j>a2*1.8:#最大
            tmpdata += '4'
        else:
            if j<a2:
                #根據疑似2標籤的值判斷其周圍的數據確定是1還是2
                if i<len(startC)-1:
                    tmp = int(startC[i + 1])
                    if tmp * 1.8 < j:
                        tmpdata += '1'
                    else:
                        if i>0:
                            tmp=int(startC[i-1])
                            if tmp * 1.8 < j:
                                tmpdata += '1'
                            else:
                                if tmp>a2:
                                    tmpdata += '3'
                                else:
                                    tmpdata += '2'
                        else:
                            tmpdata += '2'
                else:
                    tmpdata += '2'
            else:
                if j>=a3:
                    tmpdata += '3'
                else:#對於大於疑似標籤2的值,可能是3還是2做進一步判斷
                    if i<len(startC)-1:
                        tmp=int(startC[i+1])
                        if tmp*1.8<j:
                            if tmp<=a1:
                                tmpdata += '2'
                            else:
                                tmpdata += '3'
                        else:
                            if i<len(startC)-1:
                                tmp = int(startC[i + 1])
                                if tmp * 1.8 < j:
                                    tmpdata += '3'
                                else:
                                    tmpdata += '2'
                            else:
                                tmpdata += '2'
                    else:
                        tmpdata += '2'
        print(i, tmpdata)
    print(tmpdata)
    return tmpdata

def CodeList(result,type='codec'):
    """
    閾值切分後的波形值
    :param result:
    :param type:返回的值類型
    :return:
    """
    result = result[1:]  # 去除最開始的空白值
    startC = result[:6]  # 其始值
    data = result[6:-7]  # 終止值
    endC = result[-7:]  # 數據
    if len(data) % 6 == 0:  # 數據位校驗
        print("OK!")
        sum1list = [startC[1], startC[2], endC[3], endC[4], endC[5]]
        sum2list = [startC[0], startC[3], startC[5], endC[0], endC[6]]
        sum3list = [startC[4], endC[1], endC[2]]
        a1, b1 = divmod(sum(sum1list), 5)
        a2, b2 = divmod(sum(sum2list), 5)
        a3, b3 = divmod(sum(sum3list), 3)
        start=Calc(startC, a1, a2, a3)
        end=Calc(endC, a1, a2, a3)
        DataFlags=False
        try:
            if Code[start]=="StartC" and Code[end]=="Stop":
                print("校驗成功")
                DataFlags = True
            else:
                print("校驗失敗")
                return start+"-"+end
        except:
            print("校驗失敗")
            return start + "-" + end
        if DataFlags==True:
            codevalue = []
            for i in range(0, len(data), 6):
                tmpdata = Calc(data[i:i + 6], a1, a2, a3)
                codevalue.append(Code[tmpdata])
            if type=='codec':
                tmp=''
                for i in codevalue:
                    tmp+=i
                return tmp
            else:
                tmp=[]
                for i in codevalue:
                    tmp.append(code128[i])
                print("******************",tmp)
                return tmp
    else:
        print("Wrong!")
        return "Data length wrong!"

def Get_Threshold(lists):
    """
    自動切割閾值獲取
    :param lists:
    :return:
    """
    means=sum(lists)/len(lists)
    s=False
    e=False
    num=0
    up=[]
    down=[]
    upsum=[]
    downsum=[]
    upnum=0
    downnum=0
    for i in range(len(lists)):
        if lists[i]<means:
            s=True
            downsum.append(int(lists[i]))
            downnum+=1
        else:
            e=True
            upsum.append(int(lists[i]))
            upnum+=1
        if s==True and e==True:
            num+=1
            if num%2==0:
                down.append(max(downsum))
            else:
                up.append(max(upsum))
            s = False
            e = False
            upsum = []
            downsum = []
            upnum = 0
            downnum = 0
    up.append(max(upsum))
    # print(means)
    # print(up)
    # print(down)
    # print(max(down)-min(up))
    # print(min(up)-min(down))
    if max(down)-min(up)<0:
        # print(max(down))
        return max(down)
    result=[]
    try:
        for i in range(len(up)):
            if up[i]-max(down)>min(up)-min(down):#踢掉臨近切分值
                result.append(up[i])
        print(result,min(result),min(result)-(min(up)-min(down))/10)
        return min(result)-(min(up)-min(down))/10
    except:
        return max(down)

class MyWindow(QWidget):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)

        self.setGeometry(300, 300, 200, 300)
        self.setWindowTitle('Code128')

        self.startbtn=QPushButton("運行",self)
        self.typelabel=QLineEdit("codec",self)
        self.labelshow=QLineEdit("顯示結果",self)
        self.thre=QLineEdit("0",self)

        self.startbtn.setGeometry(20, 20, 160, 50)
        self.typelabel.setGeometry(20, 90, 160, 50)
        self.thre.setGeometry(20, 140, 160, 50)
        self.labelshow.setGeometry(20, 190, 160, 50)

        self.show()
        self.startbtn.clicked.connect(self.StartRun)

    def StartRun(self):
        self.file = QFileDialog.getOpenFileNames(None, "", "", "")[0]
        type=self.typelabel.text()
        data_thread = UpdateData(self.file,type,self.labelshow,int(self.thre.text()))
        data_thread.run()
        self.labelshow.setText("請重新選擇!")

class UpdateData(QThread):
    """界面和 運行相分離,通過信號與槽來進行參數傳遞"""
    def __init__(self, file,type,label,thredata,parent=None):
        super(UpdateData, self).__init__(parent)
        self.file = file[0]
        self.type=type
        self.label=label
        self.thredata=thredata

    def run(self):
        img=ImgRead(self.file)
        # cv2.imshow("img",img)
        lists=CalcHist(img)
        print("----")
        if self.thredata==0:
            print("*****")
            thre0=int(Get_Threshold(lists))
            print(thre0)
            result=Split(lists,thre0)
        else:
            result=Split(lists,self.thredata)
        print("切分後的數組:",result)
        out=CodeList(result,self.type)
        self.label.setText(str(out))
        plt.plot(lists)
        plt.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mywindow = MyWindow()
    mywindow.show()
    app.exit(app.exec_())

測試圖像:

實驗結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章