esphome / feature-requests

ESPHome Feature Request Tracker
https://esphome.io/
409 stars 26 forks source link

ESP32 Camera image rotation (0, 90, 180, 270) #2142

Open anverx opened 1 year ago

anverx commented 1 year ago

Describe the problem you have/What new integration you would like

Let the esp rotate camera images before serving them. I've designed a case for the camera (link below) which allows physical rotation of the camera. I can make the case much, much smaller if the camera image can be rotated in software. Maybe the camera module can be configured to rotate the image?
Only 0, 90, 180 and 270 rotations are useful.

Please describe your use case for this integration and alternatives you've tried:

Additional context

link to the enclosure design: https://www.printables.com/model/176992-housing-for-esp32-cam

fonske commented 1 year ago

With vertical_flip and horizontal_mirror you can adjust these views.

# ESP32-CAM ESP-EYE
esp32_camera:
  external_clock:
    pin: GPIO4
    frequency: 20MHz
  i2c_pins:
    sda: GPIO18
    scl: GPIO23
  data_pins: [GPIO34, GPIO13, GPIO14, GPIO35, GPIO39, GPIO38, GPIO37, GPIO36]
  vsync_pin: GPIO5
  href_pin: GPIO27
  pixel_clock_pin: GPIO25

# Camera settings
  resolution: 640x480
  jpeg_quality: 10
  vertical_flip: false
  horizontal_mirror: false
  special_effect: none
  contrast: 0
  brightness: 0
  saturation: 0
  agc_mode: AUTO
  aec2: false
  ae_level: 0
  aec_value: 300
  aec_mode: AUTO
  agc_value: 0
  agc_gain_ceiling: 2X
  wb_mode: AUTO
  test_pattern: false
  max_framerate: 30 fps
  idle_framerate: 1.0 fps
#  max_framerate: 10.0
#  idle_framerate: 0.1

  name: Prusa camera

# Flashlight
output:
  - platform: gpio
    pin: GPIO21
    id: gpio_21
  - platform: gpio
    pin: GPIO22
    id: gpio_22
anverx commented 1 year ago

I'm failing to see how this would work. Which values of vertical_flip and horizontal_mirror should be used to achive 90 degree rotation? rotations

xasz commented 1 year ago

Just wanted to say, that i really would love the feature aswell. I am on the same problem and trying to rotate a picture by 90degree.

nielsnl68 commented 1 year ago

@nagyrobi the solution that @fonske spoke of is NOT an alternative for the OT's question. It just allows the image to flip horizontal and vertical. It cant be used to rotate the image 90 degrees. From what i understand the camera module used for example on the AI thinkering's esp32_cam does not support this future. See also #168 for an explanation from @OttoWinter hemself.

anverx commented 1 year ago

The camera module processes and encodes the image to jpeg. The module doesn't have the capability to rotate the image only flip, and neither does the ESP (not enough RAM apparently). At this moment it looks like the feature cannot be implemented for ov2640 camera module (the one used in ESP32-Cam). Bummer.

https://community.home-assistant.io/t/flip-esp32-cam-image-90-degrees/217248/2

kamoteshake commented 11 months ago

@anverx Not sure what your use case is but for me, in homeassistant, I used motionEye to stream all of my esp32cams to homeassistant. I am able to rotate some of the cameras using the Video Rotation setting.

anverx commented 8 months ago

Afaict motionEye is dead/abandoned. And standard HA camera card doesn't offer any options.

ChrisOboe commented 4 months ago

there is a rotation standard in exif metadata. if esphome would add this information to the image almost any client will rotate it automatically without esphome needing to modify the image itself.

i don't know how hard it is to add exif data to each image but i'm pretty sure its easier than modifing the image itself since it doesn't need complex decoding (besides finding the proper offset for the exif data) and encoding again.

Tufan-67 commented 2 months ago

There is a litle complex way to change cam rotation. I'm using Kendryte K210, 480x320 LCD and ESP32 OV240 drivers. I made some additions to "const int resolution[FRAMESIZE_INVALID][3]", "const int ratio_table[][4]", "enum: framesize_t" and "enum: aspect_ratio_t".

const int resolution[FRAMESIZE_INVALID][3]: { 480, 320, ASPECT_RATIO_3X2 }, / 7 - HVGA / { 320, 480, ASPECT_RATIO_2X3 }, / 8 - HVGA REVERSE / ** This line added, reveresed of upper line { 640, 480, ASPECT_RATIO_4X3 }, / 9 - VGA */

const int ratio_table[][4] // ox, oy, mx, my { 8, 72, 1584, 1056 }, // 1 -3x2 { 400, 0, 800, 1200 }, // 2 -2x3 **** This line added, max MX: 1600, max MY: 1200 { 0, 100, 1600, 1000 }, // 3 -16x10

ratio and pixel numbers must be relevant. for 480x320 LCD I chose MX: 800, MY: 1200 (Choose accordingto your aspect ratio) OX = ((max MX) - MX) / 2 OY = ((max MY) - MY) / 2

enum: framesize_t FRAMESIZE_HVGA, // 7 - 480x320 FRAMESIZE_HVGA_R, // 8 - 320x480 **** This line added, 90 degree rotated of FRAMESIZE_HVGA FRAMESIZE_VGA, // 9 - 640x480

enum: aspect_ratio_t ASPECT_RATIO_3X2, // 1 ASPECT_RATIO_2X3, // 2 **** This line added, ASPECT_RATIO_16X10, // 3

More important thing is line indexes which are used each variable set and enums.

After all these modification chose FRAMESIZE_HVGA_R for framesize, then use HMIRROR and VFLIP for necessary orientation. And if necessary change LCD rotation.

All these modification working in my K210 platform.