赞
踩
npm i -S @tensorflow/tfjs
// main.js 入口文件
import Vue from 'vue'
Vue.config.productionTip = false
const tf = require("@tensorflow/tfjs")
Vue.prototype.$tf = tf;
<template> <view class="content"> <image class="logo" src="/static/logo.png"></image> <view class="text-area"> <text class="title">Tensorflow.js Version: {{msg}}</text> </view> </view> </template> <script> export default { data() { return { title: 'Hello', msg: this.$tf.version["tfjs"] } }, onLoad() { }, methods: { } } </script> <style> .content { display: flex; flex-direction: column; align-items: center; justify-content: center; } .logo { height: 200rpx; width: 200rpx; margin-top: 200rpx; margin-left: auto; margin-right: auto; margin-bottom: 50rpx; } .text-area { display: flex; justify-content: center; } .title { font-size: 36rpx; color: #8f8f94; } </style>
在HTML
端程序完成了训练与推理,但是在Android
端训练时model.fit
抛出了Cannot read property 'now' of undefined
,暂未找到问题源头;Android
端推理正常进行。
另外一个HTML
端和Android
端的diff是HTML
端有fetch
这个函数,而Android
端没有,目前采用uni.request
替代,可以考虑通过unil.request
封装出一个与fetch
兼容的函数,通过fetchFunc
传进模型加载函数里。
加载预训练模型上,也是因为fetch
的原因不能实现模型的加载,但是可以自己实现一个fetchFunc
传进httpRouter
的构造函数里。
另外,为了发挥uni-app
原生的优势,最好是从本地,甚至是从安装包里加载模型。目前的一个想法是:将预训练模型用base64
编码以后保存为json
格式,以如下的方式读取:
let mapDataCollection = require('@/static/mapData/guizhou.json');
console.log("cityJson: " + JSON.stringify(cityJson));
//=>cityJson: [{"name":"基础底图","isDown":true,"isZip":false,"isDowning":false,"update":false},...,{"name":"沿河县","isDown":false,"isZip":false,"isDowning":false,"update":false}]
H5
端可以引入jQuery
,用AJAX
读取服务器上的json
文件。
$.getJSON('../static/mapData/guizhou.json').then(mapdata=> {
console.log("cityJson: " + JSON.stringify(cityJson));
})
//=>cityJson: [{"name":"基础底图","isDown":true,"isZip":false,"isDowning":false,"update":false},...,{"name":"沿河县","isDown":false,"isZip":false,"isDowning":false,"update":false}]
可以在js
文件将任意js
对象用export
关键字导出,在需要的页面用import
或require
进行导入,import
无法导入json
文件1。
//js数据文件
let cityJson = [{"name":"基础底图","isDown":true,"isZip":false,"isDowning":false,"update":false},...,{"name":"沿河县","isDown":false,"isZip":false,"isDowning":false,"update":false}]
export {
cityJson
}
//业务页面
import {cityJson} from '@/static/mapData/guizhou.js'
但是上述require
法又将引入一个内存占用大、加载时间长的问题:uni-app
会将所有的运行资源打包成一个大号的js
脚本,在uni-app
的运行时环境中运行。如果我们把base64
编码的深度学习的模型打包进去,主程序js
文件少则几十兆多则数百兆,这对手机是一个很大的挑战。至于结果,我还没进行测试,估计稍大的模型不会太理想。
或许还有一种第一次运行下载模型的方法。做起来也简单,启动时使用uni.uni.getSavedFileList
看是否已经下载过,若没有首先uni.downloadFile
下载模型拓扑结构和权重到临时路径,接着uni.saveFile
保存。最后加载权重就可以啦。
上述两种方法都离不开要自己写一个TensorFlow.js
的IOHandler
。只是实现一个load
和一个save
接口,问题不大,核心是给返回一个有modelTopylogy
、weightSpecs
和weightData
的ModelArtifacts
对象,照葫芦画瓢问题不大,更何况TensorFlow.js
的开发者们已经把base64StringToArrayBuffer
功能这么贴心地写出来了,多么愉快呀。
关于文件IO2
// -------------------------------------默认的异步操作------------------------------ export function getDirectory(directoryName,successCB){ plus.io.requestFileSystem( plus.io.PRIVATE_DOC, function( fs ) { //directoryName:可以是一个文件名,如果是路径,则路径上的所有文件夹都会自动创建 fs.root.getDirectory(directoryName, {create:true},successCB, function(){} ); console.log("创建完成.............") }, function ( e ) {} ); } export function getFile(filePath,successCB){ plus.io.requestFileSystem( plus.io.PRIVATE_DOC, function( fs ) { //directoryName:可以是一个文件名,如果是路径,则路径上的所有文件夹都会自动创建 fs.root.getFile(filePath, {create:true},successCB, function(){} ); console.log("创建完成.............") }, function ( e ) {} ); } export function moveFile(srcFilePath,srcFileName,dstFilePath,dstFileName,successCB){ plus.io.resolveLocalFileSystemURL( "_documents/b1/bridges.json", function( entry ){ plus.io.resolveLocalFileSystemURL("_doc/", function(root){ /* entry.copyTo( root, "bridges11.json", function( entry ){ console.log("New Path: " + entry.fullPath); }, function( e ){ console.log( "错1误"+JSON.stringify(e) ); } ); */ entry.moveTo( root, "bridges12.json", function( entry ){ console.log("New Path: " + entry.fullPath); }, function( e ){ console.log( "错1误"+JSON.stringify(e) ); } ); }) }) } export function copyFile(srcFilePath,srcFileName,dstFilePath,dstFileName,successCB){ plus.io.resolveLocalFileSystemURL( "_documents/b1/bridges.json", function( entry ){ plus.io.resolveLocalFileSystemURL("_doc/", function(root){ entry.copyTo( root, "bridges11.json", function( entry ){ console.log("New Path: " + entry.fullPath); }, function( e ){ console.log( "错1误"+JSON.stringify(e) ); } ); }) }) } /** * 传入目录dirEntry,如果传了fileName,则删除对应文件,否则目录下所有文件全部删除 * @param {Object} dirEntry * @param {Object} fileName */ export function removeFile(dirEntry, fileName) { plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) { let entry = dirEntry || fs.root; let directoryReader = entry.createReader(); directoryReader.readEntries(function(entries) { for (let i = entries.length - 1; i >= 0; i--) { if (fileName) { if (fileName === entries[i].name) { console.log("删除文件", entries[i].name); entries[i].remove(); } } else { entries[i].remove(); } } }); }); } // ----------------------------------------------------------------同步化-操作----------------------------------------- /** * 同步化获取文件,文件不存在会自动创建 * @param {Object} fileName 可以是文件名,也可以是/路径/文件名 * @param {Object} dirEntry * @return 文件Entry */ export async function getFileEntryAsync(fileName,dirEntry){ console.log("[getFileEntryAsync]开始执行") return new Promise((resolve) => { plus.io.requestFileSystem( plus.io.PRIVATE_DOC, function(fs) { console.log("[getFileEntryAsync]fileName is :" + fileName) let entry = dirEntry || fs.root; entry.getFile( fileName, {create: true}, function(fileEntry) { console.log("[getFileEntryAsync] 执行完成") resolve(fileEntry); },function(ex){console.log(ex)} ); } ); }) } /** * 获取文件夹,不存在会自动创建 * @param {Object} dirName */ export async function getDirEntryAsync(dirName) { return new Promise(async (resolve) => { plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) { fs.root.getDirectory(dirName, { create: true }, function(dirEntry) { resolve(dirEntry); }) }) }) } /** * 获取通过fileEntry获取file,不存在会自动创建 * @param {Object} fileName * @param {Object} dirEntry */ export async function getFileAsync(fileName, dirEntry) { console.log("[getFileAsync]") return new Promise(async (resolve) => { let fileEntry = await getFileEntryAsync(fileName, dirEntry); fileEntry.file(function(file) { resolve(file); }); }) } /** * 读取文件中的内容 * @param {Object} path * @param {Object} dirEntry */ export async function getFileContextAsync(path, dirEntry) { let deffered; let fileReader = new plus.io.FileReader(); fileReader.onloadend = function(evt) { deffered(evt.target); } let file = await getFileAsync(path, dirEntry); fileReader.readAsText(file, 'utf-8'); return new Promise((resolve) => { deffered = resolve; }); } /** * 向文件中写入数据 * @param {Object} path 要写入数据的文件的位置 * @param {Object} fileContext 要写入的内容 * @param {Object} dirEntry 文件夹,可不写使用默认 */ export async function writeContextToFileAsync(path,fileContext, dirEntry) { let fileEntry =await getFileEntryAsync(path); let file =await getFileAsync(path); return new Promise((resolve) => { fileEntry.createWriter( async writer => { // 写入文件成功完成的回调函数 writer.onwrite = e => { console.log("写入数据成功"); resolve() }; // 写入数据 writer.write(JSON.stringify(fileContext)); }) }); } /** * 判断文件是否存在 * @param {Object} fileName * @param {Object} dirEntry */ export async function existFileAsync(fileName, dirEntry){ return new Promise((resolve)=>{ plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) { let entry = dirEntry || fs.root; let directoryReader = entry.createReader(); directoryReader.readEntries(function(entries) { let isExist = entries.some(entry => entry.name === fileName); resolve(isExist); }); }); }) } /** * 遍历dirEntry,深层次的目录暂不考虑 * @param {Object} dirEntry */ export async function iterateDierctory(dirEntry) { return new Promise((resolve) => { plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) { let entry = dirEntry || fs.root; let directoryReader = entry.createReader(); directoryReader.readEntries(function(entries) { entries.forEach((item, idx, arr)=>{ if(idx===0) console.log("---------------"+entry.name+"目录-----------------"); console.log(idx+1, item.name); if(idx===arr.length-1) console.log("---------------end-----------------"); }) resolve(entries); }, function(e) { console.log("Read entries failed: " + e.message); }); }); }) } /* 调用例子 this.DIR_NAME = 'test' fileName = 'test.json' filePath = '_doc/test/test.json' let dirEntry = await this.getDirEntry(this.DIR_NAME); //创建、获取文件夹 let fileEntry = await this.getFileEntry(fileName, dirEntry); // 创建、获取文件 let {result:content} = await this.getFileContext(filePath); // 获取文件的内容 let trajectory = JSON.parse(content||"[]"); trajectory.push({lat, lng}); fileEntry.createWriter(function(writer){ writer.seek(0); writer.write(JSON.stringify(trajectory)); }); */
又或许我们可以参考reneweb/react-native-tensorflow。
JavaScript
我爱一辈子。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。