Files
Loongson_2k0300_SmartCar/opencv_demo1/opencv_demo1.cpp
T

158 lines
5.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* @Author: ilikara 3435193369@qq.com
* @Date: 2025-01-07 06:55:37
* @LastEditors: ilikara 3435193369@qq.com
* @LastEditTime: 2025-01-07 08:10:54
* @FilePath: /smartcar/opencv_demo1/opencv_demo1.cpp
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include <opencv2/opencv.hpp>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <chrono>
#include <iomanip>
#include <sstream>
using namespace cv;
using namespace std;
// 将 RGB888 转换为 RGB565
ushort rgb888_to_rgb565(const Vec3b &color)
{
return ((color[2] >> 3) << 11) | ((color[1] >> 2) << 5) | (color[0] >> 3);
}
// 获取当前时间字符串
string getCurrentTime()
{
auto now = chrono::system_clock::now();
auto now_time_t = chrono::system_clock::to_time_t(now);
auto now_tm = *localtime(&now_time_t);
stringstream ss;
ss << put_time(&now_tm, "%Y-%m-%d %H:%M:%S");
return ss.str();
}
int main()
{
// 打开 USB 摄像头
VideoCapture cap(0); // 0 表示默认摄像头
if (!cap.isOpened())
{
cerr << "Error: Cannot open camera" << endl;
return -1;
}
// 设置摄像头分辨率(可选)
cap.set(CAP_PROP_FRAME_WIDTH, 320);
cap.set(CAP_PROP_FRAME_HEIGHT, 240);
// Framebuffer 设备
const char *fb_device = "/dev/fb0";
int fb_fd = open(fb_device, O_RDWR);
if (fb_fd == -1)
{
cerr << "Error: Cannot open framebuffer device" << endl;
return -1;
}
// 获取 Framebuffer 信息
struct fb_var_screeninfo vinfo;
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo))
{
cerr << "Error: Cannot get framebuffer information" << endl;
close(fb_fd);
return -1;
}
// 检查 Framebuffer 是否支持 RGB565
if (vinfo.bits_per_pixel != 16)
{
cerr << "Error: Framebuffer is not RGB565 format" << endl;
close(fb_fd);
return -1;
}
// 映射 Framebuffer 到内存
size_t fb_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
ushort *fb_data = (ushort *)mmap(0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
if (fb_data == MAP_FAILED)
{
cerr << "Error: Failed to map framebuffer to memory" << endl;
close(fb_fd);
return -1;
}
// 主循环
Mat frame, resizedFrame;
int frameCount = 0;
while (true)
{
// 从摄像头捕获一帧图像
cap >> frame;
if (frame.empty())
{
cerr << "Error: Captured frame is empty" << endl;
break;
}
// 调整图像大小为 160x128
resize(frame, resizedFrame, Size(160, 128));
// 获取当前时间和帧数
string timeStr = getCurrentTime();
string frameStr = "Frame: " + to_string(frameCount);
// 在图像左上角绘制黑色边框的白色文字
int fontFace = FONT_HERSHEY_SIMPLEX;
double fontScale = 0.4;
int thickness = 1;
int baseline = 0;
// 计算文字位置
Point timePos(5, 15); // 时间文字位置
Point framePos(5, 30); // 帧数文字位置
// 绘制黑色边框
putText(resizedFrame, timeStr, timePos + Point(-1, -1), fontFace, fontScale, Scalar(0, 0, 0), thickness + 1);
putText(resizedFrame, timeStr, timePos + Point(1, -1), fontFace, fontScale, Scalar(0, 0, 0), thickness + 1);
putText(resizedFrame, timeStr, timePos + Point(-1, 1), fontFace, fontScale, Scalar(0, 0, 0), thickness + 1);
putText(resizedFrame, timeStr, timePos + Point(1, 1), fontFace, fontScale, Scalar(0, 0, 0), thickness + 1);
putText(resizedFrame, frameStr, framePos + Point(-1, -1), fontFace, fontScale, Scalar(0, 0, 0), thickness + 1);
putText(resizedFrame, frameStr, framePos + Point(1, -1), fontFace, fontScale, Scalar(0, 0, 0), thickness + 1);
putText(resizedFrame, frameStr, framePos + Point(-1, 1), fontFace, fontScale, Scalar(0, 0, 0), thickness + 1);
putText(resizedFrame, frameStr, framePos + Point(1, 1), fontFace, fontScale, Scalar(0, 0, 0), thickness + 1);
// 绘制白色文字
putText(resizedFrame, timeStr, timePos, fontFace, fontScale, Scalar(255, 255, 255), thickness);
putText(resizedFrame, frameStr, framePos, fontFace, fontScale, Scalar(255, 255, 255), thickness);
// 将图像数据写入 Framebuffer
for (int y = 0; y < resizedFrame.rows; y++)
{
for (int x = 0; x < resizedFrame.cols; x++)
{
Vec3b color = resizedFrame.at<Vec3b>(y, x);
fb_data[y * vinfo.xres + x] = rgb888_to_rgb565(color);
}
}
// 更新帧数
frameCount++;
// 等待一段时间(例如 30ms
usleep(30000);
}
// 释放资源
munmap(fb_data, fb_size);
close(fb_fd);
cap.release();
return 0;
}