pythonnumpyrealsense

Python Numpy: Replacing index with index from other array if zero


I am trying to merge some depth data frames, captured with a Intel realsense depth camera.

The depth data frames comes in the following format:

dataframe1 = [[0, 0, 0, 0, 0, 10, 10, 10], [0, 0, 0, 0, 0, 10, 10, 10], [0, 0, 0, 0, 0, 10, 10, 10]]
dataframe2 = [[10, 10, 10, 0, 0, 0, 0, 0], [10, 10, 10, 0, 0, 0, 0, 0], [10, 10, 10, 0, 0, 0, 0, 0]]

What I would like to do is to do some list comprehension(ish) function to add the indices of dataframe2 to dataframe1 if the indices are zero. The expected output would look like this:

dataframe1 = [[10, 10, 10, 0, 0, 10, 10, 10], [10, 10, 10, 0, 0, 10, 10, 10], [10, 10, 10, 0, 0, 10, 10, 10]]

My only idea right now is a for loop function like this:

for idx, frame in enumerate(dataframe1):
    for idy, data in enumerate(frame):
        if data == 0:
            dataframe1[idx][idy] = dataframe2[idx][idy]

Isn't there a smarter way to do list comprehension with 3D arrays?

I also tried appending the dataframes to one array and then get the average by using:

average values = numpy.average(all_arrays, axis=0).astype(uint16)

But the noise in my depth data will cause a lot of extra noise points in the average frame.

Any help is appreciated.

Best regards Martin


Solution

  • You can do it with list comprehension:

    dataframe1 = [[0, 0, 0, 0, 0, 10, 10, 10], [0, 0, 0, 0, 0, 10, 10, 10], [0, 0, 0, 0, 0, 10, 10, 10]]
    dataframe2 = [[10, 10, 10, 0, 0, 0, 0, 0], [10, 10, 10, 0, 0, 0, 0, 0], [10, 10, 10, 0, 0, 0, 0, 0]]
    [[m if not k else k for k, m in zip(i, j)] for i, j in zip(dataframe1, dataframe2)]
    

    Output:

    [[10, 10, 10, 0, 0, 10, 10, 10],
     [10, 10, 10, 0, 0, 10, 10, 10],
     [10, 10, 10, 0, 0, 10, 10, 10]]
    

    Edit: Note that this is faster than using np.where() if dataframe1 and dataframe2 are not already numpy arrays (otherwise np.where() is faster):

    import timeit
    d1 = [[0, 0, 0, 0, 0, 10, 10, 10], [0, 1, 0, 0, 0, 10, 10, 10], [0, 0, 0, 0, 0, 10, 10, 10]]*100000
    d2 = [[10, 10, 10, 0, 0, 0, 0, 0], [10, 10, 10, 0, 0, 0, 0, 0], [10, 10, 10, 0, 0, 0, 0, 0]]*100000
    
    def lstcomp(dataframe1, dataframe2):
        return [[m if not k else k for k, m in zip(i, j)] for i, j in zip(dataframe1, dataframe2)]
    
    def where(dataframe1, dataframe2):
        dataframe1 = np.array(dataframe1)
        dataframe2 = np.array(dataframe2)
        return np.where(dataframe1, dataframe1, dataframe2)
    
    %timeit lstcomp(d1, d2)
    %timeit where(d1, d2)
    

    Output:

    233 ms ± 1.53 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    456 ms ± 992 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)