背景:
在工业检测中,按照检测的性质,可以分为定量的测量和定性的判断。在定量测量领域,一般使用高分辨的工业摄像头,并配备低畸变的镜头。对于运动目标的测量,还需要配合光源,编码器等实现高质量目标图片的获取。比如产品加工精度测量等。在定性的判断领域,不需要精确的测量,判断结论只有少数几个分类。比如在加工领域,判断某个零件是否装配好,判断特定区域颜色是否和要求相同等。在这种情况下,不需要使用高精度的工业相机,一般常用的USB2.0相机可以完成这一任务。
本文的背景是要完成一个接线端子上线头是否插接到位的判断。
只需要判断线头是否被插到指定位置,所以这是一个定性的工业检测问题。
如果想要进行工业检测,必须对usb相机的参数进行控制。笔者原来在windows下实现了用FFmpeg库读取usb摄像头,(https://blog.csdn.net/iamqianrenzhan/article/details/84830277) 但是这个库不支持usb摄像头的参数控制。后来查到要实现参数控制,需要使用windows下的VFW,DircetShow或者MediaFoundation库。但是考虑到微软的库学习成本较高,在windows下使用opencv进行摄像头参数的控制。在Ubuntu下,可以使用V4L2库进行摄像头参数的控制。
本文要介绍的就是如何在Ubuntu系统下控制usb摄像头的参数。
实现
总共4个函数,分别是打开相机,打印相机参数,获取相机信息,设置相机参数。
int fd = v4l2cameraopen(&cap);
printcamerapara(fd);
get_v4l2_info(fd);
set_v4l2_para(fd);
打开相机
int v4l2cameraopen(struct v4l2_capability *cap)
{
//struct v4l2_capability newcap;
int fd=-1;
int rel=-1;
fd= open("/dev/video0",O_RDWR,0);
if(fd==-1)
{
perror("fd");
exit(EXIT_FAILURE);
}
rel= ioctl(fd,VIDIOC_QUERYCAP,cap);
if(rel==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf("*********************Querycap Success**************************\n");
if(cap->capabilities & V4L2_CAP_VIDEO_CAPTURE)
printf("*****************capture is on*****************************\n");
if(cap->capabilities & V4L2_CAP_STREAMING)
printf("*****************Stream is on******************************\n");
printf("\n");
printf("\n");
printf("*************************Capabilities**************************\n");
printf(">:[Driver:%s]\n>:[card:%s]\n>:[bus_info:%s]\n>:[version:%d]\n",
cap->driver,cap->card,cap->bus_info,cap->version);
printf("**************************************************************\n");
printf("\n");
printf("\n");
return fd;
}
打印相机参数
void printcamerapara(int fd)
{
int i = 0;
struct v4l2_queryctrl qctrl;
struct v4l2_control ctrl;
for(i=V4L2_CID_BASE;i<V4L2_CID_LASTP1;i++)
{
qctrl.id=i;
if(ioctl(fd,VIDIOC_QUERYCTRL,&qctrl)==0)
{
ctrl.id=qctrl.id;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)<0)
perror("**********************get ctrl failed**************\n");
printf(">:[name:%s]\t[id:%08x]\n",qctrl.name,qctrl.id);
printf(">:[type:%d]\n",qctrl.type);
printf(">:[min:%d]\t[max:%d]\n",qctrl.minimum,qctrl.maximum);
printf(">:[value:%d]\t[stp:%d]\n",ctrl.value,qctrl.step);
printf(">:[default_value:%d]\n",qctrl.default_value);
printf("\n");
}
}
printf("------------------------------------------------------------------\n");
for(i=V4L2_CID_CAMERA_CLASS_BASE;i<V4L2_CID_CAMERA_CLASS_BASE+32;i++)
{
qctrl.id=i;
if(ioctl(fd,VIDIOC_QUERYCTRL,&qctrl)==0)
{
ctrl.id=qctrl.id;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)<0)
perror("**********************get ctrl failed**************\n");
printf(">:[name:%s]\t[id:%08x]\n",qctrl.name,qctrl.id);
printf(">:[type:%d]\n",qctrl.type);
printf(">:[min:%d]\t[max:%d]\n",qctrl.minimum,qctrl.maximum);
printf(">:[value:%d]\t[stp:%d]\n",ctrl.value,qctrl.step);
printf(">:[default_value:%d]\n",qctrl.default_value);
printf("\n");
}
}
printf("------------------------------------------------------------------\n");
}
得到相机信息:
void get_v4l2_info(int fd)
{
struct v4l2_format Format;
printf("************************Get format info********************************\n");
Format.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_G_FMT,&Format)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:[width:%d]\t[pixelformat:%d]\n",Format.fmt.pix.width,Format.fmt.pix.height);
printf(">:[format:%d]\t[field:%d]\n",Format.fmt.pix.pixelformat,Format.fmt.pix.field);
printf(">:[bytesperline:%d]\t[sizeimage:%d]\n",Format.fmt.pix.bytesperline,Format.fmt.pix.sizeimage);
printf(">:[colorspace:%d]\n",Format.fmt.pix.colorspace);
printf("***********************************************************************\n");
printf("\n");
printf("************************Get Stream_Parm********************************\n");
struct v4l2_streamparm Stream_Parm;
Stream_Parm.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_G_PARM,&Stream_Parm)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:[Frame rate:%u] [%u]\n",Stream_Parm.parm.capture.timeperframe.numerator,Stream_Parm.parm.capture.timeperframe.denominator);
printf(">:[capability:%d] [capturemode:%d]\n",Stream_Parm.parm.capture.capability,Stream_Parm.parm.capture.capturemode);
printf(">:[extendemode:%d] [readbuffers:%d]\n",Stream_Parm.parm.capture.extendedmode,Stream_Parm.parm.capture.readbuffers);
printf("***********************************************************************\n");
printf("\n");
struct v4l2_control ctrl;
ctrl.id=V4L2_CID_EXPOSURE_AUTO;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:Get Exposure Auto:[%d]\n",ctrl.value);
ctrl.id=V4L2_CID_EXPOSURE_ABSOLUTE;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:Get Exposure Absolute:[%d]\n",ctrl.value);
ctrl.id=V4L2_CID_EXPOSURE_AUTO_PRIORITY;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:[Get Exposure Auto Priority:%d] \n",ctrl.value);
ctrl.id=V4L2_CID_AUTO_WHITE_BALANCE;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:[Get white balance auto value:%d] \n",ctrl.value);
ctrl.id=V4L2_CID_WHITE_BALANCE_TEMPERATURE;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:[Get white balance value:%d] \n",ctrl.value);
ctrl.id=V4L2_CID_BRIGHTNESS;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:[Get brightness value:%d] \n",ctrl.value);
ctrl.id=V4L2_CID_CONTRAST;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:[Get contrast value:%d] \n",ctrl.value);
ctrl.id=V4L2_CID_SATURATION;
if(ioctl(fd,VIDIOC_G_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf(">:[Get saturation value:%d] \n",ctrl.value);
}
设置相机参数:
void set_v4l2_para(int fd)
{
struct v4l2_control ctrl;
printf("Set white balance Temperature Auto……………………\n");
ctrl.id=V4L2_CID_AUTO_WHITE_BALANCE;
ctrl.value=0; //value 0 manual 1 auto
if(ioctl(fd,VIDIOC_S_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
sleep(1);
printf("done\n");
printf("Set white balance Temperature……………………\n");
ctrl.id=V4L2_CID_WHITE_BALANCE_TEMPERATURE;
ctrl.value=4000; //value
if(ioctl(fd,VIDIOC_S_CTRL,&ctrl)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
sleep(1);
printf("done2\n");
printf("Set Exposure Auto ………………\n");
ctrl.id=V4L2_CID_EXPOSURE_AUTO;
ctrl.value=1; //1 manual
if(ioctl(fd,VIDIOC_S_CTRL,&ctrl)==-1)
{
printf("failed\n");
perror("ioctl");
exit(EXIT_FAILURE);
}
sleep(1);
printf("done3\n");
printf("Set Exposure Absolute ………………\n");
ctrl.id = V4L2_CID_EXPOSURE_ABSOLUTE;
ctrl.value = 100; //4
if(ioctl(fd,VIDIOC_S_CTRL,&ctrl)==-1)
{
printf("failed\n");
perror("ioctl");
exit(EXIT_FAILURE);
}
sleep(1);
printf("done4\n");
}