importUIKit
importAVFoundation
private let scanAnimationDuration = 3.0//扫描时长
private let needSound = true //扫描结束是否需要播放声音
private let scanWidth : CGFloat = 300 //扫描框宽度
private let scanHeight : CGFloat = 300 //扫描框高度
private let isRecoScanSize = true //是否仅识别框内
private let scanBoxImagePath = "扫描框" //扫描框图片
private let scanLineImagePath = "扫描线" //扫描线图片
private let soundFilePath = "noticeMusic.caf" //声音文件
class ZWScanQRCodeVCJoe: UIViewController{
letcancelBtn=UIButton()//取消返回按钮
var scanPane: UIImageView!///扫描框
var scanPreviewLayer : AVCaptureVideoPreviewLayer! //预览图层
var output : AVCaptureMetadataOutput!
var scanSession: AVCaptureSession?
lazyvarscanLine:UIImageView= {
letscanLine =UIImageView()
scanLine.frame=CGRect(x:0,y:0,width:scanWidth,height:3)
scanLine.image=UIImage(named:scanLineImagePath)
returnscanLine
}()
override func viewDidLoad(){
super.viewDidLoad()
//初始化界面
self.initView()
//初始化ScanSession
setupScanSession()
// 监听屏幕旋转
// NotificationCenter.default.addObserver(self, selector: #selector(receiverNotification), name: UIDevice.orientationDidChangeNotification, object: nil)
self.receiverNotification()
}
@objc func receiverNotification() {
setLayerOrientationByDeviceOritation()
}
overridefuncviewWillAppear(_animated:Bool){
super.viewWillAppear(animated)
startScan()
}
//初始化界面
funcinitView() {
//取消按钮 返回按钮
cancelBtn.frame = CGRect(x: 63*WidthW, y: 70*WidthW, width: 92*WidthW, height: 92*WidthW)
// cancelBtn.backgroundColor = UIColor.gray
cancelBtn.setTitleColor(UIColor.white, for: .normal)
cancelBtn.titleLabel?.font = UIFont.systemFont(ofSize: 18)
cancelBtn.layer.cornerRadius = 3
cancelBtn.clipsToBounds = true
cancelBtn.tag=1
cancelBtn.setImage(UIImage.init(named: "返回"), for: .normal)
cancelBtn.addTarget(self, action: #selector(closeBtnClick), for: .touchUpInside)
self.view.addSubview(cancelBtn)
//
scanPane=UIImageView()
scanPane.frame=CGRect(x:300,y:100,width:400,height:400)
scanPane.image = UIImage(named: scanBoxImagePath)
self.view.addSubview(scanPane)
//增加约束
addConstraint()
scanPane.addSubview(scanLine)
}
//返回页面
@objc func closeBtnClick(){
self.view.viewContainingController()?.navigationController?.popViewController(animated: false)
}
//扫描完成回调
funcqrCodeCallBack(_codeString :String?) {
self.confirm(title:"扫描结果",message: codeString,controller:self,handler: { (_)in
//继续扫描
self.startScan()
})
}
func addConstraint() {
scanPane.translatesAutoresizingMaskIntoConstraints = false
//创建约束
let widthConstraint = NSLayoutConstraint(item: scanPane as Any, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: scanWidth)
let heightConstraint = NSLayoutConstraint(item: scanPane as Any, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: scanHeight)
let centerX = NSLayoutConstraint(item: scanPane as Any, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0)
let centerY = NSLayoutConstraint(item: scanPane as Any, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1.0, constant: 0)
//添加多个约束
view.addConstraints([widthConstraint,heightConstraint,centerX,centerY])
}
//初始化scanSession
func setupScanSession(){
do{
//设置捕捉设备
letdevice =AVCaptureDevice.default(for:AVMediaType.video)!
//设置设备输入输出
letinput =tryAVCaptureDeviceInput(device: device)
letoutput =AVCaptureMetadataOutput()
output.setMetadataObjectsDelegate(self,queue: DispatchQueue.main)
self.output= output
//设置会话
let scanSession =AVCaptureSession()
scanSession.canSetSessionPreset(.high)
ifscanSession.canAddInput(input){
scanSession.addInput(input)
}
ifscanSession.canAddOutput(output){
scanSession.addOutput(output)
}
//设置扫描类型(二维码和条形码)
output.metadataObjectTypes= [
.qr,
.code39,
.code128,
.code39Mod43,
.ean13,
.ean8,
.code93
]
//预览图层
letscanPreviewLayer =AVCaptureVideoPreviewLayer(session:scanSession)
scanPreviewLayer.videoGravity=AVLayerVideoGravity.resizeAspectFill
scanPreviewLayer.frame=view.layer.bounds
self.scanPreviewLayer= scanPreviewLayer
setLayerOrientationByDeviceOritation()
//保存会话
self.scanSession= scanSession
}catch{
//摄像头不可用
self.confirm(title: "温馨提示", message: "摄像头不可用", controller: self)
return
}
}
func setLayerOrientationByDeviceOritation() {
if(scanPreviewLayer == nil){
return
}
scanPreviewLayer.frame = view.layer.bounds
view.layer.insertSublayer(scanPreviewLayer, at: 0)
letscreenOrientation =UIDevice.current.orientation
if(screenOrientation == .portrait){
scanPreviewLayer.connection?.videoOrientation = .portrait
}elseif(screenOrientation == .landscapeLeft){
scanPreviewLayer.connection?.videoOrientation = .landscapeRight
}elseif(screenOrientation == .landscapeRight){
scanPreviewLayer.connection?.videoOrientation = .landscapeLeft
}elseif(screenOrientation == .portraitUpsideDown){
scanPreviewLayer.connection?.videoOrientation = .portraitUpsideDown
}else{
scanPreviewLayer.connection?.videoOrientation = .landscapeRight
}
//设置扫描区域
NotificationCenter.default.addObserver(forName:NSNotification.Name.AVCaptureInputPortFormatDescriptionDidChange,object:nil,queue:nil,using: { (noti)in
if(isRecoScanSize){
self.output.rectOfInterest = self.scanPreviewLayer.metadataOutputRectConverted(fromLayerRect: self.scanPane.frame)
}else{
self.output.rectOfInterest=CGRect(x:0,y:0,width:1,height:1)
}
})
}
//设备旋转后重新布局
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
setLayerOrientationByDeviceOritation()
}
//开始扫描
fileprivate func startScan(){
scanLine.layer.add(scanAnimation(), forKey: "scan")
guardletscanSession =scanSessionelse{return}
if!scanSession.isRunning
{
scanSession.startRunning()
}
}
//扫描动画
private func scanAnimation() -> CABasicAnimation{
letstartPoint =CGPoint(x:scanLine.center.x ,y:1)
letendPoint =CGPoint(x:scanLine.center.x,y:scanHeight-2)
lettranslation =CABasicAnimation(keyPath:"position")
translation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
translation.fromValue=NSValue(cgPoint: startPoint)
translation.toValue=NSValue(cgPoint: endPoint)
translation.duration=scanAnimationDuration
translation.repeatCount=MAXFLOAT
translation.autoreverses=true
returntranslation
}
//MARK: -
//MARK: Dealloc
deinit{
///移除通知
NotificationCenter.default.removeObserver(self)
}
}
//MARK: -
//MARK: AVCaptureMetadataOutputObjects Delegate
extension ZWScanQRCodeVCJoe : AVCaptureMetadataOutputObjectsDelegate
{
//捕捉扫描结果
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
//停止扫描
self.scanLine.layer.removeAllAnimations()
self.scanSession!.stopRunning()
//播放声音
if(needSound){
self.playAlertSound()
}
//扫描完成
ifmetadataObjects.count>0{
ifletresultObj = metadataObjects.firstas?AVMetadataMachineReadableCodeObject{
self.qrCodeCallBack(resultObj.stringValue)
}
}
}
//弹出确认框
func confirm(title:String?,message:String?,controller:UIViewController,handler: ( (UIAlertAction) -> Swift.Void)? = nil){
letalertVC =UIAlertController(title: title,message: message,preferredStyle: .alert)
letentureAction =UIAlertAction(title:"确定",style: .destructive,handler: handler)
alertVC.addAction(entureAction)
controller.present(alertVC,animated:true,completion:nil)
}
//播放声音
func playAlertSound(){
guardletsoundPath =Bundle.main.path(forResource:soundFilePath,ofType:nil) else{return}
guardletsoundUrl =NSURL(string: soundPath)else{return}
varsoundID:SystemSoundID=0
AudioServicesCreateSystemSoundID(soundUrl, &soundID)
AudioServicesPlaySystemSound(soundID)
}
}
我正在处理http://prepwork.appacademy.io/mini-curriculum/array/中概述的数组问题我正在尝试创建函数my_transpose,它接受一个矩阵并返回其转置。我对写入二维数组感到很困惑!这是一个代码片段,突出了我的困惑。rows=[[0,1,2],[3,4,5],[6,7,8]]columns=Array.new(3,Array.new(3))putscolumns.to_s#Outputisa3x3arrayfilledwithnilcolumns[0][0]=0putscolumns.to_s#Outputis[[0,nil,nil],[
技术选型1,前端小程序原生MINA框架cssJavaScriptWxml2,管理后台云开发Cms内容管理系统web网页3,数据后台小程序云开发云函数云开发数据库(基于MongoDB)云存储4,人脸识别算法基于百度智能云实现人脸识别一,用户端效果图预览老规矩我们先来看效果图,如果效果图符合你的需求,就继续往下看,如果不符合你的需求,可以跳过。1-1,登录注册页可以看到登录页有注册入口,注册页如下我们的注册,需要管理员审核,审核通过后才可以正常登录使用小程序1-2,个人中心页登录成功以后,我们会进入个人中心页我们在个人中心页可以注册人脸,因为我们做人脸识别签到,需要先注册人脸才可以进行人脸比对,进
我想在rubyonrails中生成QR码,以便在我用rails编写的网站后台运行。看到这个http://code.google.com/p/qrcode-rails/但无法弄清楚如何让它为我工作。基本上在RoR中,我想:向生成器传递一个字符串、我的唯一代码、一个20个字符长度的数字(例如32032928889998887776)并生成一个名为“代码”_qr.jpg的图像并保存在资源文件夹中以附加到我的电子邮件中程序将发出。我该怎么做,有人知道吗?虽然我在问(不是很重要,我现在得到这个答案)但是我如何实现QR码读取,以从网络摄像头取回该代码?谢谢。 最佳答
这是我的代码,可以运行,但它太大了。我想重构它。req_row=-1req_col=-1a.each_with_indexdo|row,index|row.each_with_indexdo|col,i|ifcol==0req_row=indexreq_col=ibreakendendendifreq_col>-1andreq_row>-1a.each_with_indexdo|row,index|row.each_with_indexdo|col,i|print(req_row==indexori==req_col)?0:colprint""endputs"\r"endend输入:二
我正在尝试学习如何在二维数组中进行搜索;例如:array=[[1,1],[1,2],[1,3],[2,1],[2,4],[2,5]]我想知道如何在数组中搜索格式为[1,y]的数组,然后显示其他y数字是什么:[1,2,3]。如果有人能帮助我了解如何仅使用数字进行搜索(因为我发现的很多示例都包含字符串或哈希),甚至可以帮助我了解在哪里寻找正确的资源,那将会很有帮助。 最佳答案 Ruby允许您通过在block参数中使用圆括号来查看元素。select和map只分配一个block参数,但您可以查看元素:array.select{|(x,y)|
我正在尝试使用我的2Druby数组解决一些问题,当我进行数组切片时,我的LOC减少了很多。例如,require"test/unit"classLibraryTest我想知道是否有办法得到对角切片?假设我想从[0,0]开始并想要一个3的对角线切片。然后我会从[0,0]、[1,1]、[2,2]获取元素,我会得到一个数组[1,4,7]上面的例子。是否有任何神奇的单行ruby代码可以实现这一目标?3.次做{一些神奇的东西?} 最佳答案 puts(0..2).collect{|i|array[i][i]}
我正在打印一些QR码(来自Ruby脚本),将ESC/POS命令写入EpsonTM-T20热敏打印机。顺便说一句,我正在编写一个简单的ESC/POS命令打印机“驱动程序”。我用的打印机是EpsonTM-T20(USB接口(interface))我正在使用serialportgem从Windows7主机进行一些测试。关于为打印格式化文本和线性条形码编写ESC/POS命令的一切都很好,但是我在理解打印QR代码的命令协议(protocol)时遇到问题,使用Epson提供的唯一可用文档(据我所知),请参阅:http://www.novopos.ch/client/EPSON/TM-T20/TM-
a=[1,2,3]b=[4,5,6]我如何将两个数组组合成一个二维数组?:[[1,4],[2,5],[3,6]] 最佳答案 尝试Array#zipa.zip(b)=>[[1,4],[2,5],[3,6]] 关于arrays-组合两个数组以在ruby中创建一个二维数组,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/12011294/
我正在研究Rails3.0。我有一个二维数组。二维数组由用户数据和一个bool值组成。例如:[[user1,true],[user2,true],[user3,false]]看起来像这样:[[#,true],[#,true],[#,false],]我想有条件地查找/提取记录;说找到一整行Userid=2,它应该只返回第二行,即[#,true]有没有办法遍历这样的数组?如何实现? 最佳答案 my_array.select{|user,flag|user.id==2}所有拥有true标志的用户:my_array.select{|user
我对Ruby知之甚少,找不到创建二维数组的方法。任何人都可以提供一些片段或信息让我开始吗? 最佳答案 a=[[1,2],[3,4]]a.eachdo|sub|sub.eachdo|int|putsintendend#Output:#1#2#3#4或:a=[[1,2],[3,4]]a.eachdo|(x,y)|putsx+yend#Output:#3#7 关于ruby-在Ruby中创建和迭代二维数组,我们在StackOverflow上找到一个类似的问题: htt