Issue
I am taking multiple white light images in a row that I want to split into RGB images later on due to time constraints for my application. I currently save the raw RGB image as a .data
but cannot figure out how to read the file back into an array to allow me to manipulate it in a separate script. Is there a better way to save this RGB data very quickly so that I have access to it later? or even better split it up into R G and B then save those images individually?
Camera Capture:
self.camera.capture('file_location.data', 'rgb')
Read back into Python (Seperate Script):
path = 'file_location.data'
with open(path, 'rb') as f:
contents = f.read()
I am able to read the binary file but have not found how to convert contents
into an array that I can manipulate.
Solution
Here's a way of doing what you ask - it saves the 7 images in a list in memory so that you can take the photos in rapid sequence and then flush them to disk at a more leisurely pace after your experiment is complete.
You seem to be under the misapprehension that compression means data loss. In the case of PNG, the compression is loss-less, unlike JPEG which is lossy.
#!/usr/bin/env python3
import numpy as np
from PIL import Image
# Make 7 random RGB images 2592x1944 and append to list in memory
imageList = []
for i in range(7):
print(f'Creating image {i}')
im = np.random.randint(0,256,(1944,2592,3), dtype=np.uint8)
imageList.append(im)
# Show user length of list
print(f'Number of images in list: {len(imageList)}')
# Save images after experiment is complete
for i,image in enumerate(imageList):
filename = f'image-{i}.png'
print(f'Saving image: {filename}')
Image.fromarray(image).save(filename)
Sample Output
Creating image 0
Creating image 1
Creating image 2
Creating image 3
Creating image 4
Creating image 5
Creating image 6
Number of images in list: 7
Saving image: image-0.png
Saving image: image-1.png
Saving image: image-2.png
Saving image: image-3.png
Saving image: image-4.png
Saving image: image-5.png
Saving image: image-6.png
If you run the program, you will see that the 7 images are created almost instantaneously, and only the saving to disk at the end takes a while.
Here are the created files:
-rw-r--r--@ 1 mark staff 15132795 6 Aug 11:01 image-0.png
-rw-r--r-- 1 mark staff 15132768 6 Aug 11:01 image-1.png
-rw-r--r-- 1 mark staff 15132789 6 Aug 11:01 image-2.png
-rw-r--r-- 1 mark staff 15132792 6 Aug 11:01 image-3.png
-rw-r--r-- 1 mark staff 15132790 6 Aug 11:01 image-4.png
-rw-r--r-- 1 mark staff 15132791 6 Aug 11:01 image-5.png
-rw-r--r-- 1 mark staff 15132784 6 Aug 11:01 image-6.png
If you want to analyse the memory usage, you can either run htop
while the program is running and watch the RAM usage there, or you can run it like this:
/usr/bin/time -l ./script.py
6.79 real 6.98 user 0.21 sys
162914304 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
40470 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
9 voluntary context switches
2620 involuntary context switches
48621173737 instructions retired
30872454100 cycles elapsed
145956864 peak memory footprint
Note that you could equally use OpenCV instead of PIL, just use:
import cv2
and, at the end
cv2.imwrite(filename, image)
Note that a Raspberry Pi has 4 CPU cores and Python tends to only use one, so if you wanted to be able to store more images, you could start say 3 additional processes that wait for images from the acquisition process and write them to disk. Then you would clear the RAM out of unsaved images at 3 times the rate. This is pretty simple with Redis or Python 3.8 multiprocessing shared memory. If you ran a Redis instance on your Raspberry Pi, it could run without WiFi (as it would be local), but you could pull the images afterwards (or real-time) from your PC for Matlab to process.
Answered By - Mark Setchell