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)}}
相关文章:
IOS ARKit进行图像识别
先讲一下基础控涧,资源的话可以留言,抽空我把它传到GitHub上,这里没写收积分,竟然充值才能下载,我下载也要充值,牛! ARSCNView 可以理解画布或者场景 1 配置 ARWorldTrackingConfiguration AR追…...
初级数据结构——二叉搜索树
目录 前言一、定义二、基本操作三、时间复杂度分析四、变体五、动态图解六、代码模版七、经典例题[1.——700. 二叉搜索树中的搜索](https://leetcode.cn/problems/search-in-a-binary-search-tree/)代码题解 [2.——938. 二叉搜索树的范围和](https://leetcode.cn/problems/ra…...
C++设计模式之组合模式中如何实现同一层部件的有序性
在组合模式中,为了实现同一层上部件的有序性,可以采取以下几种设计方法: 1. 使用有序集合 使用有序集合(如 std::list、std::vector 或其他有序容器)来存储和管理子部件。这种方法可以确保子部件按照特定顺序排列&am…...
duxapp RN 端使用AppUpgrade 进行版本更新
版本更新包含了组件和工具的组合 注册 下面这是 duxcms 入口文件检查更新的注册方法,注册的同时会检查更新 import {request,updateApp,userConfig } from ./utils// 检查app更新 setTimeout(async () > {if (process.env.TARO_ENV rn) {// eslint-disable-n…...
【计网】自定义序列化反序列化(三) —— 实现网络版计算器【下】
🌎实现网络版计算器【下】 本次序列化与反序列化所用到的代码,Tcp服务自定义序列化反序列化实现网络版计算器。 文章目录: 实实现网络版计算器【下】 客户端实现 基于守护进程的改写 🚀客户端实现 在这之前,…...
神经网络中的优化方法(一)
目录 摘要Abstract1. 与纯优化的区别1.1 经验风险最小化1.2 代理损失函数1.3 批量算法和小批量算法 2. 神经网络中优化的挑战2.1 病态2.2 局部极小值2.3 高原、鞍点和其他平坦区域2.4 悬崖和梯度爆炸2.5 长期依赖2.6 非精确梯度2.7 局部和全局结构间的弱对应 3. 基本算法3.1 随…...
Linux 计算机网络基础概念
目录 0.前言 1.计算机网络背景 1.1 独立模式 1.2 网络互联 1.3 局域网(Local Area Network,LAN) 1.4 广域网(Wide Area Network,WAN) 2.协议 2.1什么是协议 2.2协议分层和软件分层 2.3 OSI七层网络模型 2.3…...
qt QGraphicsEllipseItem详解
1、概述 QGraphicsEllipseItem是Qt框架中QGraphicsItem的一个子类,它提供了一个可以添加到QGraphicsScene中的椭圆项。QGraphicsEllipseItem表示一个带有填充和轮廓的椭圆,也可以用于表示椭圆段(通过startAngle()和spanAngle()方法ÿ…...
Python websocket
router.websocket(/chat/{flow_id}) 接口代码,并了解其工作流程、涉及的组件以及如何基于此实现你的新 WebSocket 接口。以下内容将分为几个部分进行讲解: 接口整体概述代码逐行解析关键组件和依赖关系如何基于此实现新功能示例:创建一个新的…...
【MySQL-5】MySQL的内置函数
目录 1. 整体学习的思维导图 2. 日期函数 编辑 2.1 current_date() 2.2 current_time() 2.3 current_timestamp() 2.4 date(datetime) 2.5 now() 2.6 date_add() 2.7 date_sub() 2.8 datediff() 2.9 案例 2.9.1 创建一个出生日期登记簿 2.9.2 创建一个留言版 3…...
深度学习笔记之BERT(三)RoBERTa
深度学习笔记之RoBERTa 引言回顾:BERT的预训练策略RoBERTa训练过程分析静态掩码与动态掩码的比较模型输入模式与下一句预测使用大批量进行训练使用Byte-pair Encoding作为子词词元化算法更大的数据集和更多的训练步骤 RoBERTa配置 引言 本节将介绍一种基于 BERT \t…...
C++知识点总结(59):背包型动态规划
背包型动态规划 一、背包 dp1. 01 背包(限量)2. 完全背包(不限量)3. 口诀 二、例题1. 和是质数的子集数2. 黄金的太阳3. 负数子集和4. NASA的⻝物计划 一、背包 dp 1. 01 背包(限量) 假如有这几个物品&am…...
C++:反向迭代器的实现
反向迭代器的实现与 stack 、queue 相似,是通过适配器模式实现的。通过传入不同类型的迭代器来实现其反向迭代器。 正向迭代器中,begin() 指向第一个位置,end() 指向最后一个位置的下一个位置。 代码实现: template<class I…...
webGL入门教程_04vec3、vec4 和齐次坐标总结
vec3、vec4 和齐次坐标总结 1. vec3 和 vec4 1.1 什么是 vec3 和 vec4? vec3: GLSL 中的三维向量类型,包含 3 个浮点数:(x, y, z)。常用于表示三维坐标、RGB 颜色、法线、方向等。 vec4: GLSL 中的四维向量类型&…...
uniapp中父组件数组更新后与页面渲染数组不一致实战记录
简单描述一下业务场景方便理解: 商品设置功能,支持添加多组商品(点击添加按钮进行增加).可以对任意商品进行删除(点击减少按钮对选中的商品设置进行删除). 问题: 正常添加操作后,对已添加的任意商品删除后,控制台打印数组正常.但是与页面显示不一致.已上图为例,选中尾…...
优化 Conda 下载速度:详细的代理配置和网络管理策略
优化 Conda 下载速度:详细的代理配置和网络管理策略 为了彻底解决使用 Conda 下载 PyTorch 时遇到的速度问题,并确保下载过程稳定可靠,这需要一个详细、综合的技术方案。让我们更深入地分析问题原因,然后详尽地解释采取的解决策略…...
服务器遭受DDoS攻击后如何恢复运行?
当服务器遭受 DDoS(分布式拒绝服务)攻击 后,恢复运行需要快速采取应急措施来缓解攻击影响,并在恢复后加强防护以减少未来攻击的风险。以下是详细的分步指南: 一、应急处理步骤 1. 确认服务器是否正在遭受 DDoS 攻击 …...
MFC音视频播放器-支持电子放大等功能
前言 本播放器在VS2019下开发,使用ffmpegD3D实现视频播放渲染功能。同时本播放器支持录像功能、截图功能、音视频播放功能、码流信息显示、电子放大功能等。D3D的渲染同时支持surface和texture两种方式,电子放大功能是在D3D Texture方式下进行实现。以下…...
c语言编程1.17蓝桥杯历届试题-回文数字
题目描述 观察数字:12321,123321 都有一个共同的特征,无论从左到右读还是从右向左读,都是相同的。这样的数字叫做:回文数字。 本题要求你找到一些5位或6位的十进制数字。满足如下要求: 该数字的各个数位之…...
el-table 纵向 横向 多级表头
<el-table :data"tableData" class"diaTable":span-method"handleSpanMethod"border:header-cell-style"{background:#292929,color:#fff}"><!-- 纵向表头 --><el-table-column label"纵向表头" width"…...
uniapp开发微信小程序笔记8-uniapp使用vant框架
前言:其实用uni-app开发微信小程序的首选不应该是vant,因为vant没有专门给uni-app设置专栏,可以看到目前Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本,并由社区团队维护 React 版本和支付宝小程序版本。 但是vant的优…...
分布式项目使用Redis实现数据库对象自增主键ID
hello。大家好,我是灰小猿,一个超会写bug的程序猿! 在分布式项目中,数据表的主键ID一般可能存在于UUID或自增ID这两种形式,UUID好理解而且实现起来也最容易,但是缺点就是数据表中的主键ID是32位的字符串&a…...
npm-运行项目报错:A complete log of this run can be found .......npm-cache_logs\
1.问题 没有找到对应的某种依赖,node_modules出现问题。 2.解决 (1)查看对应依赖是否引入或者是由于合并分支错误 引入js或依赖不存在。谨慎删除依赖包 (2)查找对应引入依赖进行安装最后解决方法-删除依赖包清除缓存 npm cache clean --force (2)重新向同事引入…...
SolarCube: 高分辨率太阳辐照预测基准数据集
太阳能作为清洁能源在减缓气候变化中的作用日益凸显,其稳定的供应对电网管理至关重要。然而,太阳辐照受云层和天气变化的影响波动较大,给光伏电力的管理带来挑战,尤其是在调度、储能和备用系统管理方面。因此,精确的太…...
华为小米苹果三星移动设备访问windows共享文件夹windows11
如果移动设备和windows电脑都在同一个局域网内,可以用移动设备访问windows11的共享文件夹 1、设置共享文件夹 2、添加everyone用户即可 3、查看ip地址 4、在华为手机上点击文件管理,里面有个网上邻居 5、正常情况下,华为手机会扫描到同一局域…...
网络安全三防指南:只防病毒不安全
5月17日,瑞星全球反病毒监测网截获一个恶性病毒,由于该病毒的破坏能力和当年著名的CIH病毒几乎完全一样,因此瑞星将该病毒命名为“新CIH”病毒。被“新CIH”感染的电脑,主板和硬盘数据将被破坏,致使电脑无法启动&#…...
论文概览 |《Urban Analytics and City Science》2023.05 Vol.50 Issue.4
本次给大家整理的是《Environment and Planning B: Urban Analytics and City Science》杂志2023年5月第50卷第4期的论文的题目和摘要,一共包括19篇SCI论文! 论文1 Data analytics and sustainable urban development in global cities 全球城市的数据…...
【ROS2】ROS2 C++版本 与 Python版本比较
ROS 系列学习教程(总目录) ROS2 系列学习教程(总目录) 目录 一、功能包的构建方式二、功能包组织结构三、代码编写四、性能与效率五、兼容性六、应用场景 目前ROS开发主要使用 C 和 Python 语言,这里会分别实现并讲解。 相较于ROS1,ROS2的 C 和 Python …...
物联网射频识别和RFID开发(一):RFID基础—概念、应用
一、RFID的发展历史 二、RFID与物联网 (一)物联网与RFID的关系 物联网的基本思想是美国麻省理工学院在1999年提出的,其核心思想是为全球每个物品提供唯一的电子标识符。这种电子标识符就是现在经常提到的“电子产品编码(Electronic Product …...
JVM:即时编译器,C2 Compiler,堆外内存排查
1,即时编译器 1.1,基本概念 常见的编译型语言如C,通常会把代码直接编译成CPU所能理解的机器码来运行。而Java为了实现“一次编译,处处运行”的特性,把编译的过程分成两部分,首先它会先由javac编译成通用的…...
高港区住房和城乡建设局网站/厦门seo网站排名优化
Webpack 简介 什么是 Webpack? webpack是一种前端资源构建工具,一个静态模块打包器在webpack看来,前端所有的资源文件都会作为模块处理它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)’ Webpack 五个核心…...
网站开发的成品/域名注册阿里云
希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入…...
soho在哪里做网站/产品网络营销策划
JavaScript,DOM操作表格 学习要点: 1.操作表格 DOM在操作生成HTML上,还是比较简明的。不过,由于浏览器总是存在兼容和陷阱,导致最终的操作就不是那么简单方便了。本章主要了解一下DOM操作表格和样式的一些知识。 一&am…...
网站网络投票建设模板/关键词挖掘站长工具
盗链就是在用户向网站a请求网站资源时,网站a将网站资源的路径填写为b网站资源的地址,用户将直接看到网站a上显示着网站b的资源,从而造成盗链。 要防止盗链,就要用到处理管道中的技术 在相应的模块类中: void app_Begin…...
保定手机网站制作/病毒式营销的案例
HQChart使用教程74-使用快速创建数字币深度图深度图效果图demo例子demo地址代码Option项说明TypeSymbolIsAutoUpdateAutoUpdateFrequencyBorderMaxVolRateCorssCursorInfoHPenTypeVPenTypeIsShowTooltipFrameSplitCountXSplitCountIsShowLeftTextIsShowRightTextXLineTypeYLine…...
商城网站建设讯息/国内疫情最新情况
获取txt文本文档的编码类型(c,c#) http://blog.csdn.net/xt_chaoji/article/details/7345052 C/C文本文件件编码格式http://blog.csdn.net/afjafjafj2008/article/details/6620617...