IOS ARKit进行图像识别

先讲一下基础控涧,资源的话可以留言,抽空我把它传到GitHub上,这里没写收积分,竟然充值才能下载,我下载也要充值,牛!
ARSCNView 可以理解画布或者场景
1 配置 ARWorldTrackingConfiguration AR追踪识别相关
ARFaceTrackingConfiguration 面部识别
2 加载资源 图片资源就不多讲,手机拍照去掉底图就可以了,3d模型需要带linda的ipad pro或者iphone pro构建
一共两种一种是识别图片,一种是识别3d模型,感觉图片识别效果较好,但是麻烦点是获取现实世界空间坐标,而且对运动物体还是不是很友好,所以后来准备看一下CoreML相关

let configuartion = ARWorldTrackingConfiguration()
var images :[UIImage] = []for i in 1...19{let image = UIImage(named: "AR\(i)")images.append(image!)}//加载图片资源,通过图片名configuartion.detectionImages = loadedImagesFromDirectoryContents(images)configuartion.maximumNumberOfTrackedImages = 1//加载3d资源,3d资源文件如下图所示
if let referenceObj = ARReferenceObject.referenceObjects(inGroupNamed: "AR Resource Group", bundle: nil){print("")configuartion.detectionObjects = referenceObj}configuartion.isAutoFocusEnabled = true // 确保自动对焦开启
//       configuartion.planeDetection = .horizontalconfiguartion.isLightEstimationEnabled = truesceneView.session.run(configuartion, options: [.resetTracking,.removeExistingAnchors])//遵守的代理协议ARSessionDelegate 会话协议sceneView.session.delegate = self//ARSCNViewDelegate scnview场景协议sceneView.delegate = self//显示调试参数sceneView.debugOptions = [SCNDebugOptions.showFeaturePoints]//通过图片名加载图片func loadedImagesFromDirectoryContents(_ images: [UIImage]) -> Set<ARReferenceImage>{var index = 0var customReferenceSet = Set<ARReferenceImage>()images.forEach { (downloadedImage) in//1. Convert The UIImage To A CGImageguard let cgImage = downloadedImage.cgImage else { return }//2. Get The Width Of The Imagelet imageWidth = CGFloat(cgImage.width)//3. Create A Custom AR Reference Image With A Unique Namelet customARReferenceImage = ARReferenceImage(cgImage, orientation: CGImagePropertyOrientation.up, physicalWidth: imageWidth)customARReferenceImage.name = "MyCustomARImage\(index)"//4. Insert The Reference Image Into Our SetcustomReferenceSet.insert(customARReferenceImage)print("ARReference Image == \(customARReferenceImage)")index += 1}//5. Return The Setreturn customReferenceSet}

3d资源文件,文件格式是.arobject,该文件是通过带Linda的iPad pro设备扫描生成的,详情参考代码demo
请添加图片描述

ARSessionDelegate 协议

