compute a specific integral image from sprite sheet's integral image?

45 views Asked by At

Suppose I have the integral image of an entire sprite sheet. Is it possible to retrieve the integral image of a specific image within the sprite sheet using the sprite sheet's integral image?

I've attempted to establish a relationship between each pixel of the sprite sheet's integral image, but I have not found any relevant information. Consequently, I am unsure if achieving this is even possible.

example :

image_shape_in_sprite_sheet : (2, 2)

sprite_sheet :
[[1 2 1 2]
 [3 4 3 4]
 [1 2 1 2]
 [3 4 3 4]]

sprite_sheet_integral : 
[[ 1.  3.  4.  6.]
 [ 4. 10. 14. 20.]
 [ 5. 13. 18. 26.]
 [ 8. 20. 28. 40.]]

top_left_ROI : (2, 2)
bottom_right_ROI : (3, 3)

output :

[[1, 3],
 [4, 10]]
1

There are 1 answers

0
Christoph Rackwitz On

You can just slice the corresponding region from the larger integral image, then adjust the values in the following way: subtract the preceding row and column across the slice, so the "zero" row/column becomes zero and the other values are decreased accordingly.

I'll use a format that maintains the zero rows and columns. That makes the indexing and arithmetic simpler.


Given:

sprite_sheet = np.uint8([
    [1, 2, 1, 2],
    [3, 4, 3, 4],
    [1, 2, 1, 2],
    [3, 4, 3, 4],
])

y0,y1,x0,x1 = 2,4, 2,4
sprite = sprite_sheet[y0:y1, x0:x1]
array([[1, 2],
       [3, 4]], dtype=uint8)
sheet_integral = cv.integral(sprite_sheet)
array([[ 0,  0,  0,  0,  0],
       [ 0,  1,  3,  4,  6],
       [ 0,  4, 10, 14, 20],
       [ 0,  5, 13, 18, 26],
       [ 0,  8, 20, 28, 40]], dtype=int32)

That's what you want, but sliced out of the big one:

cv.integral(sprite)
array([[ 0,  0,  0],
       [ 0,  1,  3],
       [ 0,  4, 10]], dtype=int32)

Let's take that slice (with preceding row and column):

foo = sheet_integral[y0:y1+1, x0:x1+1].copy()
array([[10, 14, 20],
       [13, 18, 26],
       [20, 28, 40]], dtype=int32)

Now adjust its values. Subtract preceding row and column from the entire array, so the preceding row and column become zero, like in the big one.

This uses numpy broadcast semantics, which is why I'm doing a 0:1 slice instead of just taking index 0.

foo -= foo[0:1, :] # intermediate result, observe the subtraction
foo -= foo[:, 0:1] # final result
array([[ 0,  0,  0],
       [ 3,  4,  6],
       [10, 14, 20]], dtype=int32)
array([[ 0,  0,  0],
       [ 0,  1,  3],
       [ 0,  4, 10]], dtype=int32)

And that is what you're looking for.