LoginSignup
4
3

More than 3 years have passed since last update.

ヒートマップ生成高速化の試行錯誤

Last updated at Posted at 2017-08-18

0~255を取る値からヒートマップ(RGB)を算出するプログラムを作っていましたが、
最初に書いたソース(GPU+Cupy)が遅すぎたため、試行錯誤した結果を残します。

※cv2.applyColorMap(grayscale_image,cv2.COLORMAP_JET)で全て解決でしたが、自作してしまいました(恥)。

下記は、画像サイズ320x180に対する処理です。
コードは主要部分のみ載せています。
また、ヒートマップは近似値を求める簡易版(三角関数未使用)です
値の大きさをサーモグラフィのような色に変換するの線形の図)。
簡易版ヒートマップ

GPU+Cupy(for)

元々書いていたコードです。
愚直にforで回して処理する負け組コードです。

    def conv_v_to_heat(v):
        image = cuda.cupy.zeros((v.shape[0], array.v[1], 4))
        for i, w in enumerate(image):
            for j, h in enumerate(w):
                image[i,j,0] = get_heat_r(array[i][j])
                image[i,j,1] = get_heat_g(array[i][j])
                image[i,j,2] = get_heat_b(array[i][j])
                image[i,j,3] = array[i][j] # アルファは適当

    def get_heat_r(v):
        if v <= 127:
            return 0
        elif v <= 190:
            return (v-127)*4
        else:
            return 255
sec: 20.43495798110962

CPU+Numpy(for)

for使うくらいならGPUやめてしまったほうがまだましなのでは?
と思ってCPUに変えました(ソース省略)。
bash
sec: 0.6369609832763672

CPUのほうが全然速かったです。

CPU+Numba+Numpy(for)

Numba入れてみました。

    @jit
    def conv_v_to_heat(v):

    @jit
    def get_heat_r(v):
sec: 0.20061397552490234

更に速くなりました。

CPU+Numba+Numpy(filter)

そもそも、Numpyにforを使う時点で負け組なので、
フィルタリングで対処するようにしました。

    def conv_v_to_heat(v):
       image = np.zeros((v.shape[0], v.shape[1], 4))
        image[:, :, 0] = get_r(array)
        image[:, :, 1] = get_g(array)
        image[:, :, 2] = get_b(array)
        image[:, :, 3] = v

    def get_heat_r(v):
        out = np.zeros((v.shape))
        out[...] = 255
        out[(v<=190)] = (v[(v<=190)]-127)*4
        out[(v<=127)] = 0
        return out
sec: 0.0013210773468017578

圧倒的に速くなりました。

CPU+Numpy(filter)

試しに、Numba外してみます。

sec: 0.001230478286743164

あれ、速くなりました。というか誤差レベルです。

GPU+Cupy(filter)

じゃあGPUは?

sec: 0.008527278900146484

遅くなりました。

まとめ

実装 time(sec)
GPU+Cupy(for) 20.43495798110962
CPU+Numpy(for) 0.63696098327637
CPU+Numba+Numpy(for) 0.20061397552490
CPU+Numba+Numpy(filter) 0.00132107734680
CPU+Numpy(filter) 0.00123047828674
GPU+Cupy(filter) 0.00852727890015

CPU+Numpy(filter)が一番でした。
もっと速い実装はあると思いますが、個人的には満足行く速度になりました。
やっぱ、for使ったら負けすね。

4
3
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
4
3