#include "imagecamera.h"
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <QDir>
#include <dirent.h>
#include <unistd.h>
#include <asm/types.h>
#include <math.h>
#include <malloc.h>
#include <QImage>
#define log_debug qDebug
void yuyv_to_rgb888(unsigned char* yuv,unsigned char* rgb, int imgWidth, int imgHeight)
{
unsigned int i;
unsigned char* y0 = yuv + 0;
unsigned char* u0 = yuv + 1;
unsigned char* y1 = yuv + 2;
unsigned char* v0 = yuv + 3;
unsigned char* r0 = rgb + 0;
unsigned char* g0 = rgb + 1;
unsigned char* b0 = rgb + 2;
unsigned char* r1 = rgb + 3;
unsigned char* g1 = rgb + 4;
unsigned char* b1 = rgb + 5;
//DBG("yuyv_to_rgb start\n");
float rt0 = 0, gt0 = 0, bt0 = 0, rt1 = 0, gt1 = 0, bt1 = 0;
for(i = 0; i <= (imgWidth * imgHeight) / 2 ;i++)
{
bt0 = 1.164 * (*y0 - 16) + 2.018 * (*u0 - 128);
gt0 = 1.164 * (*y0 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128);
rt0 = 1.164 * (*y0 - 16) + 1.596 * (*v0 - 128);
bt1 = 1.164 * (*y1 - 16) + 2.018 * (*u0 - 128);
gt1 = 1.164 * (*y1 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128);
rt1 = 1.164 * (*y1 - 16) + 1.596 * (*v0 - 128);
if(rt0 > 250) rt0 = 255;
if(rt0 < 0) rt0 = 0;
if(gt0 > 250) gt0 = 255;
if(gt0 < 0) gt0 = 0;
if(bt0 > 250) bt0 = 255;
if(bt0 < 0) bt0 = 0;
if(rt1 > 250) rt1 = 255;
if(rt1 < 0) rt1 = 0;
if(gt1 > 250) gt1 = 255;
if(gt1 < 0) gt1 = 0;
if(bt1 > 250) bt1 = 255;
if(bt1 < 0) bt1 = 0;
*r0 = (unsigned char)bt0;
*g0 = (unsigned char)gt0;
*b0 = (unsigned char)rt0;
*r1 = (unsigned char)bt1;
*g1 = (unsigned char)gt1;
*b1 = (unsigned char)rt1;
yuv = yuv + 4;
rgb = rgb + 6;
if(yuv == NULL)
break;
y0 = yuv;
u0 = yuv + 1;
y1 = yuv + 2;
v0 = yuv + 3;
r0 = rgb + 0;
g0 = rgb + 1;
b0 = rgb + 2;
r1 = rgb + 3;
g1 = rgb + 4;
b1 = rgb + 5;
}
}
ImageCamera::ImageCamera(QString c, QObject *parent) : QThread(parent)
{
camera = c;
err.clear();
bKeep = false;
memset(pix_format, 0, sizeof(pix_format));
cam_fd = -1;
buffer_count = 5; //5; // count 指定根据图像占用空间大小申请的缓存区个数
video_buffer_ptr = new u8*[buffer_count];
}
bool ImageCamera::initCamera()
{
int index = 0;
int ret = 0;
if(camera.isEmpty())
{
err = QString("设备节点位置为空");
return false;
}
if(cam_fd != -1)
{
close(cam_fd);
}
// 打开相机设备节点
cam_fd = open(camera.toStdString().c_str(), O_RDWR);
//cam_fd = open("/dev/video0", O_RDWR);
if(cam_fd == -1)
{
err = QString("打开相机节点失败");
return false;
}
// 设置使用的相机通道,此处为0
if(0 != ioctl(cam_fd, VIDIOC_S_INPUT, &index))
{
err = QString("%1").arg(strerror(errno));
return false;
}
// ioctl(camera,VIDIOC_)
// 查询相机的基本信息
struct v4l2_capability cap;
ioctl(cam_fd, VIDIOC_QUERYCAP, &cap);
log_debug("Driver Name:%s, Card Name:%s, Bus info:%s, Driver Version:%u.%u.%u",
cap.driver,cap.card,cap.bus_info,(cap.version>>16)&0xFF, (cap.version>>8)&0xFF,cap.version&0xFF);
// 查询相机支持的采图格式
struct v4l2_fmtdesc fmtdesc;
fmtdesc.index=0;
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
log_debug("Support format:");
do{
ret=ioctl(cam_fd, VIDIOC_ENUM_FMT, &fmtdesc);
log_debug("index %d, format %s", fmtdesc.index, fmtdesc.description);
fmtdesc.index++;
}while(0==ret);
// 查询相机支持的帧率范围
struct v4l2_streamparm stream_parm;
memset(&stream_parm, 0, sizeof(struct v4l2_streamparm));
stream_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(cam_fd, VIDIOC_G_PARM, &stream_parm);
log_debug("FrameRate: numerator = %d, denominator = %d",
stream_parm.parm.capture.timeperframe.numerator, stream_parm.parm.capture.timeperframe.denominator);
// 设置相机的输出格式,图片大小等数据
struct v4l2_format format;
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; // 设置相机输出为JPEG(V4L2_PIX_FMT_MJPEG),也可设置为yuyv(V4L2_PIX_FMT_YUYV),但具体的输出格式不能依靠此处
// format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; // 设置输出图片宽、高
//11111111111111111111111111111111qqcy
format.fmt.pix.height = nHeight;
format.fmt.pix.width= nWidth;
// format.fmt.pix.
// format.fmt.pix.height = 600;
// format.fmt.pix.bytesperline = IMAGE_WIDTH * 1;
// format.fmt.pix.sizeimage = IMAGE_WIDTH * IMAGE_HEIGHT * 1;
// format.fmt.pix.field = V4L2_FIELD_NONE;
// 尝试相机是否支持改格式
ret = ioctl(cam_fd, VIDIOC_TRY_FMT, &format);
if (ret != 0)
{
err = QString::asprintf("ioctl(VIDIOC_TRY_FMT) failed %d(%s)", errno, strerror(errno));
log_debug(err.toLatin1().constData());
return false;
}
// // 真正进行设置改格式
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(cam_fd, VIDIOC_S_FMT, &format);
if (ret != 0)
{
err = QString::asprintf("ioctl(VIDIOC_S_FMT) failed %d(%s)", errno, strerror(errno));
log_debug(err.toLatin1().constData());
return false;
}
// 获取相机输出的图片参数
if(-1 == ioctl(cam_fd, VIDIOC_G_FMT, &format)){ // 得到图片格式
err = QString("set format failed!");
log_debug(err.toLatin1().constData());
return false;
}
log_debug("fmt.type:\t\t%d",format.type);
/**************************************************************/
// 此处的图片格式,决定着采集到的图片数据要怎么解析,一般分为 MJPG 和 YUYV,上面设置的和此处获取的在某些情况下会不一致,因此需要此处决定解析格式
sprintf(pix_format, "%c%c%c%c", \
format.fmt.pix.pixelformat & 0xFF,\
(format.fmt.pix.pixelformat >> 8) & 0xFF, \
(format.fmt.pix.pixelformat >> 16) & 0xFF,\
(format.fmt.pix.pixelformat >> 24) & 0xFF);
log_debug("pix.pixelformat:\t%s", pix_format);
log_debug("pix.width:\t\t%d",format.fmt.pix.width);
log_debug("pix.height:\t\t%d",format.fmt.pix.height);
log_debug("pix.field:\t\t%d",format.fmt.pix.field);
// 查询相机需要开辟的内存信息
// 向驱动申请视频流数据的帧缓冲区
struct v4l2_requestbuffers req;
req.count = buffer_count;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ret = ioctl(cam_fd, VIDIOC_REQBUFS, &req); // 申请若干个帧缓冲区
if (ret != 0)
{
err = QString::asprintf("ioctl(VIDIOC_REQBUFS) failed %d(%s)", errno, strerror(errno));
log_debug(err.toLatin1().constData());
return false;
}
log_debug("req.count: %d", req.count);
if (req.count < buffer_count)
{
err = QString::asprintf("request buffer failed");
log_debug(err.toLatin1().constData());
return false;
}
// 逐一将相机开辟的内存进行内存映射
// 应用程序通过内存映射,将帧缓冲区的地址映射到用户空间
struct v4l2_buffer buffer;
memset(&buffer, 0, sizeof(buffer));
buffer.type = req.type;
buffer.memory = V4L2_MEMORY_MMAP;
for (int i=0; i<req.count; i++)
{
buffer.index = i;
ret = ioctl (cam_fd, VIDIOC_QUERYBUF,
常驻客栈
- 粉丝: 1w+
- 资源: 1378
最新资源
- 毕业设计-基于选题管理系统全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于行人检测系统,pyqt + opencv全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于一个简化的物联网系统全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于学生管理系统全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于学生成绩管理分析系统全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于疫情管理系统全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于云笔记系统全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于医院预约挂号系统(期末项目)全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于主动学习推荐系统的实现全部资料+详细文档+高分项目+源码.zip
- 使用Python代码生成文本圣诞树图案
- 毕业设计-基于主机安全态势感知系统全部资料+详细文档+高分项目+源码.zip
- 毕业设计-基于智慧工地监控管理系统全部资料+详细文档+高分项目+源码.zip
- 基于对人脸识别技术开发现状的研究和分析,本文利用图像处理技术、课堂考勤系统的作用为督促学生参与到课堂教学中,让学生能够更好学习相关知识。传统的课堂教学采用课堂点
- Windows系统下Python及开发工具的详细安装指南
- HTML5实现好看的无人机监控介绍网站模板.zip
- HTML5实现好看的网上家具商城网站模板.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
- 1
- 2
- 3
- 4
前往页