QuaggaJS是條形碼掃描器完全用JavaScript編寫支持實時的本地化和各種類型的條形碼,如
EAN, CODE 128,CODE 39,EAN 8,UPC-A ,UPC-C ,I2of5, 2of5,CODE 93和CODABAR.該類庫還能夠 getUserMedia直接訪問用戶的相機流,使得我們的開發變得更加簡單。
項目地址: https://github.com/serratus/quaggaJS#browser-support
常用API
Quagga.init(config,callback)
該方法初始化給定配置的庫config(見下文),並調用callback(err)Quagga完成引導階段之后。如果配置了實時檢測,則初始化過程還要求攝像機訪問。如果發生錯誤,err 則設置參數並包含有關原因的信息。可能的原因可能inputStream.type是設置LiveStream,但瀏覽器不支持此API,或者簡單地說,如果用戶拒絕使用相機的權限。
如果沒有指定目標,QuaggaJS會查找與CSS選擇器匹配的元素#interactive.viewport(為了向后兼容)。 target可以是一個字符串(與CSS元素匹配的DOM節點)或DOM節點。
Quagga.start()
當庫被初始化時,該start()方法啟動視頻流並開始定位和解碼圖像。
Quagga.stop()
如果解碼器當前正在運行,則在調用stop()解碼器之后不再處理任何圖像。另外,如果在初始化時請求相機流,則此操作也會斷開相機的連接。
Quagga.onProcessed(callback)
該方法注冊callback(data)處理完成后為每個幀調用的函數。該data對象包含有關操作成功/失敗的詳細信息。取決於檢測和/或解碼是否成功,輸出會有所不同
Quagga.onDetected(callback)
注冊一個callback(data)功能,每當條形碼圖案被定位和解碼成功時觸發。傳遞的data對象包含關於解碼處理的信息,包括可以通過調用獲得的檢測到的代碼data.codeResult.code。
Quagga.offProcessed(handler)
如果onDetected事件不再是相關的,請從事件隊列中offProcessed刪除給定handler的事件
Quagga.offDetected(handler)
如果onDetected事件不再相關,請從事件隊列中offDetected刪除給定handler的事件。
結果對象:
回調通入onProcessed,onDetected接收data在執行對象。該data對象包含以下信息。取決於成功,某些領域可能是undefined或只是空的。
{ " codeResult ": { "代碼": " FANAVF1461710 ", //解碼代碼作為字符串 "格式": " code_128 ",//或code_39,庫德巴,EAN_13,ean_8,UPC_A,upc_e "啟動": 355, " end ": 26, " codeset ": 100, " startInfo ": { " error ": 1.0000000000000002, " code ": 104, " start ": 21, " end ": 41 }, " decodeCodes ": [{ " code ": 104, " start ": 21, " end ": 41 }, //為了簡潔而剝離 { "錯誤": 0.8888888888888893, "代碼": 106, "啟動": 328, "端": 350 }], " endInfo ": { " error ": 0.8888888888888893, " code ": 106, " start ": 328, " end ": 350 }, "方向": - 1 }, " line ": [{ " x ": 25.97278706156836, " y ": 360.5616435369468 },{ " x ": 401.9220519377024, " y ": 70.87524989906444 }], "角度": - 0.6565217179979483, "圖案": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, / * ...* / 1 ], " box ": [ [ 77.4074243622672,410.9288668804402 ] [ 0.050203235235130705,310.53619724086366 ] [ 360.15706727788256,33.05711026051813 ] [ 437.5142884049146,133.44977990009465 ] ] " box ": [ [ [ 77.4074243622672,410.9288668804402 ] [ 0.050203235235130705,310.53619724086366 ] [ 360.15706727788256,33.05711026051813 ] [ 437.5142884049146,133.44977990009465 ] ] [ [ 248.90769330706507,415.2041489551161 ] [ 198.9532321622869,352.62160512937635 ] [ 339.546160777576,240.3979259789976 ] [ 389.5006219223542,302.98046980473737 ] ] ] }
Configuration
QuaggaJS附帶的配置涵蓋了默認用例,可根據具體要求進行微調。
該配置由config定義以下高級屬性的對象管理:
{ numOfWorkers: 4, locate: true, inputStream: {...}, frequency: 10, decoder:{...}, locator: {...}, debug: false, }
numOfWorkers
QuaggaJS支持線程,並在4線程的默認配置下運行。該數字應與目標設備中可用的核心數量一致。
如果您不知道前面的數字,或者設備種類太多,您可以使用navigator.hardwareConcurrency(參見 這里)可用或使用核心估計器。
Locate
QuaggaJS的主要特征之一就是能夠在給定的圖像中定位條形碼。該locate屬性控制是否啟用此功能(默認)或關閉。
為什么有人會關閉此功能?本地化條形碼是一項計算上昂貴的操作,可能無法在某些設備上正常工作。另一個原因是缺乏自動對焦產生模糊的圖像,這使得本地化功能非常不穩定。
然而,即使沒有上述情況適用,還有一種情況可能會禁用locate:如果條形碼的方向和/或大致位置已知,或者如果要引導用戶通過矩形大綱。這可以同時提高性能和魯棒性。
inputStream
該inputStream屬性定義了QuaggaJS中的圖像/視頻的來源。
{ name: "Live", type: "LiveStream", constraints: { width: 640, height: 480, facingMode: "environment", deviceId: "7832475934759384534" }, area: { // defines rectangle of the detection/localization area top: "0%", // top offset right: "0%", // right offset left: "0%", // left offset bottom: "0%" // bottom offset }, singleChannel: false // true: only the red color-channel is read }
首先,type屬性可以被設置為三個不同的值: ImageStream,VideoStream,或LiveStream(默認值),並應根據使用情況進行選擇。很可能,默認值是足夠的。
第二,該constraint鍵定義輸入圖像的物理尺寸和附加屬性,例如facingMode在多個連接的設備的情況下設置用戶相機的源。另外,如果需要,deviceId如果給用戶選擇相機,則可以設置。這可以通過MediaDevices.enumerateDevices()輕松實現
第三,area支路限制圖像的解碼區域。值以百分比形式給出,與使用時的CSS樣式屬性相似 position: absolute。這area在locate屬性設置false為為用戶定義矩形的情況下也是有用的。
最后一個關鍵singleChannel僅在有人想要調試解碼器的錯誤行為的情況下才是相關的。如果設置為true輸入圖像的紅色通道,而不是計算源RGB的灰度值。
frequency:
此頂級屬性控制視頻流的掃描頻率。它是可選的,並定義每秒掃描的最大數量。這對於掃描會話長時間運行的情況以及諸如CPU功耗等資源非常有用。
decoder:
QuaggaJS通常以兩級方式運行(locate設置為true),在條形碼位於之后,解碼過程開始。解碼是將條形轉換成其真實含義的過程。大多數配置選項decoder僅用於調試/可視化目的。
{ readers: [ 'code_128_reader' ], debug: { drawBoundingBox: false, showFrequency: false, drawScanline: false, showPattern: false } multiple: false }
最重要的屬性是readers需要在會話期間解碼的條形碼類型的數組。可能的值是:
- code_128_reader(默認)
- ean_reader
- ean_8_reader
- code_39_reader
- code_39_vin_reader
- codabar_reader
- upc_reader
- upc_e_reader
- i2of5_reader
- 2of5_reader
- code_93_reader
為什么默認情況下不會激活所有類型?只是因為應該為用例明確定義一組條形碼。更多的解碼器意味着更多的可能的沖突,或者是錯誤的。應該照顧讀者的命令,因為有些人可能會返回一個值,即使它不是正確的類型(EAN-13與UPC-A)。
該multiple屬性告訴解碼器,在找到有效的條形碼后是否應該繼續解碼。如果設置為多個true,結果將作為結果對象的數組返回。數組中的每個對象將具有一個 box,並且可能具有codeResult取決於解碼單個框的成功。
其余的性質drawBoundingBox,showFrequency,drawScanline和 showPattern大多的調試和可視化過程中的利益。
啟用擴展EAN:
默認設置ean_reader不能讀取擴展名,如EAN-2或 EAN-5。為了激活這些補充,您必須按照以下配置提供它們:
decoder: { readers: [{ format: "ean_reader", config: { supplements: [ 'ean_5_reader', 'ean_2_reader' ] } }] }
請注意,supplements當發現第一次補充時,reader停止解碼的事宜的順序。因此,如果您對EAN-2和EAN-5擴展感興趣,請使用上面描述的順序。
重要的是要提及,如果提供補充,常規的EAN-13代碼不能再讀取同一個reader。如果您想閱讀帶有和不帶擴展名的EAN-13,則必須向ean_reader配置添加另一個閱讀器。
Locator
locator如果locate標志設置為只有相關的配置true。它控制本地化過程的行為,需要針對每個具體的用例進行調整。默認設置只是在開發過程中最有效的值的組合。
只有兩個屬性與Quagga(halfSample和 patchSize)中的使用相關,而其余屬性僅用於開發和調試
{ halfSample: true, patchSize: "medium", // x-small, small, medium, large, x-large debug: { showCanvas: false, showPatches: false, showFoundPatches: false, showSkeleton: false, showLabels: false, showPatchLabels: false, showRemainingPatchLabels: false, boxFromPatches: { showTransformed: false, showTransformedBox: false, showBB: false } } }
該halfSample標志告訴定位器處理是否應該對縮小的圖像(半寬/高,四分之一像素計數)進行操作。打開 halfSample顯着減少處理時間,並且還有助於由於隱式平滑而找到條形碼圖案。在條形碼真的很小並且需要全分辨率來找到位置的情況下應該關閉它。如果需要,建議保持打開並使用更高分辨率的視頻圖像。
第二個屬性patchSize定義搜索網格的密度。該屬性接受的值的字符串x-small,small,medium,large和 x-large。的patchSize是正比於掃描條形碼的大小。如果你有很大的條形碼,可以讀取特寫,那么使用 large或x-large推薦。在條形碼遠離相機鏡頭(缺少自動對焦或小條形碼)的情況下,建議將尺寸設置為small甚至均勻x-small。對於后者,還建議您調整分辨率以找到條形碼。
ResultCollector
對結果進行篩選減少錯誤率
var resultCollector = Quagga.ResultCollector.create({ capture: true, //跟蹤生成結果圖像 capacity: 20, //存儲結果的最大數量 blacklist: [{ //不應該被記錄的code的黑名單 code: "WIWV8ETQZ1", format: "code_93" }, { code: "EH3C-%GU23RK3", format: "code_93" }, { code: "O308SIHQOXN5SA/PJ", format: "code_93" }, { code: "DG7Q$TV8JQ/EN", format: "code_93" }, { code: "VOFD1DB5A.1F6QU", format: "code_93" }, { code: "4SO64P4X8 U4YUU1T-", format: "code_93" }], filter: function(codeResult) { //過濾器,嚴格定義存出結果 returns true/false // only store results which match this constraint // e.g.: return codeResult.format === "ean_13"; return codeResult.format === "code_128_reader"; } });