iOS原生實現(xiàn)二維碼拉近放大

Work Hard, Play Hard, Live Life.

前言

生活中,我們都是使用支付寶支付,當我們再掃描一個較遠的二維碼過程中,我們會發(fā)現(xiàn),鏡頭會自動放大很容易掃到二維碼進行支付。看起來這么人性化的操作,又是什么原理,該怎么實現(xiàn)呢?掃碼現(xiàn)在很常見, 很多App基本都具備掃碼功能, 網(wǎng)上也有很多對iOS二維碼的講解, Github上也有很多事例、開源的代碼,但是發(fā)現(xiàn)APP掃碼功能上,自動拉近掃描二維碼的這波神操作,很少涉及。本文簡單介紹如何iOS原生如何實現(xiàn)掃描較小二維碼過程中拉近放大。
先看看本文效果圖:


Demo效果圖

對比支付寶掃碼放大效果圖:


支付寶

實現(xiàn)

從網(wǎng)絡技術(shù)博客、Github上,我們都能很快實現(xiàn)一個二維碼掃描功能,本文不再重復這些知識點。重點是如何拉近鏡頭和定位到二維碼判斷二維碼大小。

iOS原生掃碼

以下是iOS AVFoundation的掃碼原理圖。


原理圖

拉近鏡頭

蘋果提供了AVCaptureConnection中,videoScaleAndCropFactor:縮放裁剪系數(shù),使用該屬性,可以實現(xiàn)拉近拉遠鏡頭。

- (void)setVideoScale:(CGFloat)scale{

    //注意改變設(shè)備屬性前一定要首先調(diào)用lockForConfiguration:調(diào)用完之后使用unlockForConfiguration方法解鎖
    [_input.device lockForConfiguration:nil];
    
    //獲取放大最大倍數(shù)
    AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
    CGFloat maxScaleAndCropFactor = ([[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] videoMaxScaleAndCropFactor])/16; 
    
    if (scale > maxScaleAndCropFactor)
        scale = maxScaleAndCropFactor;
    
    CGFloat zoom = scale / videoConnection.videoScaleAndCropFactor;
    
    videoConnection.videoScaleAndCropFactor = scale;
    
    [_input.device unlockForConfiguration];
    
    CGAffineTransform transform = _videoPreView.transform;
    [CATransaction begin];
    [CATransaction setAnimationDuration:.025];
    
     _videoPreView.transform = CGAffineTransformScale(transform, zoom, zoom);
    
    [CATransaction commit];
   
} 

實現(xiàn)步驟:
1、首先調(diào)用lockForConfiguration。
2、獲取系統(tǒng)相機最大倍數(shù),根據(jù)需求自定義MAX倍數(shù)。
3、改變videoScaleAndCropFactor。
4、unlockForConfiguration方法解鎖。
5、將視圖layer層放大對應的倍數(shù)。

1、注意改變設(shè)備屬性前一定要首先調(diào)用lockForConfiguration:調(diào)用完之后使用unlockForConfiguration方法解鎖。
2、the videoScaleAndCropFactor property may be set to a value in the range of 1.0 to videoMaxScaleAndCropFactor,videoScaleAndCropFactor這個屬性取值范圍是1.0-videoMaxScaleAndCropFactor,如果你設(shè)置超出范圍會崩潰哦


二維碼定位

我們都知道,原生掃描結(jié)果AVCaptureMetadataOutputObjectsDelegate是返回了一個數(shù)組,而數(shù)組里面是一個個的AVMetadataMachineReadableCodeObject,而AVMetadataMachineReadableCodeObject中有個corners數(shù)組,記錄二維碼的坐標。查閱了官方文檔和相關(guān)資料,我們很容易聯(lián)想到,通過corners來獲取二維碼的坐標,大小形狀。

@@property corners
@abstract The points defining the (X,Y)
locations of the corners of the machine-readable code.

@discussion
The value of this property is an NSArray of
NSDictionaries, each of which has been created from a CGPoint using
CGPointCreateDictionaryRepresentation(), representing the coordinates
of the corners of the object with respect to the image in which it
resides. If the metadata originates from video, the points may be
expressed as scalar values from 0. - 1. The points in the corners
differ from the bounds rectangle in that bounds is axis-aligned to
orientation of the captured image, and the values of the corners
reside within the bounds rectangle. The points are arranged in
counter-clockwise order (clockwise if the code or image is mirrored),
starting with the top-left of the code in its canonical orientation.

