prusa3d / Prusa-Link

166 stars 28 forks source link

Feature request: Flip/Rotate Pi camera image #737

Open mix579 opened 1 year ago

mix579 commented 1 year ago

The way the camera is mounted on my Mk3S printers, the picture from the Pi camera in PrusaLink is upside down. Would love to see an option in the Camera settings to flip it/rotate 180 degrees. I suspect it's possible to do that on the Pi somehow but I know nothing about it, and shouldn't have to.

davidstosik commented 1 year ago

I looked for it but did not find anything. In the end, I realized the new camera mount I wanted to print would solve the issue because it makes the camera's correct physical orientation. ๐Ÿ˜ฌ

cozmo14047 commented 1 year ago

I really want this too

czesiu20 commented 1 year ago

It would be useful for me too

kanzelsberger commented 9 months ago

This is a must and should be fairly simple to implement. I tried to rotate raspberry camera v2 using /boot/config.txt with no luck...

x23piracy commented 9 months ago

upvote, please add this

cozmo14047 commented 9 months ago

It doesent look like this is going to be done. @TojikCZ

TojikCZ commented 9 months ago

Yup, most likely not on PrusaLink side, sorry. Rotating a 4k photo in raw yuyv either needs a better programmer or a lot of power

kanzelsberger commented 9 months ago

Well for those running PrusaLink on Raspberry Pi 3, 4 or 5 (probably also Zero 2) there is enough power. However, if that is complicated, why not do that on the frontend side? I would say it will be way too easy to do it in JavaScript when the image is received. It's one operation every 10 seconds in worst case, that is not very expensive.

TojikCZ commented 9 months ago

That's what i was thinking

davidstosik commented 9 months ago

Aren't there ways, with Raspberry Pi and Camera, to rotate the image at the driver level?

Things I found googling:

There seem to be some options that are not "transpose the image data after taking the capture", though I'm not knowledgeable enough to confirm what you'd need in PrusaLink... ๐Ÿค”


Another idea: EXIF data. ๐Ÿ’ก When I rotate my iPhone (or digital camera) and take a picture, the file's data itself is not rotated so that the JPEG binary at the beginning of the file is the actual top left corner of my picture. Instead, an EXIF tag is added to the JPEG file:

exif orientation (source)

camera.exif:tags should allow the addition of the Orientation tag (doc)


I don't know how to edit the Python code directly on my Raspberry Pi Zero (I can SSH and found prusa-link, but it all seems to be compiled into .pyc files and my knowledge around that is basically none). Would something like this impact the output picture? (Having installed the exif package with eg. pip install exif.)

--- prusa/link/cameras/encoders.py  2024-02-26 11:44:40.581695756 +0900
+++ prusa/link/cameras/encoders.py 2024-02-26 11:34:40.280423311 +0900
@@ -15,6 +15,8 @@
 import numpy as np
 from turbojpeg import TJSAMP_422, TurboJPEG  # type: ignore

+from exif import Image as exifImage
+
 from . import v4l2

 jpeg = TurboJPEG()
@@ -357,6 +359,12 @@
             raise RuntimeError(
                 "Encoding failed - re-queueing the coded buffer")

+        image = exifImage(output)
+        image.set("Orientation", 3)
+        output = image.get_file()
+
         return output

I'd expect the image displayed in the PrusaLink web interface to be upside down.


Update: it works! Basically, removing encoders.pyc and copying encoders.py from the repository allowed me to run PrusaLink with the modified file (need to restart prusalink with prusalink restart). Of course, this is just a proof of concept and it would need more work (add a setting somewhere, store it, and use that setting instead of the hard-coded 3), but as a proof of concept, it shows that my Raspberry Pi Zero W was able to mark the image as rotated 180ยบ using an EXIF tag (without having to transpose the whole binary data).

Here's the kind of image it showed in the UI:

image

Whereas without my hack, the image looks like this:

image

I can show the hack image's EXIF data in macOS' Preview app:

image

Orientation: 3 (Rotated 180ยบ)


I also tried with "Orientation", 8 and it works too, though the web UI could use a scale fix. ๐Ÿ˜…

image

(Using width: 100% CSS leads to that.)

PrusaConnect looks rather nice too, though rotating the thumbnail retrieved from PrusaLink would require a bit more work. (It could be that PrusaConnect strips out EXIF info when generating a thumbnail of the image shared by PrusaLink.)

image
cozmo14047 commented 9 months ago

Aren't there ways, with Raspberry Pi and Camera, to rotate the image at the driver level?

Things I found googling:

  • alias raspivid="/usr/bin/raspivid -rot 90" (source)
  • v4l2-ctl --set-ctrl=rotate=90 (source)
  • Does libcamera.Transform apply at the driver level? (source)

There seem to be some options that are not "transpose the image data after taking the capture", though I'm not knowledgeable enough to confirm what you'd need in PrusaLink... ๐Ÿค”

Another idea: EXIF data. ๐Ÿ’ก When I rotate my iPhone (or digital camera) and take a picture, the file's data itself is not rotated so that the JPEG binary at the beginning of the file is the actual top left corner of my picture. Instead, an EXIF tag is added to the JPEG file:

exif orientation (source)

camera.exif:tags should allow the addition of the Orientation tag (doc)

I don't know how to edit the Python code directly on my Raspberry Pi Zero (I can SSH and found prusa-link, but it all seems to be compiled into .pyc files and my knowledge around that is basically none). Would something like this impact the output picture? (Having installed the exif package with eg. pip install exif.)

--- prusa/link/cameras/encoders.py  2024-02-26 11:44:40.581695756 +0900
+++ prusa/link/cameras/encoders.py 2024-02-26 11:34:40.280423311 +0900
@@ -15,6 +15,8 @@
 import numpy as np
 from turbojpeg import TJSAMP_422, TurboJPEG  # type: ignore

+from exif import Image as exifImage
+
 from . import v4l2

 jpeg = TurboJPEG()
@@ -357,6 +359,12 @@
             raise RuntimeError(
                 "Encoding failed - re-queueing the coded buffer")

+        image = exifImage(output)
+        image.set("Orientation", 3)
+        output = image.get_file()
+
         return output

I'd expect the image displayed in the PrusaLink web interface to be upside down.

Update: it works! Basically, removing encoders.pyc and copying encoders.py from the repository allowed me to run PrusaLink with the modified file (need to restart prusalink with prusalink restart). Of course, this is just a proof of concept and it would need more work (add a setting somewhere, store it, and use that setting instead of the hard-coded 3), but as a proof of concept, it shows that my Raspberry Pi Zero W was able to mark the image as rotated 180ยบ using an EXIF tag (without having to transpose the whole binary data).

Here's the kind of image it showed in the UI:

image

Whereas without my hack, the image looks like this:

image

I can show the hack image's EXIF data in macOS' Preview app:

image

Orientation: 3 (Rotated 180ยบ)

I also tried with "Orientation", 8 and it works too, though the web UI could use a scale fix. ๐Ÿ˜… image

(Using width: 100% CSS leads to that.)

PrusaConnect looks rather nice too, though rotating the thumbnail retrieved from PrusaLink would require a bit more work. (It could be that PrusaConnect strips out EXIF info when generating a thumbnail of the image shared by PrusaLink.)

image

Good job, you were actully able to do it ( somthing the devs couldnt do) @TojikCZ . I will be looking at doing this, maybe add a pull request