有什么方法可以裁剪ESP CAM捕获的JPG图像?

发布于 2025-02-04 01:54:02 字数 1243 浏览 3 评论 0原文

//我正在尝试裁剪ESPCAM捕获的图像,图像是我想裁剪的JPG格式。由于图像被存储为单维阵列,因此我试图重新排列阵列中的元素,但是没有发生任何变化//

我已经在RGB565中裁剪了图像,但我正在努力理解单维数组(图像缓冲区)


camera_config_t config;

  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0; 
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_RGB565; 
  config.frame_size = FRAMESIZE_SVGA;
  // config.jpeg_quality = 10;
  config.fb_count = 2;
    
  esp_err_t result = esp_camera_init(&config);
   
  if (result != ESP_OK) {
    return false;
  }
    camera_fb_t * fb = NULL;
    fb = esp_camera_fb_get();
    if (!fb)
     {
        Serial.println("Camera capture failed");
     }

FB缓冲区是一个单维数组,我想提取每个单独的RGB值。

//I am trying to crop an image captured by espcam the image is in a jpg format I would like to crop it. As the image is stored as a single-dimensional array I tried to rearrange the elements in the array but no changes occurred //

I have cropped the image in RGB565 but I am struggling to understand the single-dimensional array(image buffer)


camera_config_t config;

  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0; 
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_RGB565; 
  config.frame_size = FRAMESIZE_SVGA;
  // config.jpeg_quality = 10;
  config.fb_count = 2;
    
  esp_err_t result = esp_camera_init(&config);
   
  if (result != ESP_OK) {
    return false;
  }
    camera_fb_t * fb = NULL;
    fb = esp_camera_fb_get();
    if (!fb)
     {
        Serial.println("Camera capture failed");
     }

the Fb buffer is a single-dimensional array I want to extract each individual RGB value.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦毁影碎の 2025-02-11 01:54:02

JPG是一种压缩格式,这意味着您的行和列不与您在屏幕上显示1:1网格所看到的相对应。您需要将其转换为普通的RGB(或等效)格式,然后将其复制。

JPG通过使用数学转换然后过滤将图像分配到YCBCR组件中来实现压缩。有关其他信息,我参考此页面

幸运的是,您可以关注在Arduino上的逆向JPEG转换(提示:忘记实时执行此操作,除非您的时间限制非常放松)。

这个想法是使用将JPEG图像转换为一系列数据的库:

使用库非常简单:我们将其授予JPEG文件,并且库将开始生成像素数组 - 所谓的最小编码单元,或简称MCUS。 MCU是16 x 8像素的块。库中的功能将返回每个像素的颜色值为16位颜色值。上5位是红色值,中间6为绿色,下5个为蓝色。现在,我们可以通过我们喜欢的任何通信渠道发送这些值。

对于您的用例,您不会通过通信通道发送数据,而是通过将块推入相邻瓷砖,然后进行裁剪来将其存储在本地阵列中。

JPG is a compressed format, meaning that your rows and columns are not corresponding to what you would see by displaying a 1:1 grid on the screen. You need to convert it to the plain RGB (or equivalents) format and then copy it.

JPG achieves compression by splitting the image into YCbCR components, using a mathematical transformation and then filtering. For additional information I refer to this page.

Luckily you can follow this tutorial to do the inverse JPEG transformation on an Arduino (tip: forget to do this in real time, unless your time constraints are very relaxed).

The idea is to use a library that converts the JPEG image into an array of data:

Using the library is fairly simple: we give it the JPEG file, and the library will start generating arrays of pixels – so called Minimum Coded Units, or MCUs for short. The MCU is a block of 16 by 8 pixels. The functions in the library will return the color value for each pixel as 16-bit color value. The upper 5 bits are the red value, the middle 6 are green and the lower 5 are blue. Now we can send these values by any sort of communication channel we like.

For your use case you won't send the data through the communication channel, but rather store it in a local array by pushing the blocks into adjacent tiles, then do the crop.

携余温的黄昏 2025-02-11 01:54:02

这取决于您使用的是哪种硬件(相机和板)。
我将其基于OV2640相机模块,因为它是我一直在使用的模块。它将图像传递到已经编码的框架缓冲区,因此我猜这可能是您所面临的。

编码后试图裁剪图像可能很棘手,但是您可能会指示相机芯片仅使用a 窗口函数

访问此设置的最简单方法是定义一个访问此设置的函数:

void setWindow(int resolution , int xOffset, int yOffset, int xLength, int yLength) {
    sensor_t * s = esp_camera_sensor_get();
    resolution = 0;
    s->set_res_raw(s, resolution, 0, 0, 0, xOffset, yOffset, xLength, yLength, xLength, yLength, true, true);
}

/*
* resolution = 0 \\ 1600 x 1200
* resolution = 1 \\  800 x  600
* resolution = 2 \\  400 x  296
*/

其中(xoffset,yoffset)是像素中窗口的原点,(xlength,ylength)是像素中窗口的大小。请注意,更改分辨率将有效地覆盖这些设置。否则,这对我来说很好,尽管仅出于某种原因,只有在窗口大小中保留了4:3的宽高比。

That depends on what kind of hardware (camera and board) you are using.
I'm basing this on the OV2640 camera module because it's the one I've been working with. It delivers the image to the frame buffer already encoded, so I'm guessing this might be what you are facing.

Trying to crop the image after it has been encoded can be tricky, but you might be able to instruct the camera chip to only deliver a certain part of the sensor output in the first place using a window function.

The easiest way to access this setting is to define a function to access this:

void setWindow(int resolution , int xOffset, int yOffset, int xLength, int yLength) {
    sensor_t * s = esp_camera_sensor_get();
    resolution = 0;
    s->set_res_raw(s, resolution, 0, 0, 0, xOffset, yOffset, xLength, yLength, xLength, yLength, true, true);
}

/*
* resolution = 0 \\ 1600 x 1200
* resolution = 1 \\  800 x  600
* resolution = 2 \\  400 x  296
*/

where (xOffset,yOffset) is the origin of the window in pixels and (xLength,yLength) is the size of the window in pixels. Be aware that changing the resolution will effectively overwrite these settings. Otherwise this works great for me, although for some reason only if the aspect ratio of 4:3 is preserved in the window size.

2025-02-11 01:54:02

查看 ESP32相机驱动程序的输出格式表-jpeg。如果您可以处理原始格式(保存/传输要慢,并且要大得多),那么这将使您可以通过与几个循环进行副本更容易地裁剪图像。 JPEG被压缩,不容易裁剪。链接的页面还提到:

  • 使用YUV或RGB对芯片造成了很大的压力,因为写给PSRAM并不是特别快。结果是图像数据可能丢失了。如果启用WiFi,则尤其如此。如果需要RGB数据,建议捕获JPEG,然后使用fmt2rgb8888fmt2bmp/frame2bmp

使用fmt2rgb8888 (这意味着每个像素值将以两个字节保存,并且图像不被压缩)和frameize_svga(800x600像素),如果您应该能够在二维数组中访问framebuffer,如果您想要:

uint16_t *buffer = fb->buf;
uint16_t pxl = buffer[row * 800 + column];  // 800 is the SVGA width
// pxl now contains 5 R-bits, 6 G-bits, 5 B-bits

Looking at the output format table for the ESP32 Camera Driver one can see that most output formats are non-jpeg. If you can handle a RAW format instead (it will be slower to save/transfer, and be MUCH larger) then that would allow you to more easily crop the image by make a copy with a couple of loops. JPEG is compressed and not easily cropped. The page linked also mentions this:

  • Using YUV or RGB puts a lot of strain on the chip because writing to PSRAM is not particularly fast. The result is that image data might be missing. This is particularly true if WiFi is enabled. If you need RGB data, it is recommended that JPEG is captured and then turned into RGB using fmt2rgb888 or fmt2bmp/frame2bmp

If you are using PIXFORMAT_RGB565 (which means each pixel value will be kept in TWO bytes, and the image is not jpeg compressed) and FRAMESIZE_SVGA (800x600 pixels), you should be able to access the framebuffer as a two-dimensional array if you want:

uint16_t *buffer = fb->buf;
uint16_t pxl = buffer[row * 800 + column];  // 800 is the SVGA width
// pxl now contains 5 R-bits, 6 G-bits, 5 B-bits
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文