⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main2.c

📁 在基于ARM处理器的Liunx系统下的开放板上实现摄像头图像采集
💻 C
字号:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <termios.h>
#inclide <iostream>

#include "fb.h"
#include "videodev.h"
#include "bmp.h"
#include "grab-ng.h"

#define _GNU_SOURCE
#include <getopt.h>


struct capture_info{
	int width, height;
	char device[256];
};

struct fb_dev
{
	//for frame buffer
	int fb;
	void *fb_mem;	//frame buffer mmap
	int fb_width, fb_height, fb_line_len, fb_size;
	int fb_bpp;
	//src must be RGB24 format
	void (*fb_draw)(struct fb_dev *fbdev, void* src, int x, int y, int width, int height);
};

static char *default_framebuffer="/dev/fb0";

static struct capture_info capinfo={320, 240, "/dev/v4l/video0"};
static struct fb_dev fbdev;
static char* fb_dev_name=NULL;
struct ng_video_buf* pvideo_buf;
char *bmpName="/root/Documents/ndt.bmp";
double x=0,y=0;

#define NUM_CAPBUFFER	32

void fb_draw16bpp(struct fb_dev *fbdev, void* src, int x, int y, int width, int height)
{
	int i, j;
	int fb_line_len = fbdev->fb_line_len;
	__u8 *psrc= (__u8*)src;
	__u16* pdsc = (__u16*)fbdev->fb_mem;
	__u16 tmp, tmp1;

	pdsc+=y*fb_line_len/2 + x;

	for(i=0; i<height; i++){
		for(j=0; j<width; j++){
			/*
			tmp = (*psrc)>>3;		tmp<<=11;	*psrc++;		//this is for GIGEND----PC
			tmp1 = (*psrc)>>2;	tmp|=(tmp1<<5);	*psrc++;
			tmp |= (*psrc)>>3;	*psrc++;
			pdsc[j] = tmp;
			*/
			//this is for little end ----ARM
			tmp = (*psrc)>>3;		tmp<<=0;	*psrc++;			//BLUE
			tmp1 = (*psrc)>>2;	tmp|=(tmp1<<5);	*psrc++;		//GREEN
			tmp |=(((*psrc)>>3) << 11);	*psrc++;					//RED
			pdsc[j] = tmp;
		}
		pdsc+=fb_line_len/2;
	}
}

void fb_draw12bpp(struct fb_dev *fbdev, void* src, int x, int y, int width, int height)
{
	int i, j;
	int fb_line_len = fbdev->fb_line_len;
	__u8 *psrc= (__u8*)src;
	__u8* pdsc = (__u8*)fbdev->fb_mem;
	__u8 tmp;

	//fixed me! x must be even
	pdsc+=y*fb_line_len + x*3/2;

	for(i=0; i<height; i++){
		for(j=0; j<width*3/2;){
			tmp = psrc[2]&0xf0;
			tmp |=(psrc[1]>>4);
			pdsc[j++] = tmp;

			tmp = psrc[0]&0xf0;
			tmp |=(psrc[5]>>4);
			pdsc[j++] = tmp;

			tmp = psrc[4]&0xf0;
			tmp |=(psrc[3]>>4);
			pdsc[j++] = tmp;

			psrc+=6;
		}
		pdsc+=fb_line_len;
	}
}

