@ti.kernel or @ti.pyfunc

‘mat’ is a 1000000*16 Boole Matrix, and I want to convert the matrix to a photo.(1 is white, 0 is black)
There is something wrong when I utilise ‘@ti.kernel’, however, ‘@ti.pyfunc’ is fine. Could u plz tell me the reason? And how to fix it if I want to use ‘@ti.kernel’? Thank you in advance.

import taichi as ti
import tomatrix

ti.init(arch=ti.gpu)

mat=tomatrix.mat
shape = (16, len(mat))
type = ti.u8
pixels = ti.var(dt=type, shape=shape)
#print(mat[0][2])

@ti.kernel
def draw():
    for i in range(len(mat)):
        for j in range (16):
            if mat[i,j] == 1:
                pixels[j,i] = 255    # integars between [0, 255] for ti.u8
            else:
                pixels[j,i] = 0
draw()

ti.imwrite(pixels, f"export.png")

What is tomatrix here? Could you post the source code of tomatrix.py?
If mat is a np.array, then simply ti.imwrite(mat, f"export.png") should work.

I roughly guess the mat here is a Python list:

mat = [[1, 2, ...], ...]

Python list cannot be passed into Taichi kernels directly for now. You’ll need to convert them into numpy.array first:

import taichi as ti  # taichi is a professnional package about computer graphics
import numpy as np  # numpy is a professional package about arrays
import tomatrix  # your tomatrix.py

ti.init(arch=ti.gpu)

mat=np.array(tomatrix.mat)  # assume your `tomatrix.mat` is a Python list
shape = mat.shape  # numpy will automatically compute the shape for you :)
type = ti.u8
pixels = ti.var(dt=type, shape=shape)


@ti.kernel
def draw(m: ti.ext_arr()):  # ti.ext_arr() tells Taichi this is an external array (np.array or torch.Tensor)
    for i, j in pixels:  # same as two for-loops over pixels.shape, only works in @ti.kernel
            if mat[i,j] == 1:
                pixels[i, j] = 255    # IIRC Taichi images are row-major (x, y)
            else:
                pixels[i, j] = 0

draw()

ti.imwrite(pixels, f"export.png")

Thank you for your response. I combine the source code with ‘tomatrix.py’. However, it seems still not work.
Here is my code:

import numpy as np
import taichi as ti

file = open("ext.txt", "r")
fp1 = open("graph.txt", "w")
rl = file.readlines()

n = 0
mat = np.zeros((3 * len(rl), 16), int)

dic = {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5, '7': 6, '8': 7, '9': 8, '0': 9, 'a': 10, 'b': 11, 'c': 12,
       'd': 13, 'e': 14, 'f': 15}

for e in rl:
    for i in range(3):
        mat[n][int(dic[e[i]])] = 1
        #  print(e[i])
        n += 1

np.savetxt("graph.txt", mat, fmt="%d")
file.close()
fp1.close()

ti.init(arch=ti.gpu)

mat=np.array(mat)
shape = mat.shape
type = ti.u8
pixels = ti.var(dt=type, shape=shape)


@ti.kernel
def draw(m: ti.ext_arr()):
    for i, j in pixels:  # same as two for-loops over pixels.shape, only works in @ti.kernel
        if mat[i, j] == 1:
            pixels[i, j] = 255  # IIRC Taichi images are row-major (x, y)
        else:
            pixels[i, j] = 0

draw(mat)

ti.imwrite(pixels, f"export.png")

And the data set ‘ext.txt’ like this:

350
2c0
430
4b1
1f1
153
002

Thank you in advance!

I found the reason, @ti.kernel can’t capture the mat from outerscope, we should use the argument m instead which is processed by Taichi:

- if mat[i, j] == 1:
+ if m[i, j] == 1:
import numpy as np
import taichi as ti

file = open("ext.txt", "r")
fp1 = open("graph.txt", "w")
rl = file.readlines()

n = 0
mat = np.zeros((3 * len(rl), 16), int)

dic = {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5, '7': 6, '8': 7, '9': 8, '0': 9, 'a': 10, 'b': 11, 'c': 12,
       'd': 13, 'e': 14, 'f': 15}

for e in rl:
    for i in range(3):
        mat[n][int(dic[e[i]])] = 1
        #  print(e[i])
        n += 1

np.savetxt("graph.txt", mat, fmt="%d")
file.close()
fp1.close()

ti.init(arch=ti.gpu)

mat=np.array(mat)
shape = mat.shape
type = ti.u8
pixels = ti.var(dt=type, shape=shape)


@ti.kernel
def draw(m: ti.ext_arr()):
    for i, j in pixels:  # same as two for-loops over pixels.shape, only works in @ti.kernel
        if m[i, j] == 1:  # CHANGED HERE!
            pixels[i, j] = 255  # IIRC Taichi images are row-major (x, y)
        else:
            pixels[i, j] = 0

draw(mat)

ti.imwrite(pixels, f"export.png")

It is ok now. Thank you very much! It is the first time that I have utilised Taichi to process the data set. Taichi is easy to learn and efficient.

1 Like