3

I have a txt file with 46 entries that looks like this -

2020-05-24T10:57:12.743606#[0.0, 0.0, 0.0653934553265572, 0.0, 1.0, 0.0]
2020-05-24T10:57:12.806380#[0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
2020-05-24T10:57:12.869022#[0.0, 0.0, 0.0, 0.0, 1.0, 0.0]

The first argument is a timestamp of the camera image taken. For each timestamp, there are 3 RGB images.

My goal is to concatenate them along the channel axis(axis = 2). The image dimension is 70x320x3. So the desired output is 46x70x320x9.

I would need to wait till all 3 images are recognised, then append them to a list and feed that to a numpy array. I'm failing as the output dimension I'm getting is 46x138(for 3 images from append)x70x320x3 46x138x70x320x3 before concate. Concatenation doesn't work when implemented with axis =2 or 3

From this how can I get 46x70x320x9?

Code -

with open("train.txt", 'r') as f:
    data = f.readlines()[:]
images = []
image_concat = []
labels = []
for row in data:
    for camera in ['center', 'left', 'right']:
        img_id, label = row.strip("\n").split("#")
        img_path = os.path.join(IMG_PATH, '{}-{}.jpg'.format(camera, img_id))
        image = cv2.imread(img_path)
        images.append(image)
        if camera == 'right':
            image_concat.append(images)

X_data = np.array(image_concat)
print(X_data.shape)

Referred links -

Need help combining two 3 channel images into 6 channel image Python

numpy: concatenate two arrays along the 3rd dimension

numpy concatenate multiple arrays arrays

numpy concatenate over dimension

Please help. Any help will be appreciated. Thank you.

Deepak
  • 126
  • 8

2 Answers2

3

Here is an implementation with dummy data

collect = []
for i in range(46):

    #create dummy arrays, simulate list of 3 RGB images
    a = [np.zeros((70,320,3)) for b in range(3)]
    # a[0].shape: (70,320,3) 

    #concatenate along axis 2
    b = np.concatenate(a, axis=2)
    # b.shape: (70,320,9)

    #create new axis in position zero
    b = b[np.newaxis, ...]
    # b.shape : (1,70,320,9)
    collect.append(b)

output = np.concatenate(collect, axis=0)

output.shape
(46, 70, 320, 9)

edit:

# IIUC:
# left camera makes 70,320,3 at time t
# right camera makes 70,320,3 at time t
# center camera makes 70,320,3 at time t
# these need to be concatenated to 70,320,9
# if so, you can use a dictionary

#initialise dict
collected_images = {}
for timepoint, row in enumerate(data):
    #at every timepoint, initialise dict entry
    collected_images[timepoint] = []
    for camera in ['center', 'left', 'right']:
        image = cv2.imread('path/to/image')
        collected_images[timepoint].append(image)

# now you have all images in a dictionary
# to generate the array, you can

output = []
for key, val in collected_iamges.items():
    temp = np.concatenate(val, axis=2)
    output.append(temp[np.newaxis, ...])

output = np.concatenate(output, axis=0)
warped
  • 8,947
  • 3
  • 22
  • 49
  • Thank you for breaking it down. I'm able to understand how that new axis helps in my case. In my case, when I read text file, I get all the rows which results in all 138 file path. I struggle to narrow it down to every 3 rows to do first concatenation. I need to figure out how. – Deepak Jun 08 '20 at 21:30
  • 1
    Thanks a lot. Your breakdown not only helped me learn but also understand the problem even better. I had to make some changes. Got it done. – Deepak Jun 09 '20 at 10:01
  • Sorry to bother you again. I extended the logic to a larger dataset of 110,000 timestamp that has 3 times its in images, The script crashed with a "bus error(core dumped)" message. I see no spike in memory or cpu usage. But, I reckon using dictionary causes too much to be in persistent memory. Any other way to solve this issue? – Deepak Jun 09 '20 at 21:46
  • @Deepak if I understand correctly, you want to create an array with a shape of (110000, 70, 320, 9). This object has a size of 165 gb. I suggest that you change your strategy and work with smaller data packages. You could load and process smaller chunks at a time. – warped Jun 09 '20 at 22:07
  • Changed my logic -- Used list instead of dictionary. Appended a list of 3 images to a new list, performed concatenation to that, in turn appended this to another list and deleted the 3 images list for each iteration. Solved the memory problem. – Deepak Jun 11 '20 at 16:31
1

After @warped's first answer, I figured out the output list from the text file was the problem. It was dumping all lines in one go. After several tries, I ended up using csv.reader which made things so much easier. After that just extended @warped's second answer and got the task done.

with open('train.txt', 'r') as f:
    lines = f.readlines()
    data = csv.reader(lines, delimiter = "#")
    for count, index in enumerate(data):
        img_id = index[0]
        label = [float(item) for item in index[1][1:-1].split(",")]

Label solution from here -- Python - convert list of string to float - square braces and decimal point causing problems

After it was basically using the answer.

This link helped me choose csv reader -- Python not reading from a text file correctly?

Deepak
  • 126
  • 8