int framebuffer_open(void)
{
	int fb;
	struct fb_var_screeninfo fb_vinfo;
	struct fb_fix_screeninfo fb_finfo;
	
	if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER")))
		fb_dev_name=default_framebuffer;

	fb = open (fb_dev_name, O_RDWR);
	if(fb<0){
		printf("device %s open failed\n", fb_dev_name);
		return -1;
	}
	
	if (ioctl(fb, FBIOGET_VSCREENINFO, &fb_vinfo)) {
		printf("Can't get VSCREENINFO: %s\n", strerror(errno));
		close(fb);
		return -1;
	}

	if (ioctl(fb, FBIOGET_FSCREENINFO, &fb_finfo)) {
		printf("Can't get FSCREENINFO: %s\n", strerror(errno));
		return 1;
	}

	fbdev.fb_bpp = fb_vinfo.red.length + fb_vinfo.green.length +
		fb_vinfo.blue.length + fb_vinfo.transp.length;

	fbdev.fb_width = fb_vinfo.xres;
	fbdev.fb_height = fb_vinfo.yres;
	fbdev.fb_line_len = fb_finfo.line_length;
	fbdev.fb_size = fb_finfo.smem_len;

	printf("frame buffer: %dx%d,  %dbpp, 0x%xbyte\n", 
		fbdev.fb_width, fbdev.fb_height, fbdev.fb_bpp, fbdev.fb_size);

	switch(fbdev.fb_bpp){
	case 16:
		fbdev.fb_draw = fb_draw16bpp;
		break;
	case 12:
		fbdev.fb_draw = fb_draw12bpp;
		break;
	default:
		printf("Can't support %d bpp draw\n", fbdev.fb_bpp);
		return -1;
	}


	fbdev.fb_mem = mmap (NULL, fbdev.fb_size, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
	if(fbdev.fb_mem==NULL || (int)fbdev.fb_mem==-1){
		fbdev.fb_mem=NULL;
		printf("mmap failed\n");
		close(fb);
		return -1;
	}
	fbdev.fb=fb;
	memset (fbdev.fb_mem, 0x0, fbdev.fb_size);
    return 0;
}

void framebuffer_close()
{
	if(fbdev.fb_mem){
		munmap(fbdev.fb_mem, fbdev.fb_size);
		fbdev.fb_mem=NULL;
	}

	if(fbdev.fb){
		close(fbdev.fb);
		fbdev.fb=0;
	}
}

int capture()
{
	void* caphandle;
	struct ng_vid_driver *cap_driver = &v4l_driver;

	struct ng_video_fmt fmt;

	fmt.fmtid = VIDEO_BGR24;
	fmt.width = capinfo.width;
	fmt.height = capinfo.height;

	if(framebuffer_open()<0){
		return -1;
	}

	caphandle=cap_driver->open(capinfo.device);

	if(!caphandle){
		printf("failed to open video for linux interface!\n");
		return -1;
	}

	if(cap_driver->setformat(caphandle, &fmt)){
		printf("failed to set video format!\n");
		return -1;
	}

	cap_driver->startvideo(caphandle, 25,  NUM_CAPBUFFER);

	{
		
		int x, y, width, height;
		int diff_width, diff_height;

		diff_width = fbdev.fb_width - fmt.width;
		diff_height = fbdev.fb_height - fmt.height;

		if(diff_width>0){
			x =  diff_width/2;
			width = fmt.width;
		}
		else{
			x = 0;
			width = fbdev.fb_width;
		}

		if(diff_height>0){
			y =  diff_height/2;
			height = fmt.height;
		}
		else{
			y = 0;
			height = fbdev.fb_height;
		}

		//begin capture
		while(1){
			pvideo_buf=cap_driver->nextframe(caphandle);
			fbdev.fb_draw(&fbdev, pvideo_buf->data, x, y, width, height);
			ng_release_video_buf(pvideo_buf);
			
		}
	}

	framebuffer_close();
	cap_driver->stopvideo(caphandle);
	cap_driver->close(caphandle);
	return 0;
}

const char*program_name; 
void print_usage (FILE*stream,int exit_code)
{ 
	fprintf (stream, "Usage:%s options [ inputfile ....]\n",program_name); 
	fprintf (stream, "-h --help Display this usage information.\n"
		"-d --device <video device>.\n "
		"-f --framebuffer <frame buffer device>.\n "
		"-v --verbose <n>.\n "
		"-s --size <320:240>\n");
	exit (exit_code); 
} 
/*采集一副图象,将其写入到bmp文件中,然后读出该bmp图象数据信息,提取数据进行图象识别,计算出图片中
   激光光斑的坐标*/
int save_bmp()
{
	
	if(!pvideo_buf->data)
		return 0;
	int lineByte=(320*24/8+3)/4*4;
	FILE *fp=fopen(bmpName,"wb");
	if(fp==0)
		return 0;
	BITMAPFILEHEADER fileHead;
	fileHead.bftype = 0x4d42;
	fileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lineByte*240;
	fileHead.bfReserved1=0;
	fileHead.bfReserved2=0;
	fileHead.bfoffBits=54;
	fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);
	BITMAPINFOHEADER head;
	head.biBitCount=24;
	head.biClrImportant=0;
	head.biClrUsed=0;
	head.biCompression=0;
	head.biHeight=240;
	head.biPlanes=1;
	head.biSize=40;
	head.biSizeImage=lineByte*240;
	head.biWidth=320;
	head.biPelsPerMeter=0;
	head.biYPelsPerMeter=0;
	fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);
	fwrite(pvideo_buf->data,240*lineByte,1,fp);
	fclose(fp);
	return 1;
}

int read_bmp()
{
	unsigned bmpWidth;
	unsigned bmpHeight;
	int *pBmpBuf;
	FILE *fp=fopen(bmpName,"rb");
	if(fp==0)
		return 0;
	fseek(fp,sizeof(BITMAPFILEHEADER),0);
	BITMAPINFOHEADER head;
	fread(&head,sizeof(BITMAPINFOHEADER),1,fp);
	bmpWidth=head.biWidth;
	bmpHeight=head.biHeight;
	int lineByte=(bmpWidth*24/8+3)/4*4;
    fread(pBmpBuf,1,lineByte*bmpHeight,fp);
    fclose(fp);
	return 1;
}
//获得图象中心坐标
void get_middle()
{
	doublex1=0,y1=0,x2=0;
	save_bmp();
	//printf("width=%d,height=%d\n",bmpWidth,bmpHeight);
	read_bmp();
	int i,j,k;
	int lineByte=(bmpWidth*24/8+3)/4*4;
	for(i=1;i<bmpWidth;i++){
		for(j=1;j<bmpHeight;j++){
			x1+=(*(pBmpBuf+j*lineByte+i*3+0)*0.11+*(pBmpBuf+j*lineByte+i*3+1)*0.59+*(pBmpBuf+j*lineByte+i*3+2)*0.3)*i
            x2+=*(pBmpBuf+i*lineByte+j*3+0)*0.11+*(pBmpBuf+i*lineByte+j*3+1)*0.59+*(pBmpBuf+i*lineByte+j*3+2)*0.3
            y1+=(*(pBmpBuf+i*lineByte+j*3+0)*0.11+*(pBmpBuf+i*lineByte+j*3+1)*0.59+*(pBmpBuf+i*lineByte+j*3+2)*0.3)*j
		}
	}
	x=x1/x2;
	y=y1/x2;
	sleep(10);
}


