I found this very nice example, how to make an array of frames: https://stackoverflow.com/a/17394994/7489698
But I do not know how to use this in PIL correctly. To demonstrate it, I have sketched this commands:
import numpy as np
import cv2
from PIL import Image, ImageTk
nframes = 10
frame = cv2.imread('test.jpg')
(x,y,d)=frame.shape
frames = np.empty((nframes,x, y, d))
for k in range(nframes):
frames[k,:,:,:] = frame
frame_avg=np.int8(np.mean(frames,0))
frame_avg.shape
cv2.imwrite('test_avg.jpg',frame_avg)
Image.fromarray(frame)
Image.fromarray(frame_avg)
The image test.jpg
is read and 10 times stored in the array frames
. The average thereof is stored in the file test_avg.jpg
where it can be seen that it looks ok.
Converting the orignal frame to a PIL image is working, but the last line throws this error:
---> 20 Image.fromarray(frame_avg)
/usr/local/lib/python3.10/dist-packages/PIL/Image.py in fromarray(obj, mode)
3313 typekey_shape, typestr = typekey
3314 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}"
-> 3315 raise TypeError(msg) from e
3316 else:
3317 rawmode = mode
TypeError: Cannot handle this data type: (1, 1, 3), |i1
What did I do wrong???
KR, Christof
The frame_avg
array you created has a data type of int8
(|i1
), which PIL's Image.fromarray
does not support for RGB images. PIL expects uint8
(np.uint8
) data for typical RGB images. That's why you are seeing the TypeError. Change the data type of frame_avg
from int8
to uint8
. And edit your code like this:
import numpy as np
import cv2
from PIL import Image
nframes = 10
frame = cv2.imread('test.jpg')
# Convert to RGB for PIL compatibility (OpenCV reads as BGR)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
(x, y, d) = frame.shape
frames = np.empty((nframes, x, y, d), dtype=np.uint8)
for k in range(nframes):
frames[k, :, :, :] = frame
# Average and convert back to uint8
frame_avg = np.mean(frames, axis=0).astype(np.uint8)
# Save averaged image using OpenCV (convert back to BGR for OpenCV)
cv2.imwrite('test_avg.jpg', cv2.cvtColor(frame_avg, cv2.COLOR_RGB2BGR))
# Convert to PIL Image and display
Image.fromarray(frame) # should work
Image.fromarray(frame_avg) # now works too
The following documentations and links may help you
Which is best practice doing null checks or empty checks with Kotlin data classes?
https://github.com/python-pillow/Pillow/issues/1190
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.fromarray
If you are looking for some more OpenCV related projects, you can see here: https://www.pcbway.com/project/shareproject/How_to_use_AI_to_program_a_2DOF_ROBOT_Arduino_pyhton_opencv_chatgp_ps3eyecam_d3896679.html