- 小程序识别ai视觉功能,不能单独使用识别?
当前的识别系统是marker 跟踪配置或者OSD 跟踪配置,都是具有跟踪功能,无法设置单独识别而不跟踪识别的图片平面。因为有些场景生但是识别获取当前识别到的东西后,显示3d模型,另外对模型进行操控,而不强制跟随位置。
2022-11-22 - XRFrame AR模式下,采用Marker识别模式,模型识别成功后,如果让这个模型不再消失呢?
XRFrame AR模式下,采用Marker识别模式,模型识别成功后,如果让这个模型不再消失呢? 通过获取追踪状态,当状态为2时,识别的物体可以展示,但状态为1时,他又会消失掉,无法让识别的物体一直处于显示状态。请问题大佬有没有解决方案?
2023-04-04 - XR-FRAME 使用glb文件 碰撞体识别不了?透明碰撞体被渲染了背景色
xr-asset-load 和 xr-gltf 展示出来的glb场景 glb文件里面的透明碰撞体 全部展示出来了 颜色是光影颜色或者相机背景色
2023-03-07 - canvas安卓Android真机不显示,IOS苹果手机正常显示怎么处理?
[图片][图片] 如上图左IOS,右安卓,canvas生成海报,ISO下是显示,测试机iphone13,ios版本16.2; 安卓手机是红米9A,安卓版本11,安卓手机另一部是华为nova9,安卓版本12.0.1,两部安卓都不显示, 开发者工具是正常显示的,版本库是2.30.0。 代码如下: <!-- 主页面 --> <template> <view class="content"> <!-- 分享弹窗--> <hch-poster v-if="show" ref="hchPoster" @cancel="handleCancel" :posterData.sync="posterData" @previewImage="previewImage" /> </view> </template> <script> import { getwxacodeunlimit } from '../../api/common.js'; import base64src from '../../components/base64Topath.js' //引入base64Topath.js export default { data() { return { show: false, // 海报模板数据 posterData: { poster: { // http://yny-file.oss-cn-shanghai.aliyuncs.com/upload/20221205/a641ce554786c034dd8679e3906cd0b8.png //根据屏幕大小自动生成海报背景大小 // url: 'http://yny-file.oss-cn-shanghai.aliyuncs.com/upload/20221205/9f9d77aa47a406ec016f52bd8c63ee1b.png', //图片地址 url: 'https://file.qimaiziyuanwang.com/qmt/2022/12/15/5927a96ba0734f4c8ab2e8df4c95d099.png', // 求购 r: 10, //圆角半径 w: 312, //海报宽度 h: 496, //海报高度 p: 16 //海报内边距padding }, title: { //商品标题 text: '橘猫卡(一卡多网)', //文本 fontSize: 16, //字体大小 color: '#141414', //颜色 lineHeight: 22, //行高 mt: 43 //margin-top }, content: { //商品标题 text: '三大电信运营商认可的一张一卡多网卡品即将隆重上线。卡品包括三大电三大电商三大电信运营商认可的一张一卡多网卡品即将隆重...', //文本 fontSize: 14, //字体大小 color: '#606266', //颜色 lineHeight: 24, //行高 mt: 79 //margin-top }, mainImg: { //海报主商品图 url: 'https://huangchunhongzz.gitee.io/imgs/poster/product.png', //图片地址 r: 10, //圆角半径 w: 280, //宽度 h: 158, //高度 mt: 185 //margin-top }, codeImg: { //小程序码 url: 'https://huangchunhongzz.gitee.io/imgs/poster/code.png', //图片地址 w: 88, //宽度 h: 88, //高度 mt: 50, //margin-top r: 50, //圆角半径 align: 'right', //对齐方式 }, tips: [ //提示信息 { text: '区域:上海徐汇', //文本 fontSize: 14, //字体大小 color: '#333333', //字体颜色 align: 'left', //对齐方式 lineHeight: 25, //行高 mt: 30 //margin-top }, { text: '时间:2022-09-27', //文本 fontSize: 12, //字体大小 color: '#9196A1', //字体颜色 align: 'left', //对齐方式 lineHeight: 25, //行高 mt: 30 //margin-top } ] } } }, onLoad(option) { if (option.type === '供应') { this.posterData.poster.url = 'https://file.qimaiziyuanwang.com/qmt/2022/12/15/8d20104c83744f3890621434ecfa6727.png'; } if (option.type === '求购') { this.posterData.poster.url = 'https://file.qimaiziyuanwang.com/qmt/2022/12/15/5927a96ba0734f4c8ab2e8df4c95d099.png'; } this.posterData.mainImg.url = option.imgurl; this.posterData.title.text = option.businessTitle; this.posterData.content.text = option.businessContent; this.posterData.tips[0].text = option.citytext; this.posterData.tips[1].text = option.createTime; this.posterData = JSON.parse(JSON.stringify(this.posterData)); this.fetchgetwxacodeunlimit(option.id); }, methods: { fetchgetwxacodeunlimit(id) { // 获取太阳码 getwxacodeunlimit({ "page": "pages/supplydetails/index", "scene": id }).then(response => { if (response.code === 200) { base64src(response.data, resCurrent => { this.posterData.codeImg.url = resCurrent; console.log(this.posterData.codeImg.url) this.show = true; }) } }) }, // 取消海报 handleCancel(val) {}, // h5的情况下,点击海报保存按钮到图片预览海报,可以长按保存 previewImage(base64) { // 预览图片 uni.previewImage({ urls: [base64] }) } } } </script> <style lang="scss"> </style> <!-- ==========================以下是组件hch-poster部分========================================================== --> <template> <view class="canvas-content" v-show="canvasShow" :style="'width:' + system.w + 'px; height:' + system.h + 'px;'"> <!-- #ifndef MP-TOUTIAO || MP-BAIDU --> <view class="canvas-tit" @tap="goBack()"> <image src="../../static/image/img/leftimg.png" mode=""></image> <view class="title">企脉圈</view> </view> <!-- #endif --> <!-- 背景层 --> <image class="canvasImg" src="../../static/image/canvasBg.png" mode="widthFix"></image> <!-- 海报 --> <!-- :width="system.w" :height="system.h" 支付宝必须要这样设置宽高才有效果 --> <canvas class="canvas" canvas-id="myCanvas" id="myCanvas" :style="'width:' + system.w + 'px; height:' + system.h + 'px;'" :width="system.w" :height="system.h"></canvas> <view class="button-wrapper"> <!-- 保存海报按钮 --> <!-- #ifndef MP-QQ --> <!-- cover-view 标签qq小程序有问题 --> <cover-view class="save-btn" @tap="handleSaveCanvasImage">保存图片到相册</cover-view> <!-- #endif --> <!-- #ifdef MP-QQ --> <view class="save-btn" @tap="handleSaveCanvasImage">保存图片到相册</view> <!-- #endif --> </view> </view> </template> <script> import { drawSquarePic, drawTextReturnH, getSystem } from './utils' export default { data() { return { system: {}, canvasShow: false } }, props: { posterData: { type: Object, default: () => { return {} } } }, computed: { // 计算海报背景数据 poster() { let data = this.posterData let system = this.system let posterBg = { url: data.poster.url, r: data.poster.r * system.scale, w: data.poster.w * system.scale, h: data.poster.h * system.scale, x: (system.w - data.poster.w * system.scale) / 2, y: (system.h - data.poster.h * system.scale) / 2, p: data.poster.p * system.scale } return posterBg }, // 计算海报标题 title() { let data = this.posterData let system = this.system let posterTitle = data.title posterTitle.x = this.poster.x posterTitle.y = this.poster.y + data.poster.p * system.scale + data.title.mt * system.scale return posterTitle }, // 计算海报内容 content() { let data = this.posterData let system = this.system let posterContent = data.content posterContent.x = this.poster.x posterContent.y = this.poster.y + data.poster.p * system.scale + data.content.mt * system.scale return posterContent }, // 计算海报头部主图 mainImg() { let data = this.posterData let system = this.system let posterMain = { url: data.mainImg.url, r: data.mainImg.r * system.scale, w: data.mainImg.w * system.scale, h: data.mainImg.h * system.scale, x: (system.w - data.mainImg.w * system.scale) / 2, y: this.poster.y + data.poster.p * system.scale + data.mainImg.mt * system.scale } return posterMain }, // 计算小程序码 codeImg() { let data = this.posterData let system = this.system let posterCode = { url: data.codeImg.url, r: data.codeImg.r * system.scale, w: data.codeImg.w * system.scale, h: data.codeImg.h * system.scale, x: (system.w - ((data.poster.w * system.scale) / 2)) + data.poster.p * system.scale, y: this.mainImg.y + data.poster.p * system.scale + data.mainImg.mt * system.scale } return posterCode }, }, created() { // 获取设备信息 this.system = getSystem() }, mounted() { var t = setTimeout(() => { this.creatPoster() clearTimeout(t); }, 2000) }, methods: { goBack() { uni.navigateBack({ delta: 1 }); }, // 展示海报 // posterShow() { // this.canvasShow = true // this.creatPoster() // }, // 生成海报 async creatPoster() { uni.showLoading({ title: '生成海报中...' }) const ctx = uni.createCanvasContext('myCanvas', this) this.ctx = ctx ctx.clearRect(0, 0, this.system.w, this.system.h) //清空之前的海报 ctx.draw() //清空之前的海报 // 根据设备屏幕大小和距离屏幕上下左右距离,及圆角绘制背景 let poster = this.poster let title = this.title let content = this.content let mainImg = this.mainImg let codeImg = this.codeImg await drawSquarePic(ctx, poster.x, poster.y, poster.w, poster.h, poster.r, poster.url) await drawSquarePic(ctx, mainImg.x, mainImg.y, mainImg.w, mainImg.h, mainImg.r, mainImg.url) // 绘制标题 textY 绘制文本的y位置 console.log('creatPoster -> title.x', title.x) let textY = drawTextReturnH(ctx, title.text, title.x, title.y, mainImg.w, title.fontSize, title.color, title.lineHeight, ) // 绘制内容contentY绘制文本的y位置 let contentY = drawTextReturnH(ctx, content.text, content.x, content.y, mainImg.w, content.fontSize, content.color, content.lineHeight) // 绘制小程序码 await drawSquarePic(ctx, codeImg.x, codeImg.y, codeImg.w, codeImg.h, codeImg.r, codeImg.url, codeImg .mt, ) // 小程序的名称 // 长按/扫描识别查看商品 let y = 0 this.posterData.tips.forEach((element, i) => { if (i == 0) { y = codeImg.y + element.mt * this.system.scale } else { y += element.mt } y = drawTextReturnH(ctx, element.text, title.x, y, mainImg.w, element.fontSize, element .color, element.lineHeight, element.align) }) this.canvasShow = true uni.hideLoading() }, // 保存到系统相册 handleSaveCanvasImage() { uni.showLoading({ title: '保存中...' }) let _this = this // 把画布转化成临时文件 // #ifndef MP-ALIPAY // 支付宝小程序外,其他都是用这个方法 canvasToTempFilePath uni.canvasToTempFilePath({ x: this.poster.x, y: this.poster.y, width: this.poster.w, // 画布的宽 height: this.poster.h, // 画布的高 destWidth: this.poster.w * 5, destHeight: this.poster.h * 5, canvasId: 'myCanvas', success(res) { //保存图片至相册 // #ifndef H5 // 除了h5以外的其他端 uni.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success(res) { uni.hideLoading() uni.showToast({ title: '图片保存成功,可以去分享啦~', duration: 2000, icon: 'none' }) }, fail() { uni.showToast({ title: '保存失败,稍后再试', duration: 2000, icon: 'none' }) uni.hideLoading() } }) // #endif // #ifdef H5 // h5的时候 uni.showToast({ title: '请长按保存', duration: 3000, icon: 'none' }) _this.$emit('previewImage', res.tempFilePath) // #endif }, fail(res) { console.log('fail -> res', res) uni.showToast({ title: '保存失败,稍后再试', duration: 2000, icon: 'none' }) uni.hideLoading() } }, this) // #endif // #ifdef MP-ALIPAY // 支付宝小程序条件下 toTempFilePath this.ctx.toTempFilePath({ x: this.poster.x, y: this.poster.y, width: this.poster.w, // 画布的宽 height: this.poster.h, // 画布的高 destWidth: this.poster.w * 5, destHeight: this.poster.h * 5, success(res) { //保存图片至相册 my.saveImage({ url: res.apFilePath, showActionSheet: true, success(res) { uni.hideLoading() uni.showToast({ title: '图片保存成功,可以去分享啦~', duration: 2000, icon: 'none' }) }, fail() { uni.showToast({ title: '保存失败,稍后再试', duration: 2000, icon: 'none' }) uni.hideLoading() } }) }, fail(res) { console.log('fail -> res', res) uni.showToast({ title: '保存失败,稍后再试', duration: 2000, icon: 'none' }) uni.hideLoading() } }, this) // #endif }, } } </script> <style lang="scss"> .canvas-content { height: 100vh; overflow: hidden; position: relative; .canvasImg { height: 100%; width: 100%; position: absolute; z-index: -1; left: 0; top: 0 } .canvas-tit { position: absolute; font-size: 32rpx; font-weight: 400; height: 88rpx; color: #FFFFFF; display: flex; align-items: center; top: 70rpx; left: 40rpx; z-index: 10; image { width: 20rpx; height: 20rpx; } .title { margin-left: 268rpx; } } .canvas {} .button-wrapper { width: 624rpx; margin: 0 63rpx; position: fixed; bottom: 20rpx; } .save-btn { height: 88rpx; line-height: 88rpx; text-align: center; background: linear-gradient(180deg, #FFEFB4 0%, #F9C270 100%); box-shadow: 0rpx 3rpx 6rpx rgba(0, 0, 0, 0.16); opacity: 1; color: #472B00; font-weight: bold; font-size: 28rpx; border-radius: 44rpx; } } </style> <!-- ==========================以下是工具utils文件========================================================== --> /* * @Description: 公共方法 * @Version: 1.0.0 * @Autor: hch * @Date: 2021-07-22 00:01:09 */ /** * @description: 绘制正方形(可以定义圆角),并且有图片地址的话填充图片 * @param {CanvasContext} ctx canvas上下文 * @param {number} x 圆角矩形选区的左上角 x坐标 * @param {number} y 圆角矩形选区的左上角 y坐标 * @param {number} w 圆角矩形选区的宽度 * @param {number} h 圆角矩形选区的高度 * @param {number} r 圆角的半径 * @param {String} url 图片的url地址 */ export function drawSquarePic(ctx, x, y, w, h, r, url) { ctx.save() ctx.beginPath() // 绘制左上角圆弧 ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5) // 绘制border-top // 画一条线 x终点、y终点 ctx.lineTo(x + w - r, y) // 绘制右上角圆弧 ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2) // 绘制border-right ctx.lineTo(x + w, y + h - r) // 绘制右下角圆弧 ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5) // 绘制左下角圆弧 ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI) // 绘制border-left ctx.lineTo(x, y + r) // 填充颜色(需要可以自行修改) // #ifndef MP-TOUTIAO ctx.setFillStyle('transparent') // #endif // #ifdef MP-TOUTIAO ctx.setFillStyle('#5E92EF') // #endif ctx.fill() // 剪切,剪切之后的绘画绘制剪切区域内进行,需要save与restore 这个很重要 不然没办法保存 ctx.clip() // 绘制图片 return new Promise((resolve, reject) => { if (url) { wx.getImageInfo({ src: url, success(res) { ctx.drawImage(res.path, x, y, w, h) ctx.restore() //恢复之前被切割的canvas,否则切割之外的就没办法用 ctx.draw(true) resolve() }, fail(res) { console.log('fail -> res', res) uni.showToast({ title: '图片下载异常', duration: 2000, icon: 'none' }) } }) } else { ctx.draw(true) resolve() } }) } /** * @description: 获取设备信息 * @param {type} * @return {type} * @author: hch */ export function getSystem() { let system = wx.getSystemInfoSync() let scale = system.windowWidth / 375 //按照苹果留 375*667比例 其他型号手机等比例缩放 显示 return { w: system.windowWidth, h: system.windowHeight, scale: scale } } /** * @description: 绘制文本时文本的总体高度 * @param {Object} ctx canvas上下文 * @param {String} text 需要输入的文本 * @param {Number} x X轴起始位置 * @param {Number} y Y轴起始位置 * @param {Number} maxWidth 单行最大宽度 * @param {Number} fontSize 字体大小 * @param {String} color 字体颜色 * @param {Number} lineHeight 行高 * @param {String} textAlign 字体对齐方式 */ export function drawTextReturnH( ctx, text, x, y, maxWidth = 375, fontSize = 14, color = '#000', lineHeight = 30, textAlign = 'left' ) { if (textAlign) { ctx.setTextAlign(textAlign) //设置文本的水平对齐方式 ctx.setTextAlign这个可以兼容百度小程序 ,注意:ctx.textAlign百度小程序有问题 switch (textAlign) { case 'center': x = getSystem().w / 2 break case 'right': x = (getSystem().w - maxWidth) / 2 + maxWidth break default: // 左对齐 x = (getSystem().w - maxWidth) / 2 break } } let arrText = text.split('') let line = '' for (let n = 0; n < arrText.length; n++) { let testLine = line + arrText[n] ctx.font = fontSize + 'px sans-serif' //设置字体大小,注意:百度小程序 用ctx.setFontSize设置字体大小后,计算字体宽度会无效 ctx.setFillStyle(color) //设置字体颜色 let metrics = ctx.measureText(testLine) //measureText() 方法返回包含一个对象,该对象包含以像素计的指定字体宽度。 let testWidth = metrics.width if (testWidth > maxWidth && n > 0) { ctx.fillText(line, x, y) line = arrText[n] y += lineHeight } else { line = testLine } } ctx.fillText(line, x, y) ctx.draw(true) //本次绘制是否接着上一次绘制。即 reserve 参数为 false,则在本次调用绘制之前 native 层会先清空画布再继续绘制;若 reserve 参数为 true,则保留当前画布上的内容,本次调用 drawCanvas 绘制的内容覆盖在上面,默认 false。 return y }
2023-02-14 - 小程序实现xr-frame 2DMarker+视频 区域初始是白色幕布一会才出视频等诸多问题怎么办?
小程序实现xr-frame 2DMarker+视频,让照片动起来 图片区域初始是白色幕布,一会才出视频,而且视频切换的时候是绿色幕布,很影响美观,有什么方法吗?而且iphone14只能播放一遍,不能重复播放视频。几乎所有荣耀手机直接闪退
2023-02-10 - VideoDecoder.getFrameData() 解码数据不是每次都能get成功
VideoDecoder.getFrameData() 获取视频解码数据 有的视频能正常解码直至结束 有的视频解码一段后getFrameData获取到的数据为空 请问对视频有什么要求吗 编码 码率 分辨率什么的
2023-01-03 - VisionKit AR 模型使用OrbitControls旋转的问题?
RT, 在官方demo(visionkit-basic)中参考threejs demo引入了orbit.js 但是引入并加入相关代码后没有效果。调试了很久 发现three的相机是被AR的摄像头接管了 所以threejs中无法操作相机视角,尝试把 this.camera.matrixAutoUpdate = false 屏蔽后可以旋转 但不能缩放并且与AR相机的视角有冲突。求一个AR中能旋转3D模型的方案!
2022-10-14 - AR功能使用three的TextureLoader加载的纹理贴图导致画面无限镜像闪烁?
使用AR功能时,加载了自定义的纹理贴图,在识别后导致摄像头画面无限镜像闪烁,去掉后一切正常,其它代码没有贴出来,同官方示例相同,唯一区别在于官方示例展示一个小机器人,问题代码想要展示两个平面贴图,而且两个贴图感觉也很怪异,不是一起动 const plane = new THREE.PlaneGeometry(10, 10) const texture = new THREE.TextureLoader().load("/static/ar-js/a.png"); const planeMaterial = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide }) texture.minFilter = THREE.LinearFilter const mesh = new THREE.Mesh(plane, planeMaterial) const plane2 = new THREE.PlaneGeometry(10, 10) const texture2 = new THREE.TextureLoader().load("/static/ar-js/abc.jpg"); const planeMaterial2 = new THREE.MeshBasicMaterial({ map: texture2, side: THREE.DoubleSide }) texture2.minFilter = THREE.LinearFilter const mesh2 = new THREE.Mesh(plane2, planeMaterial2) mesh2.position.set(0, 0, .6) const g = new THREE.Group(); g.rotateX(Math.PI / 2) g.add(mesh) g.add(mesh2) scene.add(g)
2022-09-06 - AR问题跟踪与定位2D目标图像后,如何将官方demo示例里的模型替换为视频与识别的模板图像进行贴合?
AR问题:跟踪与定位2D目标图像后,如何将官方demo示例里的模型替换为视频,与识别的模板图像进行贴合。https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/visionkit/marker.html
2022-08-09