0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Pythonのimshow()と同様の可視化をJavaScriptで行う

Posted at

背景

  • 空間的な温度分布や白黒画像のピクセル配列などのように、二次元配列を画像として可視化したい場合がある。
  • Pythonではmatplotlib.pyplot.imshow()を使えば良いが、JavaScriptでブラウザ上に可視化したい

1. Reactを使う場合

1.1. 実装

可視化したい配列とカラースケールをpropsとして与えることで描画を行うコンポーネントを実装する。内部ではcanvasのImageDataオブジェクトを利用してピクセルを操作している。

Imshow.jsx
import React from "react";
import * as d3 from "d3";


export default class Imshow extends React.Component {
    componentDidMount() {
        this.imshow();
    }

    componentDidUpdate(prevProps) {
        if ( (this.props.data!==prevProps.data) || (this.props.interpolate!==prevProps.interpolate) ) {
            this.imshow();
        }
    }

    imshow = () => {
        const canvas = this.refs.canvas;

        // Square only
        const resolution = Math.sqrt(this.props.data.length);
        ["width", "height"].forEach(a => canvas.setAttribute(a, resolution));

        const context = canvas.getContext("2d");
        const imageData = context.createImageData(resolution, resolution);

        this.props.data.forEach((d, i) => {
            let color = isNaN(d) ? {r: 0, g: 0, b: 0} : d3.color(this.props.interpolate(d));
            imageData.data[i*4  ] = color.r;
            imageData.data[i*4+1] = color.g;
            imageData.data[i*4+2] = color.b;
            imageData.data[i*4+3] = 255;
        });
        context.putImageData(imageData, 0, 0);
    }

    render() {
        return (
            <canvas style={{ width: "100%", height: "100%" }} ref="canvas" />
        );
    }
}

1.2. 例

複素対数関数のDomain Coloring富士山の標高に利用すると以下のようになる。

スクリーンショット 2018-11-14 20.54.03.png スクリーンショット 2018-11-14 21.05.43.png

ソースコードはGitHubにある(複素対数関数, 富士山)が、データさえ用意できれば以下のような感じで使える。

<Imshow data={this.state.imshowData} interpolate={this.state.colorScale}/>

1.3. 注意点

上記の実装では、

  • 可視化する配列props.dataは一次元配列で、正方形の可視化に限る(従って要素数は自然数の二乗である前提)
    • 二次元配列dを可視化したければ[].concat.apply([], d)で 一次元に変換できる
  • 配列のshapeと画面上のピクセル数は独立に設定できる
    • width, heightを100%に設定しているため、画面上のピクセル数は親要素によって規定される
    • 画面上のピクセル数に対して配列が小さければ当然解像度は低くなる
  • カラースケールprops.interpolateは、props.dataの値を色に変換する関数
    • d3.jsのカラースケールを使うのが簡単だが、これは引数が0-1になっていることを前提としているので適宜スケールを調整する

という点に注意。拡張が必要であれば簡単に実装できるはず。

2. Reactを使わない場合

要するにcanvas要素のピクセル値を指定しているだけなので、「Reactを使う場合」のimshow()内とほぼ同じ。ソースコードは省略するが、this.props.***を変数に置き換えたり、this.refs.canvasdocument.getElementBy***のようにしたりすれば良いと思う。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?