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
文件将任意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
我爱一辈子。
https://www.jianshu.com/p/7ba2374f26aa ↩︎
https://blog.csdn.net/qq_37746495/article/details/111868938 ↩︎
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)