我知道您可以使用AVFoundation
使用设备的相机扫描QR码。现在出现了问题,如何从静态UIImage
对象中执行此操作?
答案 0 :(得分: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;
}
}
如果存在并检测到QRCode,则返回的NSArray*
将包含CIFeature*
。如果没有QRCode,则NSArray*
将为nil
。如果QRCode解码失败,NSArray*
将没有元素。
获取编码字符串:
if (features != nil && features.count > 0) {
for (CIQRCodeFeature* qrFeature in features) {
NSLog(@"QRFeature.messageString : %@ ", qrFeature.messageString);
}
}
在@ Duncan-C的答案中,您可以提取QRCode角并在图像上绘制QRCode的封闭边界框。
注意:
在iOS10.0 beta 6下,当使用来自cameraSampleBuffer的图像时,对[qrDetector featuresInImage:ciImage options:options]
的调用会记录此内部警告(它运行顺利,但是使用此消息向控制台发送垃圾邮件,我找不到摆脱它的方法现在):
锁定计数为1时,最终确定CVPixelBuffer 0x170133e20。
来源:
答案 1 :(得分:8)
Core Image具有CIDetector
类,CIDetectorTypeQRCode
用于检测QR码。您可以为静止图像或视频提供Core Image滤镜。
那应该满足你的需求。有关详细信息,请参阅Xcode文档。
来自ShinobiControls的Github repo iOS8-day-by-day包括一个项目LiveDetection,它显示如何从视频源和静止图像中使用CIDetectorTypeQRCode。看起来它还没有针对Swift 2.0进行更新,我无法在Xcode 7.2.1下进行编译,但是项目中的函数performQRCodeDetection
正在编译。 (编译问题是使用代码来处理在Swift中处理CVPixelBuffers
时必须处理的所有可怕的类型转换,如果您只想在静态图像中找到QRCodes,则无关紧要。)< / p>
以下是该网站的关键方法(在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)
}
答案 2 :(得分:5)
Swift 4版本的@ Neimsz&#39; s answer
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
}
如何使用
if let features = detectQRCode(#imageLiteral(resourceName: "qrcode")), !features.isEmpty{
for case let row as CIQRCodeFeature in features{
print(row.messageString ?? "nope")
}
}
在执行期间,这不会产生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
答案 3 :(得分:2)
使用 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.
}
以下链接可以为您提供帮助。
答案 4 :(得分:2)
在返回测试消息方面,这里的答案没有一个非常简单。做了一个对我来说很好的扩展:
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
}
}
}
答案 5 :(得分:1)
如果只需要一个字符串,则可以使用以下代码:
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
}
}