void send_gprs()
{
	int fdcom, i, SendLen;
	
	struct termios termios_cur;
	//char RecvBuf[10];
	char *p1="AT\r\n";
	char *p2="AT+CMGF=1\r\n";
	char *p3="AT+CMGS=15123362860\r\n";
	
	p1_length=strlen(p1);
	p2_length=strlen(p2);
	p3_length=strlen(p3);

	fdcom = PortOpen(&portinfo);
	if(fdcom<0){
		printf("Error: open serial port error.\n");
		exit(1);
	}
	PortSet(fdcom, &portinfo);
	SendLen = PortSend(fdcom, p1, p1_length);
	if(SendLen>0){
				printf("No %d send %d data information.\n", i, SendLen);
			}
			else{
				printf("Error: send failed.\n");
			}
	SendLen = PortSend(fdcom, p2, p2_length);
	if(SendLen>0){
				printf("No %d send %d data information.\n", i, SendLen);
			}
			else{
				printf("Error: send failed.\n");
			}
	SendLen = PortSend(fdcom, p3, p3_length);
	if(SendLen>0){
				printf("No %d send %d data information.\n", i, SendLen);
			}
			else{
				printf("Error: send failed.\n");
			}

	char *info_x="11.342",*info_y="6.5643";
	//int decpt,sign;
	//gcvt(x,5,info_x);
    info_x_length=strlen(info_x);
	//gcvt(y,5,info_y);
	PortSend(fdcom, info_x, info_x_length);

	strcat(info_y,"/x1a");
	info_y_length=strlen(info_y);
	SendLen = PortSend(fdcom, info_y, info_y_length);
	if(SendLen>0){
				printf("No %d send %d data information.\n", i, SendLen);
			}
			else{
				printf("Error: send failed.\n");
			}
	sleep(10);
}



static int verbose =0;

int main (int argc,char*argv []) 
{ 
	int next_option; 
	const char*const short_options ="hd:v:f:s:";
	const struct option long_options [] ={
		{"help",0,NULL,'h' }, 
		{"device",1,NULL,'d' }, 
		{"framebuffer",1,NULL,'f' }, 
		{"verbose",1,NULL,'v' }, 
		{"size",0,NULL,'s' }, 
		{NULL,0,NULL,0 }}; 

	const char*output_filename =NULL; 

	program_name =argv [0]; 
	do { 
		next_option =getopt_long (argc,argv,short_options, long_options,NULL); 
		switch (next_option) 
		{ 
		case 'h':/*-h or --help */ 
			print_usage (stdout,0); 
		case 's':/*-s or --size */ 
			//ip =optarg; 
			sscanf(optarg, "%d:%d", &(capinfo.width), &(capinfo.height));
			break; 
		case 'f':/*-f or --framebuffer */ 
			fb_dev_name = optarg;
			break; 
		case 'd':/*-b or --device */ 
			strcpy(capinfo.device, optarg);
			break; 
		case 'v':/*-v or --verbose */ 
			sscanf(optarg, "%d", &verbose);
			ng_debug = verbose;
			break; 
		case '?':/*The user specified an invalid option.*/ 
			print_usage (stderr,1); 
		case -1:/*Done with options.*/ 
			break; 
		default:/*Something else:unexpected.*/ 
			print_usage (stderr,1); 
		}
	}while (next_option !=-1);  
    printf("video %s caputure: %dx%d\n", capinfo.device, capinfo.width, capinfo.height);

	pthread_t thread_id1,thread_id2,thread_id3;
	pthread_attr_t attr;
	struct sched_param param;
    pthread_attr_init(&attr);
    pthread_attr_getschedparam(&attr,&param);

    pthread_create(&thread_id2,&attr,(void*)&send_gprs,NULL);
    pthread_create(&thread_id3,&attr,(void*)&get_nd,NULL); 
    param.sched_priority++;
	pthread_attr_setschedparam(&attr,&param);
    pthread_create(&thread_id1,&attr,(void*)&capture,NULL);

    pthread_join(thread_id1,NULL);
	pthread_join(thread_id3,NULL);
    pthread_join(thread_id2,NULL);
	return capture();
} 


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -