我知道您可以使用AVFoundation设备的相机扫描QR码.现在问题来了,我怎样才能从静态UIImage对象中做到这一点?
Nei*_*msz 10
iOS API提供CoreImage框架中的CIDetector类.CIDetector可让您在图像中找到特定的图案,如面部,微笑,眼睛,或者在我们的案例中:QRCodes.
以下是在Objective-C中从UIImage检测QRCode的代码:
-(NSArray *)detectQRCode:(UIImage *) image
{
@autoreleasepool {
NSLog(@"%@ :: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
NSCAssert(image != nil, @"**Assertion Error** detectQRCode : image is nil");
CIImage* ciImage = UIImage.CIImage; // assuming underlying data is a CIImage
//CIImage* ciImage = [CIImage initWithCGImage: UIImage.CGImage]; // to use if the underlying data is a CGImage
NSDictionary* options;
CIContext* context = [CIContext context];
options = @{ CIDetectorAccuracy : CIDetectorAccuracyHigh }; // Slow but thorough
//options = @{ CIDetectorAccuracy : CIDetectorAccuracyLow}; // Fast but superficial
CIDetector* qrDetector = [CIDetector detectorOfType:CIDetectorTypeQRCode
context:context
options:options];
if ([[ciImage properties] valueForKey:(NSString*) kCGImagePropertyOrientation] == nil) {
options = @{ CIDetectorImageOrientation : @1};
} else {
options = @{ CIDetectorImageOrientation : [[ciImage properties] valueForKey:(NSString*) kCGImagePropertyOrientation]};
}
NSArray * features = [qrDetector featuresInImage:ciImage
options:options];
return features;
}
}
Run Code Online (Sandbox Code Playgroud)
如果存在并检测到QRCode,则返回的内容NSArray*将包含CIFeature*.如果没有QRCode,那NSArray*将是nil.如果QRCode解码失败,则NSArray*没有元素.
要获取编码的字符串:
if (features != nil && features.count > 0) {
for (CIQRCodeFeature* qrFeature in features) {
NSLog(@"QRFeature.messageString : %@ ", qrFeature.messageString);
}
}
Run Code Online (Sandbox Code Playgroud)
在@ Duncan-C的答案中,您可以提取QRCode角并在图像上绘制QRCode的封闭边界框.
注意:
在iOS10.0 beta 6下,[qrDetector featuresInImage:ciImage options:options]使用来自cameraSampleBuffer的图像时的调用会记录此内部警告(它运行顺利,但是使用此消息向控制台发送垃圾邮件,我现在找不到摆脱它的方法) :
锁定计数为1时,最终确定CVPixelBuffer 0x170133e20.
资源 :
芯的图像具有CIDetector类,与CIDetectorTypeQRCode用于检测QR码.您可以为静止图像或视频提供Core Image滤镜.
那应该满足你的需求.有关详细信息,请参阅Xcode文档.
来自ShinobiControls的每天iOS8的Github回购包括一个LiveDetection项目,该项目展示了如何从视频源和静止图像中使用CIDetectorTypeQRCode.看起来它还没有针对Swift 2.0进行更新,我无法在Xcode 7.2.1下进行编译,但performQRCodeDetection项目中的函数已经编译完成.(编译问题是使用代码处理CVPixelBuffersSwift中必须处理的所有可怕的类型转换,如果您想要做的只是在静态图像中找到QRCodes,这无关紧要.)
这是该网站的关键方法(在Swift中)
func performQRCodeDetection(image: CIImage) -> (outImage: CIImage?, decode: String) {
var resultImage: CIImage?
var decode = ""
if let detector = detector {
let features = detector.featuresInImage(image)
for feature in features as! [CIQRCodeFeature] {
resultImage = drawHighlightOverlayForPoints(image,
topLeft: feature.topLeft,
topRight: feature.topRight,
bottomLeft: feature.bottomLeft,
bottomRight: feature.bottomRight)
decode = feature.messageString
}
}
return (resultImage, decode)
}
Run Code Online (Sandbox Code Playgroud)
关于返回测试消息,这里的答案都不是非常简单的。做了一个对我来说很好用的小扩展:
https://gist.github.com/freak4pc/3f7ae2801dd8b7a068daa957463ac645
extension UIImage {
func parseQR() -> [String] {
guard let image = CIImage(image: self) else {
return []
}
let detector = CIDetector(ofType: CIDetectorTypeQRCode,
context: nil,
options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
let features = detector?.features(in: image) ?? []
return features.compactMap { feature in
return (feature as? CIQRCodeFeature)?.messageString
}
}
}
Run Code Online (Sandbox Code Playgroud)
@Neimsz的答案的 Swift 4版本
func detectQRCode(_ image: UIImage?) -> [CIFeature]? {
if let image = image, let ciImage = CIImage.init(image: image){
var options: [String: Any]
let context = CIContext()
options = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
let qrDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: options)
if ciImage.properties.keys.contains((kCGImagePropertyOrientation as String)){
options = [CIDetectorImageOrientation: ciImage.properties[(kCGImagePropertyOrientation as String)] ?? 1]
}else {
options = [CIDetectorImageOrientation: 1]
}
let features = qrDetector?.features(in: ciImage, options: options)
return features
}
return nil
}
Run Code Online (Sandbox Code Playgroud)
如何使用
if let features = detectQRCode(#imageLiteral(resourceName: "qrcode")), !features.isEmpty{
for case let row as CIQRCodeFeature in features{
print(row.messageString ?? "nope")
}
}
Run Code Online (Sandbox Code Playgroud)
在执行过程中不会产生 Finalizing CVPixelBuffer 0x170133e20 while lock count is 1
我使用了以下QRCode图像(QRCode = https://jingged.com)
(在具有iOS版本11.2的iPhone 6模拟器上进行了测试)
输出:
2018-03-14 15:31:13.159400+0530 TestProject[25889:233062] [MC] Lazy loading NSBundle MobileCoreServices.framework
2018-03-14 15:31:13.160302+0530 TestProject[25889:233062] [MC] Loaded MobileCoreServices.framework
https://jingged.com
Run Code Online (Sandbox Code Playgroud)
如果你只需要一个字符串,你可以使用这样的代码:
class QRToString {
func string(from image: UIImage) -> String {
var qrAsString = ""
guard let detector = CIDetector(ofType: CIDetectorTypeQRCode,
context: nil,
options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]),
let ciImage = CIImage(image: image),
let features = detector.features(in: ciImage) as? [CIQRCodeFeature] else {
return qrAsString
}
for feature in features {
guard let indeedMessageString = feature.messageString else {
continue
}
qrAsString += indeedMessageString
}
return qrAsString
}
}
Run Code Online (Sandbox Code Playgroud)
使用Zbar SDK从静态图像中读取QRcode。
关于Zbar SDK的集成请查看本教程。
然后尝试扫描静态图像。
使用 Zbar 扫描仪类来扫描您的图像。
这是文档。
仅举个例子,如何使用 Zbar 扫描仪类,
ZBarImageScanner *scandoc = [[ZBarImageScanner alloc]init];
NSInteger resultsnumber = [scandoc scanImage:yourUIImage];
if(resultsnumber > 0){
ZBarSymbolSet *results = scandoc.results;
//Here you will get result.
}
Run Code Online (Sandbox Code Playgroud)
下面的链接将为您提供帮助。
| 归档时间: |
|
| 查看次数: |
12105 次 |
| 最近记录: |