iOS 原生二維碼掃描優(yōu)化

1. 圖片很小的二維碼

以前測試提了一個bug,說有二維碼掃不了,拿到二維碼一看,是個很小的二維碼,邊長不到1cm,于是就修改了 sessionPreset 為 1080p 的,當時用的是ZXing, 當把圖片質(zhì)量改清楚時,也造成了性能的下降,基本打開掃描界面就會報memoryWarning,但是也確實解決了小二維碼掃描的問題。

AVCaptureSession 可以設(shè)置 sessionPreset 屬性,這個決定了視頻輸入每一幀圖像質(zhì)量的大小。

AVCaptureSessionPreset320x240
AVCaptureSessionPreset352x288
AVCaptureSessionPreset640x480
AVCaptureSessionPreset960x540
AVCaptureSessionPreset1280x720
AVCaptureSessionPreset1920x1080

以上列舉了部分的屬性值,分別代表輸入圖片質(zhì)量大小,一般來說AVCaptureSessionPreset640x480就夠使用,但是如果要保證較小的二維碼圖片能快速掃描,最好設(shè)置高些,如AVCaptureSessionPreset1920x1080(就是我們常說的1080p).

2. scanCrop

另一個提升掃描速度和性能的就是設(shè)置解析的范圍,在zbar和zxing中就是scanCrop, AVFoundation中設(shè)置 AVCaptureMetadataOutput 的 rectOfInterest 屬性來配置解析范圍。

最開始我按照文檔說的按照比例值來設(shè)置這個屬性,如下:

CGSize size = self.view.bounds.size;
CGRect cropRect = CGRectMake(40, 100, 240, 240);
captureOutput.rectOfInterest = CGRectMake(cropRect.origin.x/size.width,
                                     cropRect.origin.y/size.height,
                                     cropRect.size.width/size.width,
                                     cropRect.size.height/size.height);

但是發(fā)現(xiàn), Ops, 好像不對啊,掃不到了,明顯不正確呢,于是猜想: AVCapture輸出的圖片大小都是橫著的,而iPhone的屏幕是豎著的,那么我把它旋轉(zhuǎn)90°呢:

CGSize size = self.view.bounds.size;
CGRect cropRect = CGRectMake(40, 100, 240, 240);
captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,
                                     cropRect.origin.x/size.width,
                                     cropRect.size.height/size.height,
                                     cropRect.size.width/size.width);

OK,貌似對了,在iPhone5上一切工作良好,但是在4s上,或者換了sessionPreset的大小之后,這個框貌似就不那么準確了, 可能發(fā)現(xiàn)超出框上下一些也是可以掃描出來的。 再次猜想: 圖片的長寬比和手機屏幕不是一樣的,這個rectOfInterest是相對于圖片大小的比例。比如iPhone4s屏幕大小是 640x960, 而圖片輸出大小是 1920x1080. 實際的情況可能就是下圖中的效果:

1419476288149730.png

上圖中下面的代表iPhone4s屏幕,大小640x960, 上面代表AVCaptureVideoPreviewLayer中預(yù)覽到的圖片位置,在圖片輸入為1920x1080大小時,實際大小上下會被截取一點的,因為我們AVCaptureVideoPreviewLayer設(shè)置的videoGravity是AVLayerVideoGravityResizeAspectFill, 類似于UIView的UIViewContentModeScaleAspectFill效果。

于是我對大小做了一下修正:

CGSize size = self.view.bounds.size;
CGRect cropRect = CGRectMake(40, 100, 240, 240);
CGFloat p1 = size.height/size.width;
CGFloat p2 = 1920./1080.;  //使用了1080p的圖像輸出
if (p1 < p2) {
  CGFloat fixHeight = bounds.size.width * 1920. / 1080.;
  CGFloat fixPadding = (fixHeight - size.height)/2;
  captureOutput.rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,
                                          cropRect.origin.x/size.width,
                                          cropRect.size.height/fixHeight,
                                          cropRect.size.width/size.width);
} else {
    CGFloat fixWidth = bounds.size.height * 1080. / 1920.;
    CGFloat fixPadding = (fixWidth - size.width)/2;
    captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,
                                          (cropRect.origin.x + fixPadding)/fixWidth,
                                          cropRect.size.height/size.height,
                                          cropRect.size.width/fixWidth);
}

經(jīng)過上面的驗證,證實了猜想rectOfInterest是基于圖像的大小裁剪的。

3. 小結(jié)

scanCrop對于掃描來說是比較重要的,試想圖片截小點來解析是不是理論上就會更快了呢。網(wǎng)絡(luò)上貌似很難搜到關(guān)于scanCrop的詳解,希望對看到的人有幫助。
(via:劉坤的技術(shù)博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在 iOS7 以前,在iOS中實現(xiàn)二維碼和條形碼掃描,我們所知的有,兩大開源組件ZBar與ZXing. 這兩大組件...
    野豬哥123閱讀 1,669評論 0 2
  • 在iOS7之前,二維碼掃描只能用第三庫(ZBar、ZXing),我的項目中只用到過ZXing,他們的優(yōu)劣大家自行百...
    小酒窩_David閱讀 1,050評論 0 8
  • 關(guān)于二維碼(或者條形碼,以下歸類簡稱二維碼)掃描和生成的,我相信網(wǎng)絡(luò)上相關(guān)的文章層數(shù)不窮,但是,大部分都是直接粘貼...
    FR_Zhang閱讀 6,954評論 10 42
  • 一、前言 最近在做一個關(guān)于掃描二維碼簽到的小東西,所以還是上來寫一篇關(guān)于二維碼的文章,網(wǎng)上也有一些掃描二維碼的框架...
    kim逸云閱讀 4,684評論 2 8
  • 我們各自有各自的命運,誰也拯救不了誰,而我接受我的命運。生活就是這樣,實在覺得痛苦人還是應(yīng)該去相信些什么的,信個善...
    懶追隨閱讀 453評論 0 1

友情鏈接更多精彩內(nèi)容