[HOW-TO] Flip a still image captured by request (mirrored preview w/o modeswitch > non mirrored still)
Describe what it is that you want to accomplish I want to instant capture a running mirrored preview. I'm currently running two streams, main and lores, to give me a preview und the full res stream to capture. (https://github.com/raspberrypi/picamera2/issues/262#issuecomment-1215422931)
Describe alternatives you've considered
One option to achieve my goal is only to mirror the lores stream, but I think this is not possible.
My second thought was to flip back the picture I took by request. But which kind of date or array is it? Can I flip it?
The only way I could figure out was to use capture_image and flip the PIL image by transpose(Image.Transpose.FLIP_LEFT_RIGHT).
Is there a better way to do this?
Here the actual code with the flip command...
#!/usr/bin/python3
import time
import libcamera
from picamera2 import Picamera2, Preview
picam2 = Picamera2()
picam2.start_preview(Preview.QTGL)
main_stream = {}
lores_stream = {"size": (800, 600)}
my_config = picam2.create_still_configuration(main_stream, lores_stream, transform=libcamera.Transform(hflip=1), display="lores")
picam2.configure(my_config)
picam2.start()
time.sleep(5)
# It's better to capture the still in this thread, not in the one driving the camera.
request = picam2.capture_request()
request.save("main", "test.jpg")
request.release()
print("Still image captured!")
time.sleep(5)
I think flipping the image that you save like that sounds reasonable. Another alternative would be to flip the image that you display and not the one you save. Of course, that will run on every image and use CPU, but if the lores is small, and the full res camera mode runs at a relatively low framerate, then I don't think you'd notice. So something like this:
from picamera2 import Picamera2, MappedArray
picam2 = Picamera2()
config = picam2.create_still_configuration(lores={"size": (640, 480)}, display="lores", buffer_count=2)
picam2.configure(config)
w, h = config["lores"]["size"]
def hflip_lores(request):
with MappedArray(request, "lores") as m:
m.array[:h,::] = m.array[:h,::-1]
m.array[h:,:w//2] = m.array[h:,w//2-1::-1]
m.array[h:,w//2:] = m.array[h:,w-1:w//2-1:-1]
picam2.pre_callback = hflip_lores
picam2.start(show_preview=True)
Having said that, it sort of feels like something the preview window ought to be able to do for itself. I think all the preview implementations, Qt, GLES and DRM/KMS probably have this facility so it shouldn't be too hard, it "just" requires someone to trawl the net and discover the magic runes...
This may be of interest: https://github.com/raspberrypi/picamera2/pull/271
It would make the above example code look like:
from picamera2 import Picamera2, Preview
from libcamera import Transform
picam2 = Picamera2()
config = picam2.create_still_configuration(lores={"size": (640, 480)}, display="lores", buffer_count=2)
picam2.configure(config)
picam2.start_preview(Preview.QTGL, transform=Transform(hflip=1))
picam2.start()
That are great news, that fits perfect for my use case. (In my real app uses QGl but that is also implemented) Thank you.
I've postedthe new version that has this feature, so I'll close this issue. Obviously please always feel free to open a new issue if something else comes up. Thanks!