/*会话失败*/func session(_ session: ARSession, didFailWithError error: any Error) {print("didFailWithError")}/*相机更改了追踪模式*/func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {let state = camera.trackingStateprint("cameraDidChangeTrackingState")}/*当会话中断时调用此方法。会话将被中断,不再能跟踪什么时候它无法接收所需的传感器数据。 当视频捕获中断时,例如当应用程序被发送到后台或当有的时候多个前台应用程序(请参阅AVCaptureSessionInterruptReason)。在中断结束之前,不会传送额外的帧更新。*/func sessionWasInterrupted(_ session: ARSession) {print("sessionWasInterrupted")}/*当会话中断结束时调用。会话将从最后一次已知的状态继续运行一次中断已经结束。 如果设备移动,锚点将不对齐。为避免这种情况,一些应用程序可能想要重置跟踪(请参阅ARSessionRunOptions)。*/func sessionInterruptionEnded(_ session: ARSession) {print("sessionInterruptionEnded")}/*当会话输出新的音频采样缓冲区时*/func session(_ session: ARSession, didOutputAudioSampleBuffer audioSampleBuffer: CMSampleBuffer) {print("didOutputAudioSampleBuffer")}func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {//更新锚点位置,存入的锚点信息,也可以是图片锚点for anchor in anchors {guard let objectAnchor = anchor as? ARObjectAnchor else { continue }// 查找对应的框节点if let frameNode = sceneView.scene.rootNode.childNode(withName: "frame", recursively: true) {
//                    frameNode.position = SCNVector3(
//                        objectAnchor.transform.columns.3.x,
//                        objectAnchor.transform.columns.3.y,
//                        objectAnchor.transform.columns.3.z
//                    )frameNode.simdTransform = anchor.transform}}//        guard let trackedAnchor = trackedAnchor else{return}
//        
//        for anchor in anchors{
//            if anchor.identifier == trackedAnchor.identifier{
//                let newTransform = anchor.transform
//                let position = SCNVector3(newTransform.columns.3.x,
//                                          newTransform.columns.3.y,
//                                          newTransform.columns.3.z)
//                
//                DispatchQueue.main.async {
//                    self.trackNode?.position = position
//                }
//            }
//        }
//        print("didupdate session")
//        //跟踪目标物体
//        for anchor in anchors {
//              if let objectAnchor = anchor as? ARObjectAnchor {
//                  print("Object moved to: \(objectAnchor.transform)")
//                  
//                  // 更新虚拟对象的位置
//                  if let node = sceneView.node(for: objectAnchor) {
//                      let transform = objectAnchor.transform
//                      node.simdTransform = transform
//                  }
//              }
//          }}func session(_ session: ARSession, didUpdate frame: ARFrame) {DispatchQueue.global().async {self.handleFrame(session: session, frame: frame)}}

ARSCNViewDelegate代理

 /*实现这个为给定的锚点提供一个自定义节点。@discussion 此节点将自动添加到场景图。如果未实现此方法,将自动创建一个节点。如果返回nil,锚点将被忽略。@param renderer渲染场景的渲染器。@param anchor添加的锚点。@return将映射到锚点或nil的节点*/
//    func renderer(_ renderer: any SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
//        return nil
//    }/*当新节点已映射到给定的锚点时调用。@param renderer 渲染场景的渲染器。@param node 映射到锚点的节点。@param anchor 添加的锚点。*/func renderer(_ renderer: any SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//        print("添加新的节点锚点数据到场景中")if let objectAnchor = anchor as? ARObjectAnchor {print("Detected object: \(objectAnchor.referenceObject.name ?? "Unknown")")// 创建一个框架来圈住物体let frameNode = createFrame(for: objectAnchor.referenceObject)frameNode.position = SCNVector3(objectAnchor.transform.columns.3.x,objectAnchor.transform.columns.3.y,objectAnchor.transform.columns.3.z)sceneView.scene.rootNode.addChildNode(frameNode)}//        if let imageAnchor = anchor as? ARImageAnchor{
//            let image = imageAnchor.referenceImage
//            
//            if let imagename = image.name, imagename.hasPrefix("MyCustomARImage"){
//                // 创建一个虚拟对象(如盒子)来标记目标位置let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)let material = SCNMaterial()material.diffuse.contents = UIColor.redbox.materials = [material]let boxNode = SCNNode(geometry: box)boxNode.position = SCNVector3(0, 0, 0)node.addChildNode(boxNode)
//                DispatchQueue.main.async {
//                    self.showToast()
//                }
//            }
//        }
}/*当节点将使用给定锚点的数据进行更新时调用。@param renderer 渲染场景的渲染器。@param node 将被更新的节点。@param anchor 即将更新的锚点。*/func renderer(_ renderer: any SCNSceneRenderer, willUpdate node: SCNNode, for anchor: ARAnchor) {
//        print("即将更新新节点锚点数据")}/*当节点将使用给定锚点的数据进行更新时调用。@param renderer 渲染场景的渲染器。@param node 将被更新的节点。@param anchor 已更新的锚点。*/func renderer(_ renderer: any SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
//        print("已经更新节点锚点数据")}/*当映射节点已从给定锚点的场景图中删除时调用。@param renderer渲染场景的渲染器。@param node已删除的节点。@param anchor已删除的锚点。*/func renderer(_ renderer: any SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {print("删除节点")}

以上是整个代码流程
图片识别部分如下

 private func handleFrame(session: ARSession,frame: ARFrame){let i = frame.timestamp - (self.currentFrmae?.timestamp ?? 0)
//        print("time i\(i)")if i < 1{return}self.currentFrmae = frameguard let frameImg = getCurrentFrameImage(from: session) else{return}var isMatched:Bool = falsefor img in self.images{
//            if compareImages(image1: frameImg, image2: img) == 1{
//                isMatched = true
//                break
//            }let im1 = frameImglet im2 = imgmatchImages(image1: frameImg, image2: img) { [weak self]isok inif isok{DispatchQueue.main.async {self?.showToast()}}}}if isMatched{DispatchQueue.main.async {self.showToast()}}}//获取当前会话帧数据func getCurrentFrameImage(from session: ARSession) -> UIImage? {guard let currentFrame = session.currentFrame else {print("当前没有 ARFrame")return nil}let pixelBuffer = currentFrame.capturedImagelet ciImage = CIImage(cvPixelBuffer: pixelBuffer)let context = CIContext()guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else {return nil}return UIImage(cgImage: cgImage)}//对比图片2func matchImages(image1: UIImage, image2: UIImage, completion: @escaping (Bool) -> Void) {guard let cgImage1 = image1.cgImage, let cgImage2 = image2.cgImage else {completion(false)return}//使用自定义检测任务let request1 = VNGenerateImageFeaturePrintRequest()let request2 = VNGenerateImageFeaturePrintRequest()let request3 = VNDetectRectanglesRequest()request3.minimumConfidence = 0.8request3.minimumAspectRatio = 0.1request3.maximumAspectRatio = 1.0request3.quadratureTolerance = 10let handler1 = VNImageRequestHandler(cgImage: cgImage1, options: [:])let handler2 = VNImageRequestHandler(cgImage: cgImage2, options: [:])let handler3 = VNImageRequestHandler(cgImage: cgImage1, options: [:])do {try handler1.perform([request1])try handler2.perform([request2])try handler3.perform([request3])guard let featurePrint1 = request1.results?.first as? VNFeaturePrintObservation,let featurePrint2 = request2.results?.first as? VNFeaturePrintObservation else {completion(false)return}if let observations = request3.results as? [VNRectangleObservation], !observations.isEmpty{// 假设目标区域是第一个匹配的矩形let boundingBox = observations.first?.boundingBoxprint("boundRext: \(boundingBox)")}var distance: Float = 0try featurePrint1.computeDistance(&distance, to: featurePrint2)print("匹配值 \(distance)")if distance < 0.8{ //距离0.8mprint("图片相似")}completion(distance < 0.8) // 设定相似度阈值} catch {print("匹配失败:\(error)")completion(false)}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/484315.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

40分钟学 Go 语言高并发:GC原理与优化

GC原理与优化 一、GC基础知识概览 方面核心概念重要性优化目标GC算法三色标记法、并发GC⭐⭐⭐⭐⭐理解GC工作原理垃圾回收策略触发条件、回收步骤⭐⭐⭐⭐⭐掌握GC过程GC调优参数设置、性能监控⭐⭐⭐⭐优化GC效果内存管理内存分配、内存逃逸⭐⭐⭐⭐⭐减少内存压力 让我们…

2024算法基础公选课练习八(综合4)

一、前言 前面几个题都是考察字符串处理&#xff0c;后面的都是偏难的思维和图论题 二、题目总览 三、具体题目 3.1 问题 A: 昊城的分割游戏 思路 枚举前几项&#xff0c;然后发现规律 我的代码 #include<bits/stdc.h> using i64 long long; using u64 unsigned …

前端 el-table-column 里加上el-form-item 上面有黑色悬浮

如图所示 解决方法&#xff0c;查看你的 el-table-column 是否设置了 show-overflow-tooltip 属性&#xff0c;如果是去掉即可

debian编译失败

A、缘由和分析 debian的代码在删除该路径下的2个包后&#xff0c; 重新全编&#xff0c;编译不过的问题。 至于我为什么删除这2个包&#xff0c;这是因为在sdk第一次编译时一些文件已经打包进去了&#xff0c;我现在的修改无法更新进img中&#xff0c;而现在我的项目中不需要…

大数据新视界 -- 大数据大厂之 Hive 数据压缩:优化存储与传输的关键(上)(19/ 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【k8s】监控metrics-server

metrics-server介绍 Metrics Server是一个集群范围的资源使用情况的数据聚合器。作为一个应用部署在集群中。Metric server从每个节点上KubeletAPI收集指标&#xff0c;通过Kubernetes聚合器注册在Master APIServer中。为集群提供Node、Pods资源利用率指标。 就像Linux 系统一样…

EasyAnimateV5 视频生成大模型原理详解与模型使用

在数字内容创作中&#xff0c;视频扮演的角色日益重要。然而&#xff0c;创作高质量视频通常耗时且昂贵。EasyAnimate 系列旨在利用人工智能技术简化这一过程。EasyAnimateV5 建立在其前代版本的基础之上&#xff0c;不仅在质量上有所提升&#xff0c;还在多模态数据处理和跨语…

泷羽sec学习打卡-shell命令7

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于shell的那些事儿-shell6 for循环while循环实践是检验真理的唯一标准 见天我们继续学习下shell中的基…

8. 一分钟读懂“代理模式”

8.1 模式介绍 代理模式是一种结构型设计模式&#xff0c;它通过提供一个代理对象来替代对另一个对象&#xff08;真实对象&#xff09;的访问。代理对象与真实对象实现相同的接口&#xff0c;并通过代理类对真实对象的访问进行控制&#xff0c;可以在调用前后执行附加操作&…

基于SpringBoot+Vue的宠物咖啡馆系统-无偿分享 (附源码+LW+调试)

目录 1. 项目技术 2. 功能菜单 3. 部分功能截图 4. 研究背景 5. 研究目的 6. 可行性分析 6.1 技术可行性 6.2 经济可行性 6.3 操作可行性 7. 系统设计 7.1 概述 7.2 系统流程和逻辑 7.3 系统结构 8. 数据库设计 8.1 数据库ER图 &#xff08;1&#xff09;宠物订…

Python毕业设计选题:基于大数据的淘宝电子产品数据分析的设计与实现-django+spark+spider

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 电子产品管理 系统管理 数据可视化分析看板展示 摘要 本…

【人工智能的深度分析与最新发展趋势】

人工智能的深度分析与最新发展趋势 引言 人工智能&#xff08;AI&#xff09;是现代科技的重要组成部分&#xff0c;它涉及模拟人类智能的算法和技术。随着计算能力的提升和数据量的激增&#xff0c;AI的应用正在迅速渗透到各个行业。本文将深入分析人工智能的概念、技术、应…

NLP自然语言处理——关键词提取之 TF-IDF 算法(五分钟带你深刻领悟TF-IDF算法的精髓)

&#x1f525;博客主页&#xff1a;是dream &#x1f680;系列专栏&#xff1a;深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发 &#x1f498;每日语录&#xff1a;要有最朴素的生活和最遥远&#x1f30f;的梦想&#xff0c;即使明天天寒地冻&am…

【连接池】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

预训练模型与ChatGPT:自然语言处理的革新与前景

目录 一、ChatGPT整体背景认知 &#xff08;一&#xff09;ChatGPT引起关注的原因 &#xff08;二&#xff09;与其他公司的竞争情况 二、NLP学习范式的发展 &#xff08;一&#xff09;规则和机器学习时期 &#xff08;二&#xff09;基于神经网络的监督学习时期 &…

LeetCode - #151 颠倒字符串中的单词

文章目录 前言1. 描述2. 示例3. 答案关于我们 前言 我们社区陆续会将顾毅&#xff08;Netflix 增长黑客&#xff0c;《iOS 面试之道》作者&#xff0c;ACE 职业健身教练。&#xff09;的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 LeetCode 算法到目前我们已经更新…

微服务即时通讯系统(5)用户管理子服务,网关子服务

用户管理子服务&#xff08;user文件&#xff09; 用户管理子服务也是这个项目中的一个业务最多的子服务&#xff0c;接口多&#xff0c;但是主要涉及的数据表只有user表&#xff0c;Redis的键值对和ES的一个搜索引擎&#xff0c;主要功能是对用户的个人信息进行修改管理&#…

vue结合canvas动态生成水印效果

在 Vue 项目中添加水印可以通过以下几种方式实现&#xff1a; 方法一&#xff1a;使用 CSS 直接通过 CSS 的 background 属性实现水印&#xff1a; 实现步骤 在需要添加水印的容器中设置背景。使用 rgba 设置透明度&#xff0c;并通过 background-repeat 和 background-size…

html-两个div,让一个div跟随另外一个div的高度

在开发的过程中遇到有些场景事这样的&#xff0c;两个div的高度不一致&#xff0c;而且都是动态高度&#xff0c;有的时候div1高&#xff0c;有的时候div2高&#xff0c;如果设置flex的话&#xff0c;那么就会把较矮的元素撑大&#xff0c;但是我想始终都以div1的高度作为基准&…

知识管理系统|基于springBoot的知识管理系统设计与实现(附项目源码+论文+数据库)

私信或留言即免费送开题报告和任务书&#xff08;可指定任意题目&#xff09; 目录 一、摘要 二、相关技术 三、系统设计 四、数据库设计 五、核心代码 六、论文参考 七、源码获取 一、摘要 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势…