精华内容
下载资源
问答
  • H5扫码特效,可以做二维码识别,银行卡识别,提交给接口
  • 优先本地识别二维码,当本地识别不成功时会自动联网调用草料二维码接口识别。 优先本地识别二维码,当本地识别不成功时会自动联网调用草料二维码接口识别
  • 二维码识别zbar.zip

    2020-04-12 13:21:57
    然后又继续优化了一下,发现二值化的阈值对二维码识别非常关键,badcase通常是因为阈值不合适导致的,于是牺牲了一下性能,在识别程序中多次尝试不同阈值,最终识别效果达到了比较令人满意的结果,准确率从90%左右...
  • 目录前言扫一扫识别二维码图片长按图片识别二维码图片生成二维码图片代码完善识别二维码图片优化小结 前言 最近在做一个关于二维码的组件,已发布,现总结下。 开发的APP所需支持的最低版本为7.0,最初的方案为扫描...

    前言

    最近在做一个关于二维码的组件,已发布,现总结下。
    开发的APP所需支持的最低版本为7.0,最初的方案为扫描使用苹果自带的API实现扫一扫的功能、使用ZXing识别从相册或别人转发的二维码图片。但发现ZXing识别从相册中来的图片性能很差,很多图片识别不了,且耗时较长,遂使用ZBar来实现识别从相册或别人转发的二维码图片。
    这个组件重要有三个功能,扫一扫识别二维码图片、长按图片识别二维码图片和生成二维码图片。

    扫一扫识别二维码图片

    - (void)initCapture {
        AVCaptureDevice* inputDevice =
        [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        [inputDevice lockForConfiguration:nil];
        if ([inputDevice hasTorch]) {
            inputDevice.torchMode = AVCaptureTorchModeAuto;
        }
        [inputDevice unlockForConfiguration];
        
        AVCaptureDeviceInput *captureInput =
        [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];
        
        if (!captureInput) {
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
                UIAlertController *alterVC = [UIAlertController alertControllerWithTitle:@"系统提示" message:@"您已关闭相机使用权限,请至手机“设置->隐私->相机”中打开" preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
                [alterVC addAction:confirmAction];
                [self presentViewController:alterVC animated:YES completion:nil];
                
            } else {
                UIAlertController *alterVC = [UIAlertController alertControllerWithTitle:@"系统提示" message:@"未能找到相机设备" preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
                [alterVC addAction:confirmAction];
                [self presentViewController:alterVC animated:YES completion:nil];
            }
            return;
        }
        
        AVCaptureMetadataOutput *captureOutput = [[AVCaptureMetadataOutput alloc] init];
        [captureOutput setMetadataObjectsDelegate:self queue:_queue];
        self.captureOutput = captureOutput;
        self.captureSession = [[AVCaptureSession alloc] init];
        [self.captureSession addInput:captureInput];
        [self.captureSession addOutput:captureOutput];
        
        CGFloat w = 1920.f;
        CGFloat h = 1080.f;
        if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) {
            self.captureSession.sessionPreset = AVCaptureSessionPreset1920x1080;
        } else if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
            self.captureSession.sessionPreset = AVCaptureSessionPreset1280x720;
            w = 1280.f;
            h = 720.f;
        } else if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) {
            self.captureSession.sessionPreset = AVCaptureSessionPreset640x480;
            w = 960.f;
            h = 540.f;
        }
        captureOutput.metadataObjectTypes = [captureOutput availableMetadataObjectTypes];
        CGRect bounds = [[UIScreen mainScreen] bounds];
        
        if (!self.prevLayer) {
            self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
        }
        self.prevLayer.frame = bounds;
        self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        
        [self.view.layer insertSublayer:self.prevLayer atIndex:0];
        
    //    计算rectOfInterest
        CGFloat p1 = bounds.size.height/bounds.size.width;
        CGFloat p2 = w/h;
        
        CGRect cropRect = CGRectMake(CGRectGetMinX(_cropRect) - kQRReaderScanExpandWidth, CGRectGetMinY(_cropRect) - kQRReaderScanExpandHeight, CGRectGetWidth(_cropRect) + 2*kQRReaderScanExpandWidth, CGRectGetHeight(_cropRect) + 2*kQRReaderScanExpandHeight);
        
        if (fabs(p1 - p2) < 0.00001) {
            captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y /bounds.size.height,
                                                      cropRect.origin.x/bounds.size.width,
                                                      cropRect.size.height/bounds.size.height,
                                                      cropRect.size.width/bounds.size.width);
        } else if (p1 < p2) {
            //实际图像被截取一段高
            CGFloat fixHeight = bounds.size.width * w / h;
            CGFloat fixPadding = (fixHeight - bounds.size.height)/2;
            captureOutput.rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,
                                                      cropRect.origin.x/bounds.size.width,
                                                      cropRect.size.height/fixHeight,
                                                      cropRect.size.width/bounds.size.width);
        } else {
            CGFloat fixWidth = bounds.size.height * h / w;
            CGFloat fixPadding = (fixWidth - bounds.size.width)/2;
            captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y/bounds.size.height,
                                                      (cropRect.origin.x + fixPadding)/fixWidth,
                                                      cropRect.size.height/bounds.size.height,
                                                      cropRect.size.width/fixWidth);
        }
    }
    

    长按图片识别二维码图片

    识别图片使用的是ZBar,最初的方案为ZXing,因为ZXing有人在维护,但ZXing识别相册中的二维码图片或本地的图片,有些图片根本就识别不出来,且耗时较长,所以改为使用ZBar。在网上找到一篇文章再见ZXing 使用系统原生代码处理QRCode,实测发现在iOS9,iphone4s上传回来的数组为空。代码如下:

        //decode
        - (NSString *)decodeQRImageWith:(UIImage*)aImage {
            NSString *qrResult = nil;
            
            //iOS8及以上可以使用系统自带的识别二维码图片接口,但此api有问题,在一些机型上detector为nil。
            
            //    if (iOS8_OR_LATER) {
            //        CIContext *context = [CIContext contextWithOptions:nil];
            //        CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];
            //        CIImage *image = [CIImage imageWithCGImage:aImage.CGImage];
            //        NSArray *features = [detector featuresInImage:image];
            //        CIQRCodeFeature *feature = [features firstObject];
            //
            //        qrResult = feature.messageString;
            //    } else {
            
            ZBarReaderController* read = [ZBarReaderController new];
            CGImageRef cgImageRef = aImage.CGImage;
            ZBarSymbol* symbol = nil;
            for(symbol in [read scanImage:cgImageRef]) break;
            qrResult = symbol.data ;
            return qrResult;
        }
    

    无图无真相:

    14567CBE-E1D2-4FA7-AFA3-8B2037171F38.jpg
    detector的值为nil,也就是说

        CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];
    

    CIDetector的初始化方法无效。推测是苹果API的问题。

    生成二维码图片

    在iOS8及以上版本使用苹果的API生成二维码图片,代码如下:

    - (UIImage *)encodeQRImageWithContent:(NSString *)content size:(CGSize)size {
        UIImage *codeImage = nil;
        if (iOS8_OR_LATER) {
            NSData *stringData = [content dataUsingEncoding: NSUTF8StringEncoding];
           
            //生成
            CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
            [qrFilter setValue:stringData forKey:@"inputMessage"];
            [qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];
            
            UIColor *onColor = [UIColor blackColor];
            UIColor *offColor = [UIColor whiteColor];
            
            //上色
            CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"
                                               keysAndValues:
                                     @"inputImage",qrFilter.outputImage,
                                     @"inputColor0",[CIColor colorWithCGColor:onColor.CGColor],
                                     @"inputColor1",[CIColor colorWithCGColor:offColor.CGColor],
                                     nil];
            
            CIImage *qrImage = colorFilter.outputImage;
            CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];
            UIGraphicsBeginImageContext(size);
            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSetInterpolationQuality(context, kCGInterpolationNone);
            CGContextScaleCTM(context, 1.0, -1.0);
            CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
            codeImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            
            CGImageRelease(cgImage);
        } else {
            codeImage = [QRCodeGenerator qrImageForString:content imageSize:size.width];
        }
        return codeImage;
    }
    

    iOS8以下使用libqrencode库来生成二维码图片。

    代码完善

    2015年12月11日

    QA测试发现,服务端生成的二维码,使用ZBar识别不出来,但将这张图片保存到相册,然后发送就可以识别出来。最初的想法是要服务端修改生成的二维码,但安卓能够识别出来,此路不通,那只有看ZBar的源码了。

    - (id <NSFastEnumeration>) scanImage: (CGImageRef) image
    {
        timer_start;
        int nsyms = [self scanImage: image
                          withScaling: 0];
      //没有识别出来,判断CGImageRef对象的宽和高是否大于640,大于或等于的话进行缩放再进行扫描
        if(!nsyms &&
           CGImageGetWidth(image) >= 640 &&
           CGImageGetHeight(image) >= 640)
            // make one more attempt for close up, grainy images
            nsyms = [self scanImage: image
                          withScaling: .5];
    
        NSMutableArray *syms = nil;
        if(nsyms) {
            // quality/type filtering
            int max_quality = MIN_QUALITY;
            for(ZBarSymbol *sym in scanner.results) {
                zbar_symbol_type_t type = sym.type;
                int quality;
                if(type == ZBAR_QRCODE)
                    quality = INT_MAX;
                else
                    quality = sym.quality;
    
                if(quality < max_quality) {
                    zlog(@"    type=%d quality=%d < %d\n",
                         type, quality, max_quality);
                    continue;
                }
    
                if(max_quality < quality) {
                    max_quality = quality;
                    if(syms)
                        [syms removeAllObjects];
                }
                zlog(@"    type=%d quality=%d\n", type, quality);
                if(!syms)
                    syms = [NSMutableArray arrayWithCapacity: 1];
    
                [syms addObject: sym];
            }
        }
    
        zlog(@"read %d filtered symbols in %gs total\n",
              (!syms) ? 0 : [syms count], timer_elapsed(t_start, timer_now()));
        return(syms);
    }
    

    在这里就产生了一个解决有些二维码图片识别不出来的解决思路:将传过来的UIImage的宽和高设置为640,识别不出来再进行缩放识别。修改UIImage的代码如下:

    -(UIImage *)TransformtoSize:(CGSize)Newsize
    {
        // 创建一个bitmap的context
        UIGraphicsBeginImageContext(Newsize);
        // 绘制改变大小的图片
        [self drawInRect:CGRectMake(0, 0, Newsize.width, Newsize.height)];
        // 从当前context中创建一个改变大小后的图片
        UIImage *TransformedImg=UIGraphicsGetImageFromCurrentImageContext();
        // 使当前的context出堆栈
        UIGraphicsEndImageContext();
        // 返回新的改变大小后的图片
        return TransformedImg;
    }
    

    这样类似于ZXing中的tryHard设置为YES。识别不出来的二维码图片就可以识别了。

    2016年5月20日
    bug: 点击进入扫一扫界面,退出,再进入,这样重复5次左右,扫一扫之前的界面的会出现卡顿。
    原因:多次进入扫一扫界面,再退出,因此界面未被系统回收,captureSession对象一直在运行,会造成内存泄露,引起上一个界面卡顿。
    解决方案:在视图将要消失的时候,确保captureSession对象停止运行。

    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        if ([self.captureSession isRunning]) {
            [self.captureSession stopRunning];
        }
    }
    

    2018年4月28日

    识别二维码图片优化

    近期通过bugly收集卡顿问题发现,二维码组件在识别二维码图片时,会出现卡顿问题。为优化识别速度,采用了三种方案,并分别进行测试,并对测试数据进行分析,最终挑选出最优的方案。

    任务A:使用系统提供的CoreImage的CIDetector接口去识别二维码图片,返回对应的字符串;
    任务B:使用zbar中的方法去识别二维码图片,返回对应的字符串。

    //任务A
    + (NSString *)useSystemMethodDecodeImage:(UIImage *)image {
        NSString *resultString = nil;
        CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode
                                                  context:nil
                                                  options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];
        if (detector) {
            CIImage *ciImage = [CIImage imageWithCGImage:image.CGImage];
            NSArray *features = [detector featuresInImage:ciImage];
            CIQRCodeFeature *feature = [features firstObject];
            resultString = feature.messageString;
        }
        return resultString;
    }
    //任务B
    + (NSString *)useZbarMethodDecodeImage:(UIImage *)image {
        UIImage *decodeImage = image;
        if (decodeImage.size.width < 641) {
            decodeImage = [decodeImage TransformtoSize:CGSizeMake(640, 640)];
        }
        QRCodeZBarReaderController* read = [QRCodeZBarReaderController new];
        CGImageRef cgImageRef = decodeImage.CGImage;
        QRCodeZBarSymbol *symbol = nil;
        for(symbol in [read scanImage:cgImageRef]) break;
        return symbol.data;
    }
    
    • 方案A:先执行任务A,如果获取到的字符串为空,再执行任务B。
    + (NSString *)planOneDecodeWithImage:(UIImage *)image index:(NSInteger)index{
     
        NSMutableString *costTimeInfo = [NSMutableString stringWithFormat:@"%ld\r\n",index];
        CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
        NSString *detectorString = [MUIQRCodeDecoder useSystemMethodDecodeImage:image];
        CFAbsoluteTime detectorCostTime = (CFAbsoluteTimeGetCurrent() - startTime);
        
        [costTimeInfo appendString:[NSString stringWithFormat:@"detector : %f ms\r\n",detectorCostTime *1000.0]];
        
        NSAssert(detectorString.length > 0, @"detector fail!");
        CFAbsoluteTime zbarStartTime = CFAbsoluteTimeGetCurrent();
        NSString *zbarSymbolString = [MUIQRCodeDecoder useZbarMethodDecodeImage:image];
        NSAssert(zbarSymbolString.length > 0, @"zbar fail!");
        CFAbsoluteTime zbarCostTime = (CFAbsoluteTimeGetCurrent() - zbarStartTime);
        
        [costTimeInfo appendString:[NSString stringWithFormat:@"zbar : %f ms\r\n",zbarCostTime *1000.0]];
        
        CFAbsoluteTime totalCostTime = (CFAbsoluteTimeGetCurrent() - startTime);
        
        [costTimeInfo appendString:[NSString stringWithFormat:@"total cost : %f ms\r\n",totalCostTime *1000.0]];
        [costTimeInfo appendString:[NSString stringWithFormat:@"detectorString : %@ ms\r\n",detectorString]];
        [costTimeInfo appendString:[NSString stringWithFormat:@"zbarSymbolString : %@ ms\r\n",zbarSymbolString]];
        return [costTimeInfo copy];
    }
    
    • 方案B:同时执行任务A和任务B,两者均执行完后,返回识别的结果;
    + (NSString *)planTwoDecodeWithImage:(UIImage *)image index:(NSInteger)index { 
        __block NSMutableString *costTimeInfo = [NSMutableString stringWithFormat:@"%ld\r\n",index];
        __block NSString *detectorString = nil;
        __block NSString *zbarSymbolString = nil;
        
        CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
        
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
            detectorString = [MUIQRCodeDecoder useSystemMethodDecodeImage:image];
            NSAssert(detectorString.length > 0, @"detector fail!");
            CFAbsoluteTime costTime = (CFAbsoluteTimeGetCurrent() - startTime);
            [costTimeInfo appendString:[NSString stringWithFormat:@"detector : %f ms\r\n",costTime *1000.0]];
        });
        
        dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
            zbarSymbolString = [MUIQRCodeDecoder useZbarMethodDecodeImage:image];
            NSAssert(zbarSymbolString.length > 0, @"zbar fail!");
            CFAbsoluteTime costTime = (CFAbsoluteTimeGetCurrent() - startTime);
            [costTimeInfo appendString:[NSString stringWithFormat:@"zbar : %f ms\r\n",costTime *1000.0]];
        });
        
        dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
            dispatch_semaphore_signal(semaphore);
        });
        
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        CFAbsoluteTime totalCostTime = (CFAbsoluteTimeGetCurrent() - startTime);
        [costTimeInfo appendString:[NSString stringWithFormat:@"total cost : %f ms\r\n",totalCostTime *1000.0]];
        [costTimeInfo appendString:[NSString stringWithFormat:@"detectorString : %@ ms\r\n",detectorString]];
        [costTimeInfo appendString:[NSString stringWithFormat:@"zbarSymbolString : %@ ms\r\n",zbarSymbolString]];
        return [costTimeInfo copy];
    }
    
    • 方案C:同时执行任务A和任务B
      1、任务A先执行完且识别成功,返回识别结果;
      2、任务B先执行完且识别成功,返回识别结果;
      3、任务A和任务B均识别失败,两者均执行完后,返回识别的结果。
    + (NSString *)planThreeDecodeWithImage:(UIImage *)image index:(NSInteger)index {
        __block NSMutableString *costTimeInfo = [NSMutableString stringWithFormat:@"%ld\r\n",index];
        __block NSString *detectorString = nil;
        __block NSString *zbarSymbolString = nil;
        __block BOOL isNeedSendSignal = YES;
        
        CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
        
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
            detectorString = [MUIQRCodeDecoder useSystemMethodDecodeImage:image];
            //NSAssert(detectorString.length > 0, @"detector fail!");
            CFAbsoluteTime costTime = (CFAbsoluteTimeGetCurrent() - startTime);
            [costTimeInfo appendString:[NSString stringWithFormat:@"detector : %f ms\r\n",costTime *1000.0]];
            if (detectorString.length > 0 && isNeedSendSignal) {
                isNeedSendSignal = NO;
                dispatch_semaphore_signal(semaphore);
            }
        });
        
        dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
            zbarSymbolString = [MUIQRCodeDecoder useZbarMethodDecodeImage:image];
            //NSAssert(zbarSymbolString.length > 0, @"zbar fail!");
            CFAbsoluteTime costTime = (CFAbsoluteTimeGetCurrent() - startTime);
            [costTimeInfo appendString:[NSString stringWithFormat:@"zbar : %f ms\r\n",costTime *1000.0]];
            if (zbarSymbolString.length > 0 && isNeedSendSignal) {
                isNeedSendSignal = NO;
                dispatch_semaphore_signal(semaphore);
            }
        });
        
        dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
            if (isNeedSendSignal) {
                dispatch_semaphore_signal(semaphore);
            }
        });
        
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        CFAbsoluteTime totalCostTime = (CFAbsoluteTimeGetCurrent() - startTime);
        [costTimeInfo appendString:[NSString stringWithFormat:@"total cost : %f ms\r\n",totalCostTime *1000.0]];
        [costTimeInfo appendString:[NSString stringWithFormat:@"detectorString : %@ ms\r\n",detectorString]];
        [costTimeInfo appendString:[NSString stringWithFormat:@"zbarSymbolString : %@ ms\r\n",zbarSymbolString]]; 
        return [costTimeInfo copy];
    }
    

    测试数据如下所示:(取了前10张图片)

    识别二维码图片耗时.png

    分析测试数据发现:
    1、在测试第一张二维码图片时,总耗时均较大,如果第一次识别使用的是系统方法,耗时超过500ms,这也是为什么会出现卡顿的原因;
    2、使用系统方法去识别二维码图片时,如果不是第一次去识别,耗时较小,在65ms以内;
    3、使用zbar的方法去识别二维码图片,耗时均值在200ms以内;
    4、在方案C中,如果第一次使用系统方法,耗时为226ms。

    总结得出,从优化卡顿问题的角度出发,使用方案C最优,同时发现,如果使用系统方法能识别出二维码图片,在初始化之后(也就是第二次使用),耗时最短。同时因为在实际的使用场景中,图片是一张一张识别的,识别过程有一个间隔时间,如果已经使用系统方法识别过二维码图片,那下次识别就能达到最优。所以使用方案C的话,最差情况均值在200ms左右,最好的情况和方案A中第二次使用系统方法耗时基本一致。综合考虑,使用方案C。

    小结

    在实际的项目开发过程中,设想的情况和实际情况会存在偏差,需要自己时刻使用性能调优工具,根据数据去进行优化,而不能想当然的认为某种方式是最优的。
    源码和demo请点这里
    参考的文章链接如下
    再见ZXing 使用系统原生代码处理QRCode
    IOS二维码扫描,你需要注意的两件事
    [Zbar算法流程介绍](http://blog.csdn.net/u013738531/article/details/54574262)

    展开全文
  • 请问各位前辈,微信的wx.scanQRCode这个接口是不是只能用于扫一扫识别呢? 如果是只能用于扫一扫,那么有没有...在此之前我有用qrcode.js识别二维码以及用后来识别二维码都写过了,但是部分二维码识别不了,怎么办呢。
  • 微信二维码识别研究

    2021-10-13 09:36:02
    微信二维码识别研究 文章目录微信二维码识别研究前言一、在Win10下编译OpenCV4.5.2(含opencv_contrib)二、调试步骤1.链接OpenCV2.编写Demo3.为Demo配置环境(Debug环境)4.修改OpenCV源码三、微信二维码解码流程...

    微信二维码识别研究



    前言

    由于工作原因,需要熟悉二维码解析流程,正好微信在Opencv4.5.2中开源了wechat_qrcode源码,现对第一阶段调研做下记录。


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、在Win10下编译OpenCV4.5.2(含opencv_contrib)

    本人使用的是vs2019编译,感谢如下博文:
    win10 下编译用于 Visual Studio 2019 的 OpenCV4.5.2(含 opencv_contrib 扩展模块)附编译好的OpenCV(图文)

    二、调试步骤

    1.链接OpenCV

    编译opencv生成解决方案后,右键CMakeTargets下的INSTALL->仅用于项目->仅生成INSTALL,顺利的话,install目录如下:
    在这里插入图片描述

    2.编写Demo

    另起VS的Demo工程,代码如下(本人根据自己需要修改了opencv源码,接口增加了参数用于对比测试):

    #include <iostream>
    #include <opencv2/core.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc.hpp>
    
    #include <opencv2/wechat_qrcode.hpp>
    
    using namespace std;
    using namespace cv;
    
    int main(int argc, char* argv[])
    {
        for (size_t k = 0; k < 84; k++)
        {
            for (size_t i = 1; i < 3; i++)
            {
                string imgPath = "D:\\aaWorkspace\\WeChatQRCodeDemo\\QRCodeDemo\\qrcode_compare\\" + to_string(k) + "-" + to_string(i) + ".jpg";
                Mat img = imread(imgPath);
                if (!img.data)
                {
                    cout << "Failed to read image!" << endl;
                    continue;
                }
                string path = "D:\\aaWorkspace\\WeChatQRCodeDemo\\QRCodeDemo\\steps\\img" + to_string(k * 10 + i) + "\\0-src.jpg";
                imwrite(path, img);
    
                Ptr<wechat_qrcode::WeChatQRCode> detector;
    
                try {
                    detector = makePtr<wechat_qrcode::WeChatQRCode>(
                        "D:\\opencv-4.5.2-contrib\\opencv\\newbuild\\downloads\\wechat_qrcode\\detect.prototxt",
                        "D:\\opencv-4.5.2-contrib\\opencv\\newbuild\\downloads\\wechat_qrcode\\detect.caffemodel",
                        "D:\\opencv-4.5.2-contrib\\opencv\\newbuild\\downloads\\wechat_qrcode\\sr.prototxt",
                        "D:\\opencv-4.5.2-contrib\\opencv\\newbuild\\downloads\\wechat_qrcode\\sr.caffemodel");
                }
                catch (const std::exception& e) {
                    cout <<
                        "\n---------------------------------------------------------------\n"
                        "Failed to initialize WeChatQRCode.\n"
                        "Please, download 'detector.*' and 'sr.*' from\n"
                        "https://github.com/WeChatCV/opencv_3rdparty/tree/wechat_qrcode\n"
                        "and put them into the current directory.\n"
                        "---------------------------------------------------------------\n";
                    cout << e.what() << endl;
                    return 0;
                }
                string prevstr = "";
                vector<Mat> points;
                auto res = detector->detectAndDecode(img, points, k * 10 + i);
                int j = 0;
                for (const auto& t : res)
                {
                    cout << endl << "qrcode: " << t << endl;
                    putText(img, t, cv::Point(points[j].at<float>(0, 0), points[j].at<float>(0, 1)), FONT_HERSHEY_COMPLEX, 2, Scalar(0, 255, 0), 2);
                    j++;
                }
                for (const auto& point : points)
                {
                    rectangle(img, cv::Point(point.at<float>(0, 0), point.at<float>(0, 1)), cv::Point(point.at<float>(2, 0), point.at<float>(2, 1)), Scalar(0, 0, 255));
                }
                path = "D:\\aaWorkspace\\WeChatQRCodeDemo\\QRCodeDemo\\steps\\img" + to_string(k * 10 + i) + "\\9-result.jpg";
                imwrite(path, img);
            }
        }
        waitKey(0);
        return 0;
    }
    

    3.为Demo配置环境(Debug环境)

    Visual Studio配置第三方库的常规操作,如下:

    (1)项目右键属性->VC++目录->包含目录:

    D:\opencv-4.5.2-contrib\opencv\newbuild\install\include
    D:\opencv-4.5.2-contrib\opencv\newbuild\install\include\opencv2
    

    (2)项目右键属性->VC++目录->库目录:

    D:\opencv-4.5.2-contrib\opencv\newbuild\install\x64\vc16\lib
    

    (3)项目右键属性->链接器->输入:

    opencv_world452d.lib
    

    (4)将步骤1目录中生成的opencv_world452d.dll(\install\x64\vc16\bin)放置到demo.exe同级

    (5)在opencv工程的INSTALL项目右键属性->调试->命令,输入demo.exe位置:

    D:\aaWorkspace\WeChatQRCodeDemo\QRCodeDemo\x64\Debug\demo.exe
    

    然后就可以断点调试opencv中相关源码了

    4.修改OpenCV源码

    比如我们需要保存检测的二维码的候选区域图片,添加如下代码:
    在这里插入图片描述

    (1)修改之后保存文件,对opencv工程右键->生成解决方案,注意不要点击重新生成解决方案
    (2)CMakeTargets下的INSTALL右键->仅用于项目->仅生成INSTALL,重新生成opencv_world452d.dll,替换demo.exe同级目录下文件


    三、微信二维码解码流程,浅见

    1.二维码定位

    try {
            detector = makePtr<wechat_qrcode::WeChatQRCode>(
               "D:\\opencv-4.5.2-contrib\\opencv\\newbuild\\downloads\\wechat_qrcode\\detect.prototxt",
               "D:\\opencv-4.5.2-contrib\\opencv\\newbuild\\downloads\\wechat_qrcode\\detect.caffemodel",
               "D:\\opencv-4.5.2-contrib\\opencv\\newbuild\\downloads\\wechat_qrcode\\sr.prototxt",
               "D:\\opencv-4.5.2-contrib\\opencv\\newbuild\\downloads\\wechat_qrcode\\sr.caffemodel");
        }
    
    int WeChatQRCode::Impl::applyDetector(const Mat& img, vector<Mat>& points) {
        int img_w = img.cols;
        int img_h = img.rows;
    
        // hard code input size
        int minInputSize = 400;
        float resizeRatio = sqrt(img_w * img_h * 1.0 / (minInputSize * minInputSize));
        int detect_width = img_w / resizeRatio;
        int detect_height = img_h / resizeRatio;
    
        points = detector_->forward(img, detect_width, detect_height);
    
        return 0;
    }
    

    微信使用训练好的深度学习的SSD目标检测模型推理出二维码矩形候选区域,又快又准,模型也很小

    2.二维码解码

    (1)解码前对候选区域做padding,宽高扩大10%

    Mat WeChatQRCode::Impl::cropObj(const Mat& img, const Mat& point, Align& aligner) {
        // make some padding to boost the qrcode details recall.
        float padding_w = 0.1f, padding_h = 0.1f;
        auto min_padding = 15;
        auto cropped = aligner.crop(img, point, padding_w, padding_h, min_padding);
        return cropped;
    }
    

    (2)缩放尺寸,多次尝试

    // empirical rules
    vector<float> WeChatQRCode::Impl::getScaleList(const int width, const int height) {
        if (width < 320 || height < 320) return {1.0, 2.0, 0.5};
        if (width < 640 && height < 640) return {1.0, 0.5};
        return {0.5, 1.0};
        //yqg
        //return { 1.0, 2.0, 0.5 };
    }
    

    (3)在ZXing的基础上扩展,采用4种二值化方式轮流尝试解码

    enum BINARIZER {
            Hybrid = 0,
            FastWindow = 1,
            SimpleAdaptive = 2,
            AdaptiveThreshold = 3
        };
    
    // Four Binarizers
        int tryBinarizeTime = 4;
        for (int tb = 0; tb < tryBinarizeTime; tb++) {
            if (source == NULL || height * width > source->getMaxSize()) {
                source = ImgSource::create(scaled_img_zx.data(), width, height);
            } else {
                source->reset(scaled_img_zx.data(), width, height);
            }
            int ret = TryDecode(source, zx_result, scaled);
            if (!ret) {
                result = zx_result->getText()->getText();
                return ret;
            }
            else//yqg
            {
                string scaledPath = "D:\\aaWorkspace\\WeChatQRCodeDemo\\QRCodeDemo\\steps\\img" + to_string(index) + "\\5-" + to_string(qr) + "-scaled-" + to_string(scaled) + "-try-Binarize-" + to_string(tb) + "-failed.jpg";
                imwrite(scaledPath, src);
            }
            // try different binarizers
            binarizer_mgr_.SwitchBinarizer();
        }
    }
    

    四种二值化器下显示效果:
    在这里插入图片描述

    (4)得到合适的二值化图片后开始解码,寻找三个定位点,透视变换等,又要忙别的了,抽空再看吧。。。

    展开全文
  • 树莓派python实现二维码识别——ZBar

    千次阅读 多人点赞 2019-05-15 21:56:26
    在本文中,采用树莓派进行二维码识别,支持中英文的二维码或者一维条码的识别。硬件由树莓派3Bplus和usb摄像头组成,软件由python、二维码识别开源工具zbar和opencv组成。通过本文,可以学习如何正确快速安装zbar及...

    树莓派二维码识别

    最近一直忙于科研,好久没有更新博客了。今天更新一篇关于使用树莓派进行二维码识别的文章,是笔者树莓派项目开发的第四篇博客,希望能够给大家带来一丝的帮助。
    现在二维码活跃在我们身边的大街小巷,基本上每天都会和二维码打交道,共享单车啊,移动支付等。那么如何实现二维码的识别呢,其实我们仔细观察二维码的特征的话,可能会看出一些特征,每一个QR码,都有三个定位块。识别二维码时会先找到定位块,然后开始读取二维码的的编码信息,然后遵循一定的规则对二维码的编码信息进行解码(翻译),解码出的内容就是我们想要的内容了,可以跳转网站,查看文字信息等。二维码识别的原理基于以上的过程,当然现在也有很多开源的二维码识别工具,如zbar和zxing。

    1、开发环境搭建

    硬件:树莓派3B plus 和 usb摄像头
    软件: python2.7版本、二维码识别开源工具ZBar和opencv(opencv的安装可参考我的博客)

    zbar 官网 http://zbar.sourceforge.net/

    ZBar是一个开源软件套件,用于从各种来源读取条形码,例如视频流,图像文件和原始强度传感器。 它支持许多流行的符号(条形码类型),包括EAN-13 / UPC-A,UPC-E,EAN-8,
    Code 128,Code 39,Interleaved 2 of 5和QR Code。灵活的分层实现方便了任何应用程序的条形码扫描和解码,可轻松地将条形码扫描小部件集成到您的Qt,GTK +或PyGTK GUI应用程序中,具备python,C++等多种语言API接口。广泛应用于零售、自动文档处理、库存跟踪、移动应用等领域。ZBar的特性如下:

    • 跨平台 - Linux / Unix,Windows,iPhone®,嵌入式
    • 高速 - 从视频流中实时扫描
    • 内存占用少
    • 小代码大小 - 核心扫描器和EAN解码器代表1K行的C代码
    • 没有浮点运算
    • 适用于使用廉价处理器/硬件的嵌入式应用
    • 模块化组件可以一起使用或单独使用

    zbar 安装

    方案一

    命令行安装:sudo apt-get install python-zbar
    直接安装,识别英文一点问题都没有,识别中文不支持。
    zbar命令行安装
    测试安装成功,进入python 环境: import zbar
    测试安装成功

    方案二

    源码安装,可识别中文
    1、wget命令用来从指定的URL下载zbar源码,命令如下:

    wget  http://downloads.sourceforge.net/project/zbar/zbar/0.10/zbar-0.10.tar.gz
    

    下载不成功的话,先用电脑下载zbar-0.10.tar.gz,上传到树莓派的pi目录下
    2、解压zbar的源文件,解压至pi目录下的zbar-0.10文件夹

    tar -zvxf  zbar-0.10.tar.gz 
    

    3、zbar是基于C语言开发的,安装编译时需要编译器,安装python-gtk和libqt4-dev

    sudo apt-get install python-gtk2-dev 
    

    4、安装libqt4-dev

    sudo apt-get install libqt4-dev
    

    5、进入zbar-0.10文件夹,运行configure 命令如下,此步运行成功生成makefile

    ./configure --without-imagemagick -disable-video  -without-qt  -without-gtk  -without-x
    

    生成makefile
    6、 编译makefile : make
    make
    7、 make安装: sudo make install
    install
    8、 测试进入python环境:import zbar
    test
    注意:第5步安装时要进入/home/pi/zbar-0.10目录,第6、7步安装时可能会出现错误,但是并不影响使用。

    zbar 中文支持修改

    ZBar是日本人写的,若要识别带有中文文字的二维码,需要在安装的时候加个小插曲,需要修改一下ZBar源文件里面的函数:修改源文件下zbar-0.10/zbar/qrcode/qrdectxt.c
    终端使用nano或者vim编辑器修改zbar-0.10/zbar/qrcode/qrdectxt.c函数,以下该步骤需要在下载完源码后进行,修改完成后再进行编译和安装。
    1、打开qrdectxt.c,采用nano编辑器
    open
    2、找到默认编码的函数,修改编码,将 ISO8859-1,换成 GB18030 将SJIS,换成GB2312
    code
    3、找到默认编码定义的list,修改解码编码顺序
    list
    4、编译源码,安装ZBar
    按照以上的步骤安装基本不会出现问题,如果出现问题仔细检查是否缺少相应的依赖安装即可。

    2、二维码识别实践

    ZBar可以直接对输入的图像提取二维码、扫码和解码,下面是笔者根据zbar的帮助文档改写的一个快速实现二维码识别的Demo,可实现对实施视频流中的二维码或者一维条码的识别,当二维码或者一维码的排放位置相对摄像头比较正时识别效果较好。

    #-*- coding: UTF-8 -*-   
    # Simple QR code recognition
    # @author: zdl
    
    # import the necessary packages
    #import simple_barcode_detection
    import cv2
    import numpy as np
    import zbar
    from PIL import Image
    
    # create a reader
    scanner = zbar.ImageScanner()
    # configure the reader
    scanner.parse_config('enable')
    font=cv2.FONT_HERSHEY_SIMPLEX
    camera=cv2.VideoCapture(0)
    
    while(True):
        # Capture frame-by-frame
        grabbed, frame = camera.read()
        if not grabbed:
            break
        pil= Image.fromarray(frame).convert('L') # 转成灰度图像
        width, height = pil.size
        raw = pil.tobytes()
        zarimage = zbar.Image(width, height, 'Y800', raw)
        scanner.scan(zarimage)
        for symbol in zarimage:  
        # do something useful with results 
            if not symbol.count: 
                print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data 
            cv2.putText(frame,symbol.data,(20,100),font,1,(0,255,0),4)
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
    

    但是为提高扫码和解码的效率,我们先使用图像处理算法实现对二维码的定位并提取二维码的图像,将该部分的图像送入ZBar的扫码器中。如何实现对二维码的定位呢,方法如下:

    • 基于梯度算子,水平垂直交叉定位
    • 角点检测,仿射变换法,可校正倾斜的二维码
    • 轮廓法,寻找最小外接矩形。
    • 轮廓层析结构法,寻找二维码的三个定位点,可校正二维码。
      我们采用第三种方法实现静态二维码的提取,实现二维码的识别。具体实现的步骤如下:
    1. 输入图像进行灰度化,滤波
    2. 图像进行Otsu自适应二值化。
    3. 二值化的图像进行图像形态学操作,实现细小连通区域的闭合。
    4. 图像位运算进行反色,这时二维码区域为白色。
    5. 寻找反色图像中的轮廓,二维码区域为轮廓中面积最大的那个,实现对二维码区域 的定位。
    6. 将定位的二维码图像取出,输入至zbar进行扫码和解码。
      源代码如下:
    # -*- coding: UTF-8 -*-
    # Simple QR code detection
    # @author: zdl
    # ZBar+python2.7.13
    
    import cv2
    import numpy as np
    import zbar
    
    # 基于轮廓定位QR位置
    def find_code(img):
        # 高斯滤波
        blur = cv2.GaussianBlur(img,(5,5),0)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # 二值化
        ret,th = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
        # 形态学操作
        mask=cv2.erode(th,None,iterations=4)
        mask=cv2.dilate(mask,None,iterations=4)
    	# 图像反色
        cv2.bitwise_not(mask, mask)
        # 寻找轮廓
        _,contours,hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    	# 寻找QR码的位置
        if len(contours)>0:
            cnt = max(contours, key=cv2.contourArea)
            x,y,w,h = cv2.boundingRect(cnt)
            img = cv2.rectangle(img,(x-15,y-15),(x+w+15,y+h+15),(0,255,0),3)
    		
            img_ROI = img[y-15:y+h+15, x-15:x+w+15]
         
        else:
            img_ROI = img
    
        return img_ROI
    
    # main函数
    if __name__ == '__main__':
    	
    	# 读入图片
        img = cv2.imread('introduce.jpg', 1)
    	# 定位QR码的位置
        img_ROI = find_code(img)
    	
    	# 初始化scanner
        scanner = zbar.ImageScanner()
        scanner.parse_config('enable')
    	
        font = cv2.FONT_HERSHEY_SIMPLEX # openCV 字体
        
        img_ROI_gray = cv2.cvtColor(img_ROI, cv2.COLOR_BGR2GRAY)
    	# 扫码
        width, height = img_ROI_gray.shape  # 获取图片大小
        raw = img_ROI_gray.tobytes()        # 图像矩阵数据转为字节数据
        zarimage = zbar.Image(width, height, 'Y800', raw) # 设置参数
        scanner.scan(zarimage)   # 扫码
    	# 解码
        for symbol in zarimage:  
        # do something useful with results 
            if not symbol.count:
                print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data
            else:
                print 'no'
            #cv2.putText(img,symbol.data,(20,100),font,1,(0,255,0),4) # 打印字符在图片上
    	# DisPlay
        cv2.imshow('img_ROI', img_ROI_gray)
        cv2.imshow('image', img)
        cv2.waitKey(0)
    
    

    运行效果:
    running result
    基于本文,我们已经实现了二维码的识别,那么结合树莓派语音合成和树莓派控制方面的知识,是不是可以做点好玩的事情呢。

    展开全文
  • WP二维码识别

    千次阅读 2013-05-16 16:34:04
    这里我们使用开源的图像识别库Zxing lib的silverlight/WP7版本来做二维码图像的识别。基本原理为:每隔一定时间从摄像头的视频流截取一张图片,获取其亮度信息,由于二维码只有黑白两色,所以只从亮度信息就可以获取...

    Windows phone SDK 从7.5版本(即mango)开始有提供访问手机摄像头的接口。这里我们使用开源的图像识别库Zxing lib的silverlight/WP7版本来做二维码图像的识别。基本原理为:每隔一定时间从摄像头的视频流截取一张图片,获取其亮度信息,由于二维码只有黑白两色,所以只从亮度信息就可以获取图片里的信息。下面介绍下具体方法:

    具体过程可以参考:http://jonas.follesoe.no/2011/07/22/qr-code-scanning-on-windows-phone-75-using-zxlib/

      (1)扫描界面的XAML代码包括三个主要组件。Rectangle 组件用来作为视频流的取景器,通过VideoBrush可以自定义视频流为各种XAML元素。使用CompositeTransform来对摄像头的选择自适应地旋转VideoBrush。

    (2)在Properties/WMAppManifest.xml文件中的节点下添加,使应用程序有访问摄像头的权限。
    (3)在后台代码的构造函数里添加定时器DispatcherTimer,每250毫秒执行一次。在每次时钟滴答(tick)时刻去获取视频流缓存区的图片亮度信息并解析。
    private readonly DispatcherTimer_timer;//定时器
    private PhotoCameraLuminanceSource _luminance;//存储图片亮度信息
    private QRCodeReader _reader;//二维码解析器对象
    private PhotoCamera _photoCamera;//摄像头对象

    public MainPage()
    {
    InitializeComponent();
    /*初始化定时器对象,每250毫秒调用ScanPreviewBuffer*/
    _timer = new DispatcherTimer();
    _timer.Interval = TimeSpan.FromMilliseconds(250);
    _timer.Tick += (o, arg) => ScanPreviewBuffer();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    /*初始化摄像头对象*/
    _photoCamera = new PhotoCamera();
    _photoCamera.Initialized += OnPhotoCameraInitialized;

    /*将XAML的VideoBrush的源设置为摄像头*/
    _previewVideo.SetSource(_photoCamera);

    base.OnNavigatedTo(e);
    }
    /*做初始化摄像头的工作*/
    Private void OnPhotoCameraInitialized(object sender, CameraOperationCompletedEventArgs e)
    {
    int width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
    int height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);

    _luminance = new PhotoCameraLuminanceSource(width, height);
    _reader = new QRCodeReader();

    Dispatcher.BeginInvoke(() => {
    _previewTransform.Rotation = _photoCamera.Orientation;
    _timer.Start();
    });
    }

    /*负责从摄像头的图片缓存区获取图片亮度信息,构造为BinaryBitmap对象,使用QRCodeReader对其尝试进行解析,若解析成功则调用DisplayResult方法做后续处理*/
    Private void ScanPreviewBuffer()
    {
    /*QRCodeReader 如果无法解析图片(即图片中没有二维码)会抛出异常,所以这里添加对异常的捕获*/
    try
    {
    _photoCamera.GetPreviewBufferY(_luminance.PreviewBufferY);
    var binarizer = new HybridBinarizer(_luminance);
    var binBitmap = new BinaryBitmap(binarizer);
    var result = _reader.decode(binBitmap);
    Dispatcher.BeginInvoke(() => DisplayResult(result.Text));
    }
    catch
    {
    }
    }

    Private void DisplayResult(stringtext)
    {
    /*stringtext为解析二维码后的信息*/
    Do something…
    }

    (4)用于获取图片亮度信息的类PhotoCameraLuminanceSource,由于PhotoCamera对象会提供图片的亮度信息,所以在这个列里面只需要一个属性和一个方法:Matrix属性存储图片的亮度信息,getRow方法获取指定行的亮度信息
    publicclassPhotoCameraLuminanceSource:LuminanceSource
    {
    public byte[] PreviewBufferY { get; private set; }

    public PhotoCameraLuminanceSource(int width, int height) : base(width, height)
    {
    PreviewBufferY = new byte[width * height];
    }

    public override sbyte[] Matrix
    {
    get { return (sbyte[])(Array)PreviewBufferY; }
    }

    public override sbyte[] getRow(int y, sbyte[] row)
    {
    if (row == null || row.Length < Width)
    {
    row = new sbyte[Width];
    }

    for (int i = 0; i < Height; i++)
    row[i] = (sbyte)PreviewBufferY[i * Width + y];

    return row;
    }
    }

    展开全文
  • 基于多二维码识别的三维运动真值获取1.背景介绍2.原理2.1图像预处理2.2 定位标轮廓提取2.3 多二维码鲁棒识别3 运行结果3.1对单张图片进行多二维码识别3.2 获取一系列图片的轨迹 1.背景介绍 使用视觉slam...
  • 二维码识别 基于stm32 ov7725

    万次阅读 多人点赞 2018-02-03 16:13:46
    二维码识别 基于stm32 ov7725 二维码识别技术在我们的生活中应用的很方便了,但基本都是基于手机的,目前在公交车上也存在了扫描二维码的机器,上次坏了之后,发现一只小企鹅,原来是基于linux的,这里介绍一下基于...
  • scan 关于二维码识别 ,二维码图片生成 做了Android6.0权限适配 单例模式调用,链式编程,可用接口回调,也可用注解回调
  • 前面,我们已经介绍了两种集成 wechat_qrcode 微信二维码识别能力的做法: 完整编译 OpenCV 和 OpenCV Contrib Native C++ 单独集成 wechat_qrcode 模块 这两种方式的预览和识别均是基于 OpenCV 提供的 JavaCamera...
  • 利用OpenCV处理图像的优势,结合ZBar提高二维码识别结果。 接口定义: #include <vector> #include <algorithm> #include <string> #include <math.h> #include <iostream> #...
  • 分享腾讯官方二维码生成接口地址 接口抓包来自腾讯QQ群的二维码生成接口,非常稳定,可以长期使用!除非腾讯不做了!! https://qun.qq.com/qrcode/index?data=
  • qt在window实现二维码识别

    千次阅读 2019-04-11 09:05:02
    最近在研究二维码识别,看了很多博客,学到了许多,这里就不一一发出链接了CSDN中一搜一堆,我第一次用手机发博,不太会用,就简单发个近两天研究总结,虽然两天就搞出来了,但是感觉水分很大。直接上代码和视频效果...
  • 最近项目中用到二维码图片识别,在python下二维码识别,目前主要有三个模块:zbar 、zbarlight、zxing。 1、三个模块的用法: #-*-coding=utf-8-*- import os import logging import zbar from PIL import...
  • 好用的二维码API接口

    2020-10-29 14:22:48
    https 二维码生成 api (如果二维码不显示,说明接口已失效) 1、搜狐视频提供的二维码 api,已稳定五年以上。...2、网易 lofter 二维码 api 接口,已稳定五年以上。https://www.lofter.com/gen...
  • 主要介绍了微信小程序实现获取小程序码和二维码java接口开发,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Android二维码识别与生成

    千次阅读 2016-08-12 15:46:27
    最近几年二维码是越来越火了,特别是随着移动端的便利性,走到哪里都是扫一扫。二维码支付、二维码扫描登录、二维码扫描关注加好友.....越来越多的应用也都加上了二维码扫描的功能,作为移动开发者,对这些新奇的...
  • 二维码API接口

    2019-02-26 17:17:00
    1.http://pan.baidu.com/share/qrcode?w=150&h=150&url=http://www.54admin.net 2.http://b.bshare.cn/barCode?site=weixin&url=http://www.54admin.net 3.http://s.jiathis.com/qrcode.php?url=ht...
  • VC++ OpenCV+ZBar提高二维码识别

    千次阅读 2019-12-23 23:32:33
    基于ZBar做二维码识别,识别率很低,为了提高识别率,可以先将图像进行灰度化处理再进行识别,准确率将会有很大提升。 #include <vector> #include <algorithm> #include <string> #include <...
  • 二维码识别之Android完整编译Zbar2017年05月11日 16:41:43阅读数:74878版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com大概刚做Android开发的时候就做过二维码扫描,那时候懂的东西少,就...
  • 二维码识别(Zxing)

    千次阅读 2016-09-18 19:38:33
    二维码因其可以在一个几何图上可以包含不同编码的大信息量数据, 低成本, 易制作等优点, 导致现在二维码的使用可谓是遍布大街小巷; 而手机上的使用也是非常的广泛, 电商类、 金融类等各种app都能看到二维码的...
  • 百度AI攻略:二维码识别

    千次阅读 2019-12-31 08:27:23
    对图片中的二维码、条形码进行检测和识别,返回存储的文字信息,获取相应信息,可应用于商品、药品出入库管理及货物运输管理等场景,轻松一扫即可快速完成对物品信息的读取、登记和存储,大幅度简化物品管理流程。...
  • 微信二维码登陆与第三方访问资源解决方案OAthor2.0
  • 微信小程序 获取小程序码和二维码java接口开发

    万次阅读 多人点赞 2017-08-30 11:35:07
    前言:目前小程序推出了自己的识别码,小程序码,这个圆形的码看起来比二维码好看。本文总结微信小程序的获取小程序码和二维码并生成二维码图片的接口开发。主要内容摘抄自微信小程序的API文档,java接口开发是自己...
  • Linux zbar二维码识别库编译

    千次阅读 2020-05-08 19:51:28
    灵活的分层实现可简化任何应用程序的条形码扫描和解码:将其与包含的GUI和命令行程序一起单独使用,轻松将条形码扫描小部件集成到Qt,GTK+或PyGTK GUI应用程序中,脚本或编程接口(Python,Perl,C ++)…一直.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,686
精华内容 7,074
关键字:

二维码识别接口