Home About
Machine Learning , tensorflow

TensorFlow.js で画像操作

テンソルの操作になれるために、TensorFlow.js を使って画像を操作する練習。

環境

$ node -v
v16.15.0

hello-tfjs プロジェクト作成

$ mkdir hello-tfjs
$ cd hello-tfjs
$ npm init -y
$ npm install npm install @tensorflow/tfjs-node

GPU環境がある場合は

$ npm install npm install @tensorflow/tfjs-node-gpu

version 確認

index.js

const tf = require('@tensorflow/tfjs-node');
console.log(tf.version.tfjs);

実行:

$ node index.js 
2022-11-10 20:55:36.565819: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
4.0.0

stderr を捨てる:

$ node index.js 2> /dev/null 
4.0.0

これ本当にエラーが出ていたとき困る。

gopher.png をあれこれする

https://github.com/keygx/Go-gopher-Vector から入手して JPG として保存。

gopher.jpg

この画像(gopher.jpg)をテンソルに変換します。

index.js

const fs = require('fs');
const tf = require('@tensorflow/tfjs-node');

const gopherImage = fs.readFileSync('gopher.jpg');

tf.tidy(()=>{
    const gopherTensor = tf.node.decodeImage(gopherImage);
    console.log(gopherTensor);
    gopherTensor.print();
});

実行:

$ node index.js 2> /dev/null
Tensor {
  kept: false,
  isDisposedInternal: false,
  shape: [ 484, 360, 3 ],
  dtype: 'int32',
  size: 522720,
  strides: [ 1080, 3 ],
  dataId: {},
  id: 2,
  rankType: '3',
  scopeId: 0
}
Tensor
    [[[255, 255, 255],
      [255, 255, 255],
      [255, 255, 255],
      ...,
      [255, 255, 255],
      [255, 255, 255],
      [255, 255, 255]],

     [[255, 255, 255],
      [255, 255, 255],
      [255, 255, 255],
      ...,
      [255, 255, 255],
      [255, 255, 255],
      [255, 255, 255]]]

shape: [ 484, 360, 3 ] と出力されました。 画像サイズ(width x height) 360x484 の RGB であることがわかります。

これを 上限,左右反転して png 保存してみる。

const fs = require('fs');
const tf = require('@tensorflow/tfjs-node');

const exportAsPng = (tensor, filepath)=>{
    const promise = tf.node.encodePng(tensor)
    promise.then((f)=>{
        fs.writeFileSync(filepath, f);
    })
};

const gopherImage = fs.readFileSync('gopher.jpg');

tf.tidy(()=>{
    const gopherTensor = tf.node.decodeImage(gopherImage);

    // 縦方向を反転する.
    const gopherTensor0 = tf.reverse(gopherTensor, 0);
    exportAsPng(gopherTensor0, 'gopher_0.png');

    // 横方向を反転する.
    const gopherTensor1 = tf.reverse(gopherTensor, 1);
    exportAsPng(gopherTensor1, 'gopher_1.png');
});

gophers.png

これおもしろい。 これを使えば、いつもやっている (x,y) 座標の配列を 3x3 の行列をかけてなんかするやつ(並行移動とか回転)の計算もできるんじゃないかな。