文章目录

  • 前言
  • 扫一扫识别二维码图片
  • 长按图片识别二维码图片
  • 生成二维码图片
  • 代码完善
    • 识别二维码图片优化
  • 小结

前言

最近在做一个关于二维码的组件,已发布,现总结下。
开发的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];//    计算rectOfInterestCGFloat 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;}

无图无真相:


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: imagewithScaling: 0];//没有识别出来,判断CGImageRef对象的宽和高是否大于640,大于或等于的话进行缩放再进行扫描if(!nsyms &&CGImageGetWidth(image) >= 640 &&CGImageGetHeight(image) >= 640)// make one more attempt for close up, grainy imagesnsyms = [self scanImage: imagewithScaling: .5];NSMutableArray *syms = nil;if(nsyms) {// quality/type filteringint 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;elsequality = 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的contextUIGraphicsBeginImageContext(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:CIDetectorTypeQRCodecontext:niloptions:@{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张图片)

分析测试数据发现:
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)

iOS二维码识别/二维码生成相关推荐

  1. 微信iOS长按无法识别二维码

    真的是无力吐槽微信的坑真的多把人能呕死,做了个公众号开发一大堆的坑 希望你看完每个字 分享一下ios微信长按无法识别二维码的问题 在网上找了一大堆的处理方式说增加img 的padding.设置缩放的. ...

  2. uniapp 扫码识别(一维码、二维码)

    注:需开启扫码功能,首先要在manifest.json配置中打开APP模块配置中 Barcode(扫码).Camera&Gallery(相机和相册) 自带扫码插件:uni.scanCode(O ...

  3. 小程序实现扫码识别二维码内容

    前言 在开发程序过程中经常和二维码打交道,经常要查看二维码的内容是什么,所以决定自己开发一个可以识别二维码,生成二维码的小工具. 一.项目展示 用户可以识别生活中常见的支持条码.二维码.DataMat ...

  4. android扫码二维码识别二维码

    1. 快速集成扫码二维码,识别二维码功能.经过加工处理优化的,直接返回扫码结果字符串和图片的bitmap数据. 直接上代码: package com.xinxinchelian.myscanzxing ...

  5. WinForm调用摄像头扫码识别二维码

    前言 因公司业务需求,需要在Windows系统下调用摄像头识别二维码需求,就有了这个功能.根据网上网友提供的一些资料,自己整合应用到项目中,效果还不错(就是感觉像素不是太好).现在将调用摄像头+识别二 ...

  6. 如何使用h5-scan-qrcode插件实现一个h5页面扫码识别二维码功能

    为了适应公司代码全程使用jquery构造 如需其他js或者vue 可根据此代码去改(因为好多地方会用到这个东西所以我封装成了一个js文件) https://dragonir.github.io/h5- ...

  7. Opencv+Zbar二维码识别(一维码校正)

    一维码由一组规则排列的黑色线条.白色线条以及对应的字符组成.对倾斜的(没有严重形变)一维码的角度校正,可以根据其黑白相间.排列规则的特点,计算傅里叶频谱,通过傅里叶频谱中直线的倾斜角度计算空间域图像一 ...

  8. java 生成二维码 识别二维码

    本实例使用的是google的zxing工具 先导包: <dependency><groupId>com.google.zxing</groupId><arti ...

  9. IOS长按识别二维码失败

    IOS长按不识别二维码,出现放大图片的问题解决. CSS加入样式: touch-callout: none; -webkit-touch-callout: none; -ms-touch-callou ...

最新文章

  1. pig脚本不需要后缀名(python tempfile模块生成pig脚本临时文件,执行)
  2. [HOW TO]-VirtualBox的虚拟机通过宿主机代理上网
  3. windows10 下 vscode + cmake 编译 Qt6 代码
  4. “SqlNullValueException: Data is Null. This method or property cannot be called on Null values.”的解决方案
  5. 电脑java语言有什么用_Java语言是什么?_Java语言有什么优点
  6. ASP.NET Core 2.1:将VMD.RESTApiResponseWrapper.Core集成到REST API应用程序
  7. 我的装机软件清单-备忘
  8. foobar2000实现用手机远程控制PC命令行版
  9. 《斯坦福算法博弈论二十讲》学习笔记(持续更新)
  10. Win11预览版更新错误怎么办?Win11预览版安装失败的解决方法
  11. JavaSwing实现简单连连看小游戏
  12. 08-22 CDR数据时钟恢复电路
  13. tableau中快速实现环比增长率计算
  14. 大数据分析师岗位是青春饭
  15. 你还在用 format 格式化字符串?
  16. 【软件工程师中级职称】学习总结
  17. please select a vaild python interpret
  18. 月均数据_三季度前20强券商私募资管月均规模下降逾7000亿元 这5家主动规模占比已超50%...
  19. 易语言 不支持html5,微凉模块可穿透框架,解决网页点击不了的问题
  20. 西行漫记(3):敏捷的奥秘

热门文章

  1. 加载磊科336usb无线网卡驱动到s3c6410开发板中去
  2. 嵌入式开发,没有串口如何看日志?
  3. 详细介绍:如何用Vue完成喵喵电影项目?
  4. matlab中mag 是什么,MATLAB中显示幅频特性语句plot(f(1:N/2),mag(1:N/2)*2/N);为什么mag(1:N/2)后面要乘以2/N?...
  5. python 调用event handler_扣丁学堂Python开发之调用语音模块时报错及解决方法
  6. CREO--螺杆限位槽
  7. 您需要售后返修管理软件的N个理由
  8. igs时间和utc_UTC时间与北京时间的关系
  9. Thinkphp3.2开发阿里云短信验证码
  10. EVE-NG 连接物理网络