#pragma mark AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    if (!bNeedScanResult) {
        return;
    }
    
    bNeedScanResult = NO;
    
    if (!_arrayResult) {
        
        self.arrayResult = [NSMutableArray arrayWithCapacity:1];
    }
    else
    {
        [_arrayResult removeAllObjects];
    }
    
    //識別掃碼類型
    for(AVMetadataObject *current in metadataObjects)
    {
        if ([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]] )
        {
            bNeedScanResult = NO;
            NSString *scannedResult = [(AVMetadataMachineReadableCodeObject *) current stringValue];
            
            if (scannedResult && ![scannedResult isEqualToString:@""])
            {
                [_arrayResult addObject:scannedResult];
            }
            //測試可以同時識別多個二維碼
        }
    }
    
    if (_arrayResult.count < 1)
    {
        bNeedScanResult = YES;
        return;
    }
    if (_isAutoVideoZoom && !bHadAutoVideoZoom) {
        
        AVMetadataMachineReadableCodeObject *obj = (AVMetadataMachineReadableCodeObject *)[self.preview transformedMetadataObjectForMetadataObject:metadataObjects.lastObject];
        [self changeVideoScale:obj];
         bNeedScanResult = YES;
         bHadAutoVideoZoom  =YES;
        return;
    }
    if (_isNeedCaputureImage)
    {
        [self captureImage];
    }
    else
    {
        [self stopScan];

        if (_blockScanResult) {
            _blockScanResult(_arrayResult);
        }
    }
}

當使用iOS原生掃碼過程中,當系統(tǒng)相機檢測到二維碼類型,回調(diào)通知我們,第一次我們可以檢測二維碼大小及其位置(如果非原生掃碼,可以通過OpenCV識別二維碼,將其定位,有待研究)。

- (void)changeVideoScale:(AVMetadataMachineReadableCodeObject *)objc
{
    NSArray *array = objc.corners;
    CGPoint point = CGPointZero;
    int index = 0;
    CFDictionaryRef dict = (__bridge CFDictionaryRef)(array[index++]);
    // 把點轉(zhuǎn)換為不可變字典
    // 把字典轉(zhuǎn)換為點,存在point里,成功返回true 其他false
    CGPointMakeWithDictionaryRepresentation(dict, &point);
    NSLog(@"X:%f -- Y:%f",point.x,point.y);
    CGPoint point2 = CGPointZero;
    CGPointMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)array[2], &point2);
    NSLog(@"X:%f -- Y:%f",point2.x,point2.y);
    CGFloat scace =150/(point2.x-point.x); //當二維碼圖片寬小于150,進行放大
    if (scace > 1) {
        //實現(xiàn)動畫效果
        for (CGFloat i= 1.0; i<=scace; i = i+0.001) {
            [self setVideoScale:i];
        }
    }
    return;
}

上代碼塊中changeVideoScale函數(shù)已將二維碼位置和寬定位出來,根據(jù)需求當相機識別的二維碼的寬少于150時,我們可以通過拉近鏡頭來實現(xiàn)放大二維碼。

源碼

上述是主要流程,完整的源碼可以通過以下方式獲取
1、 CocoaPods安裝

pod 'RHScan'

2、RHScan

小結(jié)

本文使用iOS原生掃碼實現(xiàn)如何掃碼過程拉近鏡頭放大二維碼,上述方法并無提高識別的速率,反而減慢了,如果要提高識別速度,可以從OpenCV識別二維碼定位的方向考慮。如果你有更好的方法或方案麻煩告知。

iOS 模仿微信掃描二維碼放大功能
iOS 掃描二維碼實現(xiàn)手勢拉近拉遠鏡頭
iOS 識別過程中描繪二維碼邊框
RHScan

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

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

  • 01 我爸跟老公爸是老同學,后來老公一家舉家回到老家,兩家開始了走動,我跟老公就是兩方父母牽線在一起的。 兩家住得...
    喵嗚么么閱讀 329評論 0 0
  • 插件的統(tǒng)一安裝方法為工具--插件--瀏覽安裝 接下來輸入代碼就可以了。比如夜間模式的代碼是1496166067重啟...
    鴨梨山大哎閱讀 2,217評論 1 2
  • Krita 是一個免費開源跨平臺的繪圖工具,是專門為概念藝術(shù)家,插圖作者,粗面紋理藝術(shù)家,和視覺特效行業(yè)而設(shè)計的。...
    左藍閱讀 13,968評論 1 4
  • 1. 模仿湖南兒歌《月亮粑粑》寫一段荒誕不經(jīng)然而押韻的文字(不用一韻到底,可以幾句一變化): 這次作業(yè),實在難寫,...
    73646954fc45閱讀 411評論 0 0
  • 65講 哪些習慣可以讓我們走向成功 1、冥想:可以增強記憶力 2、早起:早起不堵車!日出起床 3、儀式感:思考、寫...
    木槿花zls閱讀 105評論 0 0

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