簡體   English   中英

在node.js或瀏覽器中為Tensorflow.js使用自定義圖像

[英]Using custom images for Tensorflow.js in node.js or browser

Tensorflow.js cnn示例很好,我決定使用我的自定義角色圖像進行訓練(像這樣的本地圖像 imgur 也可用作瀏覽器的img元素)。 但是,我無法復制測試,因為示例代碼使用預處理的數據圖像。

我復制了此處的示例( https://github.com/tensorflow/tfjs-examples/blob/master/mnist-node/README.md ),並添加了必需的node js包。 該示例成功運行。 但是我意識到我無法更改示例所使用的數據,因為它會加載如下所示的預處理數據。

const BASE_URL = 'https://storage.googleapis.com/cvdf-datasets/mnist/';
const TRAIN_IMAGES_FILE = 'train-images-idx3-ubyte';
const TRAIN_LABELS_FILE = 'train-labels-idx1-ubyte';
const TEST_IMAGES_FILE = 't10k-images-idx3-ubyte';
const TEST_LABELS_FILE = 't10k-labels-idx1-ubyte';

我用MNIST(28 * 28)制作了相同格式的圖像,所以我以為我可以更改訓練和測試數據,但是失敗了,因為我不知道idx3-ubyte格式是什么。 data.js文件的URL在此處

如何生成相同的ubyte文件? 或如何直接使用本地圖像或img元素?

更新后,我檢查了data.js文件的閱讀部分,並設法生成了相同的文件格式。 它還具有標頭值。

 async function loadImages(filename) { const buffer = await fetchOnceAndSaveToDiskWithBuffer(filename); const headerBytes = IMAGE_HEADER_BYTES; const recordBytes = IMAGE_HEIGHT * IMAGE_WIDTH; const headerValues = loadHeaderValues(buffer, headerBytes); assert.equal(headerValues[0], IMAGE_HEADER_MAGIC_NUM); assert.equal(headerValues[2], IMAGE_HEIGHT); assert.equal(headerValues[3], IMAGE_WIDTH); const images = []; let index = headerBytes; while (index < buffer.byteLength) { const array = new Float32Array(recordBytes); for (let i = 0; i < recordBytes; i++) { // Normalize the pixel values into the 0-1 interval, from // the original 0-255 interval. array[i] = buffer.readUInt8(index++) / 255; } images.push(array); } assert.equal(images.length, headerValues[1]); return images; } async function loadLabels(filename) { const buffer = await fetchOnceAndSaveToDiskWithBuffer(filename); const headerBytes = LABEL_HEADER_BYTES; const recordBytes = LABEL_RECORD_BYTE; const headerValues = loadHeaderValues(buffer, headerBytes); assert.equal(headerValues[0], LABEL_HEADER_MAGIC_NUM); const labels = []; let index = headerBytes; while (index < buffer.byteLength) { const array = new Int32Array(recordBytes); for (let i = 0; i < recordBytes; i++) { array[i] = buffer.readUInt8(index++); } labels.push(array); } assert.equal(labels.length, headerValues[1]); return labels; } getData_(isTrainingData) { let imagesIndex; let labelsIndex; if (isTrainingData) { imagesIndex = 0; labelsIndex = 1; } else { imagesIndex = 2; labelsIndex = 3; } const size = this.dataset[imagesIndex].length; tf.util.assert( this.dataset[labelsIndex].length === size, `Mismatch in the number of images (${size}) and ` + `the number of labels (${this.dataset[labelsIndex].length})`); // Only create one big array to hold batch of images. const imagesShape = [size, IMAGE_HEIGHT, IMAGE_WIDTH, 1]; const images = new Float32Array(tf.util.sizeFromShape(imagesShape)); const labels = new Int32Array(tf.util.sizeFromShape([size, 1])); let imageOffset = 0; let labelOffset = 0; for (let i = 0; i < size; ++i) { images.set(this.dataset[imagesIndex][i], imageOffset); labels.set(this.dataset[labelsIndex][i], labelOffset); imageOffset += IMAGE_FLAT_SIZE; labelOffset += 1; } return { images: tf.tensor4d(images, imagesShape), labels: tf.oneHot(tf.tensor1d(labels, 'int32'), LABEL_FLAT_SIZE).toFloat() }; } } 

下面是生成器代碼。

 const {createCanvas, loadImage} = require('canvas'); const tf = require('@tensorflow/tfjs'); require('@tensorflow/tfjs-node'); const fs = require('fs'); const util = require('util'); // const writeFile = util.promisify(fs.writeFile); // const readFile = util.promisify(fs.readFile); (async()=>{ const canvas = createCanvas(28,28); const ctx = canvas.getContext('2d'); const ch1 = await loadImage('./u.png'); const ch2 = await loadImage('./q.png'); const ch3 = await loadImage('./r.png'); const ch4 = await loadImage('./c.png'); const ch5 = await loadImage('./z.png'); console.log(ch1); ctx.drawImage(ch1, 0, 0); const ch1Data = tf.fromPixels(canvas, 1); ctx.drawImage(ch2, 0, 0); const ch2Data = tf.fromPixels(canvas, 1); ctx.drawImage(ch3, 0, 0); const ch3Data = tf.fromPixels(canvas, 1); ctx.drawImage(ch4, 0, 0); const ch4Data = tf.fromPixels(canvas, 1); ctx.drawImage(ch5, 0, 0); const ch5Data = tf.fromPixels(canvas, 1); // console.log(await ch1Data.data()); const b1 = Buffer.from(await ch1Data.data()); const b2 = Buffer.from(await ch2Data.data()); const b3 = Buffer.from(await ch3Data.data()); const b4 = Buffer.from(await ch4Data.data()); const b5 = Buffer.from(await ch5Data.data()); const buffers = [b1,b2,b3,b4,b5]; const labels = [0,1,3,2,4,0,1,2,1,0,3,0,2,3,4,0,]; const Images = []; const size = labels.length; for(var i = 0; i < size;i++){ Images.push(buffers[labels[i]]); } const imageHeaderBytes = 16; const imageRecordBytes = 28 * 28; const labelHeaderBytes = 8; const labelRecordBytes = 1; let imageBuffer = Buffer.alloc(imageHeaderBytes + size * imageRecordBytes); let labelBuffer = Buffer.alloc(labelHeaderBytes + size * labelRecordBytes); const imageHeaderValues = [2051, size, 28, 28]; const labelHeaderValues = [2049, size]; for (let i = 0; i < 4; i++) { // Header data is stored in-order (aka big-endian) imageBuffer.writeUInt32BE(imageHeaderValues[i], i * 4); } for (let i = 0; i < 2; i++) { // Header data is stored in-order (aka big-endian) labelBuffer.writeUInt32BE(labelHeaderValues[i], i * 4); } let imageindex = imageHeaderBytes; let labelindex = labelHeaderBytes; for(let i = 0; i < size; i++){ // imageBuffer = Buffer.concat([imageBuffer, Images[i]]); // labelBuffer= Buffer.concat([labelBuffer, Buffer.from([labels[i]])]); // labelBuffer= Buffer.concat([labelBuffer, Buffer.from([labels[i]])]); const image = Images[i]; let index = 0; while(index < image.byteLength){ imageBuffer.writeUInt8(image[index], imageindex); index++; imageindex++; } labelBuffer.writeUInt8(labels[i], labelindex++); } fs.writeFileSync('./testGeneratedImageBuffer', imageBuffer); fs.writeFileSync('./testGeneratedLabelBuffer', labelBuffer); })(); 

“ ubyte”代表“無符號字節”。 它指的是無符號的8位整數。 兩個映像 -ubyte *文件中的每個文件都包含一系列無符號的8位整數。 每個整數都是MNIST圖像中的一個像素,其值> = 0和<= 255。

這就是在像素級別上表示圖像的方式。 現在,讓我們看一下由28行和28列組成的整個圖像的級別。 需要28 * 28 = 784這樣的整數來表示圖像。 在文件中,它們的組織方式使得前28個整數對應於第一行,后28個整數對應於第二行,依此類推。

數據集中的所有圖像都以這種方式表示,並且它們的整數被連接起來以形成圖像 -ubyte文件的內容。 為什么會有兩個這樣的文件? 這是因為train-images-idx3-ubyte是訓練數據集,而t10k-images-idx3-ubyte是測試數據集。

其他兩個文件( 標簽 -ubyte)是MNIST圖像的標簽。 圖像 -ubyte文件一樣,它們包含uint8(即,無符號的8位整數)。 但是標簽文件的值不是> 0到255,而是具有> = 0和<= 9的值,因為MNIST數據集中只有10個圖像類。

希望這很清楚。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM