我们目前正在为ESP32 32凸轮实现运动检测.为了能够与运动检测工作,我们想要访问图像的原始像素,但也希望有一个压缩的JPEG通过网络发送。
我们使用JPEGDEC库,如果他们有一个例子来绘制解码的JPEG图像到一个液晶屏幕。解码函数提供了一个回调函数,它应该处理每个MCU的绘图。但是,与其立即绘制每个单片机,我们希望将整个图像的RGB565数据存储在变量rgb中。然后,这个RGB图像将用于运动检测。
我们试图实现下面的代码,但无法让它工作,还存在一些问题:
pDraw->pPixels)提供的像素是uint16_t类型的。我们如何处理这个问题?#include <JPEGDEC.h>
uint8_t *rgb = (uint8_t*) malloc(sizeof(uint8_t) * WIDTH * HEIGHT);
JPEGDEC jpeg;
void loop()
{
camera_fb_t* frame = esp_camera_fb_get();
jpeg.openRAM((uint8_t*) frame->buf, frame->len, drawMCU);
jpeg.setPixelType(RGB565_LITTLE_ENDIAN);
jpeg.decode(0, 0, JPEG_SCALE_HALF);
jpeg.close();
pixel_counter = 0;
}
int drawMCU(JPEGDRAW *pDraw) {
for (int i = 0; i < pDraw->iWidth * pDraw->iHeight; i++) {
rgb[pixel_counter] = pDraw->pPixels[i];
pixel_counter++;
}
}发布于 2021-02-04 13:21:06
不能在函数之外调用malloc。如果您有一个setup()函数,那么将它移到那里。此外,您还需要为r、g和b字节分配空间--这将是WIDTH * HEIGHT的3倍。
然后,从RGB565数据中提取RGB字节并存储在数组中。
uint8_t *rgb = NULL;
void setup() {
rgb = malloc(WIDTH * HEIGHT * 3);
}
int drawMCU(JPEGDRAW *pDraw)
{
for (int i = 0; i < pDraw->iWidth * pDraw->iHeight; i++) {
uint8_t b = (pDraw->pPixels[i] & 0x001F) << 3;
uint8_t g = (pDraw->pPixels[i] & 0x07E0) >> 3;
uint8_t r = (pDraw->pPixels[i] & 0xF800) >> 8;
rgb[i * 3] = r;
rgb[i * 3 + 1] = g;
rgb[i * 3 + 2] = b;
}
}或者,完全不要使用malloc,因为WIDTH和HEIGHT在编译时是已知的:
uint8_t rgb[WIDTH * HEIGHT * 3];发布于 2021-12-31 23:23:49
还不清楚,我做了同样的事情,提取像素为RGB565格式,并在65k彩色oled SSD1331上显示实时视频流,而不使用外部jpeg解码器。
您根本不需要一个解码器,我已经使用提供的功能与相机驱动程序,搜索"img_converters.h“。
在Arduino IDE中,打开示例/ESP32 32/照相机/CameraWebServer.ino,移动到app_httpd.cpp Tab,您可以看到这个文件包含。
此文件包含转换图像格式的所有函数。在我的linux系统中,我在/home/massimo/Arduino/hardware/espressif/esp32/tools/sdk/include/esp32-camera/img_converters.h的ESP32 Arduino内核上找到了它。
它甚至提供了一些功能来在框架上进行叠加,比如画线(见面部识别红色和绿色)和打印文本。请让我感兴趣,如果有人发现更多的信息,我想试试。
由于字节缓冲区取决于捕获图像的大小,不排除将整个1600x1200帧捕获到ESP ram,是大量的数据,而且不能,每个像素的2个字节(RGB565)是大量的数据,不能一次捕获,需要在8/16/32/64条中划分示例。
对于96x64的oled,我将相机分辨率设置为非常低的分辨率,没有什么意义捕获大图像,然后缩小分辨率,所以我设置了160x120分辨率,当我捕获帧时,默认情况下是jpeg,我已经使用img_converters中提供的函数转换为img_converters--在一个数组中所有帧都是这样,然后删除垂直和水平的奇数像素线,所以最终的图像结果是80x60像素,最后我用一个命令将整个框架传递给我为这个oled编写的整个框架,这个命令使用在单个通道中写一个缓冲区的命令非常快地绘制:
oled.pushPixels(pixelData,len);
从SD读取和绘制oled需要6-7毫秒,每帧在全屏96x64。
一幅80x60像素的图像16位颜色(从ESP32CAMto上提取的帧需要80x60x2= 9600字节,没有问题,即使在ESP8266上也是这样,我试着分配32 or,但就在我开始转换代码以显示在320x240 ILI9341上时,我尝试了大量地管理单个帧,但是没有成功,太多的数据,这是我在每帧8或16块中剥离它的唯一方法。
因为我已经从SD卡读取了图像,所以我读取了一个条,然后显示,然后加载另一个条,然后呈现.等等..。这个动作慢了很多。
我的oled库非常快,它可以显示分辨率96x64 @接近130个FPS的视频(从uSD读取)。当我尝试相同的视频(矩阵)但在TFT上更大时,它坐下来,在320x180像素视频上最多显示12 FPS,esp8266 clocked @160 My和SPI设置为50 My。很多数据..。12 FPS,但从TFT的角度来看,它是不可思议的,它不是PC、智能手机或覆盆子,而是4美元的微控制器+6美元(320x240 2.44 ILI9341触摸屏TFT) +1美元的读卡器=触摸屏视频播放器。
使用oled,我成功地播放了视频@ 30 FPS与音频44100 16位立体声同步的外部PCM5102A数传,这是非常棒的,即使有两个MAX98357A 3W I2S制作立体声频道,并直接连接到高保真扬声器。这样就可以使用我编写的音频库,在一个小颜色的oled上播放从Youtube或其他来源(高质量的音频开箱)下载的电影,这个小颜色的oled就像硬币一样大,制作一个小的ESP iOT智能手表(但不是触摸屏)很好,它与ESP8266和ESP32一起工作,还没有在ESP32CAM上尝试外部dac,它可以工作,但不能结合SD卡,所以我怀疑它是否能够从SD_MMC播放,没有更多的引脚。
https://stackoverflow.com/questions/66046097
复制相似问题