#include <Arduino.h>
#include "esp_camera.h"
#include <esp_spiram.h>
// 引脚配置(根据你接线来改)
#define PWDN_GPIO_NUM -1 // 接地就设为 -1
#define RESET_GPIO_NUM -1 // 接 3.3V 就设为 -1
#define XCLK_GPIO_NUM -1
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 17
#define Y9_GPIO_NUM 12
#define Y8_GPIO_NUM 11
#define Y7_GPIO_NUM 10
#define Y6_GPIO_NUM 9
#define Y5_GPIO_NUM 8
#define Y4_GPIO_NUM 7
#define Y3_GPIO_NUM 6
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 16
#define HREF_GPIO_NUM 14
#define PCLK_GPIO_NUM 13
void setup() {
Serial.begin(3000000);
if (psramFound()) {
Serial.println("PSRAM is available");
// 启用 PSRAM 分配
// heap_caps_malloc_extmem_enable(16); // 单位为 KB,最小分配块
} else {
Serial.println("PSRAM not found!");
}
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_xclk = -1;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_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_JPEG;
config.frame_size = FRAMESIZE_HVGA; // 320x240
config.jpeg_quality = 10;
config.fb_count = 1;
config.fb_location = CAMERA_FB_IN_PSRAM;
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
Serial.println("Camera Ready");
}
void loop() {
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
Serial.println("===IMG_START===");
Serial.write(fb->buf, fb->len);
Serial.println("\n===IMG_END===");
esp_camera_fb_return(fb);
//
// delay(2000); // 每2秒发一张
// 发送图像内容
// Serial.write(fb->buf, fb->len);
// esp_camera_fb_return(fb);
delay(10); // 控制帧率
}
import serial
import time
import os
import cv2
import numpy as np
SERIAL_PORT = 'COM7'
BAUD_RATE = 3000000
SAVE_DIR = 'images'
IMAGE_PREFIX = 'image'
os.makedirs(SAVE_DIR, exist_ok=True)
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
cv2.namedWindow("cam", cv2.WINDOW_AUTOSIZE)
print("等待图像...")
buffer = bytearray()
in_frame = False
img_count = 0
while True:
try:
# 读一行文本,检测起始和结束标志
line = ser.readline()
if b'===IMG_START===' in line:
print(f"[{time.strftime('%H:%M:%S')}] 捕获图像开始")
buffer = bytearray()
in_frame = True
continue
elif b'===IMG_END===' in line:
print(f"[{time.strftime('%H:%M:%S')}] 图像结束,解码显示中...")
in_frame = False
print(f"接收的图像数据长度: {len(buffer)}")
if len(buffer) == 0:
print("错误:图像数据为空")
continue
nparr = np.frombuffer(buffer, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
if img is not None:
# 2. 获取屏幕分辨率(假设 1920x1080)
screen_width, screen_height = 1280, 960 # 可以改成你的屏幕分辨率
# 3. 缩放图片到全屏(可选择不同的插值方法)
resized_img = cv2.resize(img, (screen_width, screen_height), interpolation=cv2.INTER_LINEAR)
cv2.imshow("cam", resized_img)
cv2.waitKey(1)
img_path = os.path.join(SAVE_DIR, f"{IMAGE_PREFIX}_{img_count:03d}.jpg")
cv2.imwrite(img_path, img)
print(f"图像已保存: {img_path}")
img_count += 1
else:
print("图像解码失败")
continue
if in_frame:
# 用 read(size) 代替 readline() 更安全
# 但这里先用 readline 观察效果,之后可以改为 ser.read()
buffer += line
except KeyboardInterrupt:
print("中断,退出程序")
break
except Exception as e:
print(f"错误: {e}")
break
ser.close()
cv2.destroyAllWindows()