0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

GTK渲染攝像頭圖像數(shù)據(jù)

嵌入式技術(shù) ? 來源:嵌入式技術(shù) ? 作者:嵌入式技術(shù) ? 2022-12-01 09:19 ? 次閱讀

1.GDK簡介

繪圖工具集(GDK,Graphics Drawing Kit)是在GTK+ 和特定操作系統(tǒng)的應(yīng)用編程接口(API,Application Program Interface)之間的低級繪圖制層—— Linux的API是Xlib。由于GTK和機器的API之間沒有直接接口,移植GTK+就成為移植GLIB和GDK的問題。GDK提供像元的繪制能力以及低層的窗口建立和處理能力。對許多應(yīng)用來說,使用構(gòu)件時最方便的,但是,如果你想用GTK+編寫模擬時鐘的應(yīng)用程序,由于它沒有繪制時鐘表面的能力,實現(xiàn)這樣的任務(wù)就有困難了。使用帶GDK的繪圖區(qū)(drawing area)構(gòu)件代替封裝(canned)的構(gòu)件,即可繪制出任何你需要繪制的內(nèi)容。

2.繪圖子程序

使用GDK子程序編寫應(yīng)用程序并不比直接使用Xlib好多少。幸運的是,GTK+提供一種構(gòu)件,即繪圖區(qū)(drawing area)構(gòu)件。你可以用它來建立需要的手工繪圖的應(yīng)用。可以像使用其它GTK+構(gòu)件一樣使用繪圖區(qū)構(gòu)件。而且,使用該構(gòu)件建立依賴圖形的應(yīng)用也足夠靈活,這種方法的優(yōu)點是可以在同一應(yīng)用中使用GTK+和GDK。GTK+提供菜單、工具條和其它構(gòu)件,支持在繪圖區(qū)構(gòu)件內(nèi)進行繪圖,而GDK則提供用于繪制線、框、像元、圓和其它圖形的API。

每個GDK子程序至少取兩個參數(shù):可繪制區(qū)(GdkDrawable)和GDKGC。GdkDrawable表示可以在他上面進行繪圖的區(qū)域,GDKGC包函數(shù)顏色和字體信息以及其它繪圖信息。

3.Linux下攝像頭編程

V4L2是Video for linux2的簡稱,為linux中關(guān)于視頻設(shè)備的內(nèi)核驅(qū)動。在Linux中,視頻設(shè)備是設(shè)備文件,可以像訪問普通文件一樣對其進行讀寫,攝像頭在/dev/video*下,如果只有一個視頻設(shè)備,通常為/dev/video0。

V4L2是針對uvc免驅(qū)usb設(shè)備的編程框架 ,主要用于采集usb攝像頭等。

  • 攝像頭框架編程步驟

(1)打開攝像頭設(shè)備(/dev/video0 、/dev/video1 )。
(2)設(shè)置圖像格式:VIDIOC_S_FMT(視頻捕獲格式、圖像顏色數(shù)據(jù)格式、圖像寬和高)。
(3)申請緩沖區(qū):VIDIOC_REQBUFS(緩沖區(qū)數(shù)量、緩沖映射方式、視頻捕獲格式)。
(4)將緩沖區(qū)映射到進程空間:VIDIOC_QUERYBUF(要映射的緩沖區(qū)下標(biāo)、緩沖映射方式、視頻捕獲格式)。
(5)將緩沖區(qū)添加到隊列中:VIDIOC_QBUF(映射的緩沖區(qū)下標(biāo)、緩沖映射方式、視頻捕獲格式)。
(6)開啟攝像頭采集:VIDIOC_STREAMON (視頻捕獲格式)。
(7)從采集隊列中取出圖像數(shù)據(jù)VIDIOC_DQBUF,進行圖像渲染。

  • 攝像頭采集示例
#include 
#include  //攝像頭頭文件
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "camera.h"
/*攝像頭初始化*/
int Camera_Init(struct _CAMERA *video_info)
{
	int i=0;
	/*1.打開攝像頭設(shè)備*/
	int fd=open(VIDEO_DEV,2);
	if(fd<0)return -1;//攝像頭打開失敗
	/*2.設(shè)置攝像頭捕獲格式*/
	struct v4l2_format v4l2fmt;
	memset(&v4l2fmt,0,sizeof(v4l2fmt));//初始化結(jié)構(gòu)體
	v4l2fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//視頻捕獲格式
	v4l2fmt.fmt.pix.width=640;//圖像寬度
	v4l2fmt.fmt.pix.height=480;//圖像高度
	v4l2fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;//YUYV顏色編碼格式
	if(ioctl(fd,VIDIOC_S_FMT,&v4l2fmt))return -2;//設(shè)置格式失敗
	printf("采集圖像大小:%d*%dn",v4l2fmt.fmt.pix.width,v4l2fmt.fmt.pix.height);
	video_info->image_w=v4l2fmt.fmt.pix.width;
	video_info->image_h=v4l2fmt.fmt.pix.height;
	/*3.申請緩沖區(qū)*/
	struct v4l2_requestbuffers v4l2reqbuf;
    memset(&v4l2reqbuf,0,sizeof(v4l2reqbuf));//初始化結(jié)構(gòu)體
	v4l2reqbuf.count=4;//申請的緩沖區(qū)個數(shù)
	v4l2reqbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//視頻捕獲格式
	v4l2reqbuf.memory=V4L2_MEMORY_MMAP;//內(nèi)存映射
	if(ioctl(fd,VIDIOC_REQBUFS,&v4l2reqbuf))return -3;//申請緩沖區(qū)失敗
	printf("申請的緩沖區(qū)個數(shù):%dn",v4l2reqbuf.count);
	/*4.將緩沖區(qū)映射到進程空間*/
	struct v4l2_buffer v4l2buf;
	memset(&v4l2buf,0,sizeof(v4l2buf));//初始化結(jié)構(gòu)體
	v4l2buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//視頻捕獲格式
	v4l2buf.memory=V4L2_MEMORY_MMAP;//內(nèi)存映射
	for(i=0;ivideo_buff[i]=mmap(NULL,v4l2buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,v4l2buf.m.offset);
		printf("video_buff[%d]=%pn",i,video_info->video_buff[i]);
	}
	video_info->video_len=v4l2buf.length;//yuv圖像數(shù)據(jù)字節(jié)數(shù)
	printf("yuv_size=%dn",video_info->video_len);
	/*5.將映射的空間添加到采集隊列*/
	memset(&v4l2buf,0,sizeof(v4l2buf));//初始化結(jié)構(gòu)體
	v4l2buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//視頻捕獲格式
	v4l2buf.memory=V4L2_MEMORY_MMAP;//內(nèi)存映射
	for(i=0;ivideo_fd=fd;//攝像頭描述符
	return 0;//初始化成功返回0
}
;i++)>;i++)>

4.GDK渲染

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include "camera.h"
struct _CAMERA video_info;/*設(shè)備結(jié)構(gòu)體信息*/
int width,height;//圖像寬高
guchar *rgbbuf=NULL;//保存rgb顏色數(shù)據(jù)
GtkWidget *drawarea;

int on_delete_event(GtkWidget *widget,GdkEvent *event,gpointer data)
{  
	/*釋放資源*/
	g_print("釋放資源n");
	for(int i=0;i<4;i++)
	{
		munmap(video_info.video_buff[i],video_info.video_len);
	}
	free(rgbbuf);
	close(video_info.video_fd); 
	gtk_main_quit();
	return FALSE;
}


int draw_image(GtkWidget *widget,GdkEvent *event,gpointer data)
{ 
 	gdk_draw_rgb_image(widget->window,widget->style->fg_gc[GTK_STATE_NORMAL],0,0,width,height,GDK_RGB_DITHER_NONE,rgbbuf,width*3);
	return FALSE;
}
/*YUYV轉(zhuǎn)RGB888*/
void yuv_to_rgb(unsigned char *yuv_buffer,unsigned char *rgb_buffer,int iWidth,int iHeight)
{
	int x;
	int z=0;
	unsigned char *ptr = rgb_buffer;
	unsigned char *yuyv= yuv_buffer;
	for (x = 0; x < iWidth*iHeight; x++)
	{
		int r, g, b;
		int y, u, v;
		if (!z)
		y = yuyv[0] << 8;
		else
		y = yuyv[2] << 8;
		u = yuyv[1] - 128;
		v = yuyv[3] - 128;
		b = (y + (359 * v)) >> 8;
		g = (y - (88 * u) - (183 * v)) >> 8;
		r = (y + (454 * u)) >> 8;
		*(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);
		*(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
		*(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
		if(z++)
		{
			z = 0;
			yuyv += 4;
		}
	}
}


int read_data(GtkWidget * widget,GdkEvent * event,gpointer data)
{    
	/*讀取攝像頭圖像數(shù)據(jù)*/
	struct v4l2_buffer v4l2buf;
	memset(&v4l2buf,0,sizeof(v4l2buf));
	//初始化結(jié)構(gòu)體
	v4l2buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//視頻捕獲格式
	v4l2buf.memory=V4L2_MEMORY_MMAP;//內(nèi)存映射
	if(ioctl(video_info.video_fd,VIDIOC_DQBUF,&v4l2buf)==-1)
	{
		printf("Dqbuf failedn");
		return FALSE;
	}
	//將yuyv轉(zhuǎn)換為rgb24
	yuv_to_rgb(video_info.video_buff[v4l2buf.index],rgbbuf,width,height);
	/*保證線程安全,上鎖*/
	gdk_threads_enter();
	gdk_draw_rgb_image(drawarea->window,drawarea->style->fg_gc[GTK_STATE_NORMAL],0,0,width,height,GDK_RGB_DITHER_NONE,rgbbuf,width*3);
	/*保證線程安全,釋放*/
	gdk_threads_leave();
	ioctl(video_info.video_fd,VIDIOC_QBUF,&v4l2buf);//將緩沖區(qū)添加回采集隊列
	return TRUE;
}


int main (int argc,char *argv[])
{
	/*攝像頭初始化*/
	int ret=Camera_Init(&video_info);
	if(ret)
	{
		printf("攝像頭打開失敗ret=%dn",ret);
		return 0;
	}
	/*圖像寬高*/
	width=video_info.image_w;
	height=video_info.image_h;
	rgbbuf=malloc(width*height*3);
	/* init Gtk */
	GtkWidget *window;
	/*gtk初始化*/
	gtk_init(&argc,&argv);
	/*創(chuàng)建窗口*/
	window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(window),"攝像頭采集");
	/*固定窗口大小*/
	gtk_window_set_resizable (GTK_WINDOW(window),FALSE);
	
	/*連接信號*/
	g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(on_delete_event),NULL);

	/*初始化gdk的rgb*/
	gdk_rgb_init();
	gtk_widget_push_visual(gdk_rgb_get_visual());
	gtk_widget_push_colormap(gdk_rgb_get_cmap());
	/*創(chuàng)建繪圖區(qū)域*/
	drawarea=gtk_drawing_area_new();
	gtk_widget_pop_visual();
	gtk_widget_pop_colormap();
	
	gtk_container_add(GTK_CONTAINER(window),drawarea);
	g_signal_connect(G_OBJECT(drawarea),"expose_event",G_CALLBACK(draw_image),NULL);
	guint id=gtk_idle_add((GtkFunction)read_data,NULL);
	/*設(shè)置窗口大小*/
	gtk_widget_set_size_request(GTK_WIDGET(drawarea),width,height);
	gtk_widget_show_all(window);
	gtk_main();
	gdk_threads_leave();
	return 0;
}

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 圖像數(shù)據(jù)
    +關(guān)注

    關(guān)注

    0

    文章

    50

    瀏覽量

    11207
  • 攝像頭
    +關(guān)注

    關(guān)注

    59

    文章

    4752

    瀏覽量

    94394
收藏 人收藏

    評論

    相關(guān)推薦

    USB攝像頭圖像采集

    一個比較簡單的編程,實現(xiàn)簡單的USB攝像頭圖像顯示
    發(fā)表于 11-12 15:48

    USB攝像頭圖像拍攝

      請問labview如何能實現(xiàn)使用USB攝像頭進行時間間隔拍攝圖像,并保存到數(shù)據(jù)庫。請高手指點一二,謝謝
    發(fā)表于 11-26 11:12

    關(guān)于攝像頭圖像采集問題

    `我用labview實現(xiàn)電腦攝像頭圖像采集,運行過程中出現(xiàn)問題了,截圖如下,還請高手指教!謝謝啦`
    發(fā)表于 05-25 16:59

    u***攝像頭的使用

    u***攝像頭想要采集圖像信息,通過單片機驅(qū)動之后無線傳輸給pc終端。第一步是不是要做好u***攝像頭和單片機之間的驅(qū)動啊 沒做過攝像頭這方面 應(yīng)該從哪些地方學(xué)起啊u***和單片機之間
    發(fā)表于 02-06 11:59

    攝像頭采集圖像處理

    就可以做到實際中圖像處理并且做到無線傳輸。這樣的圖像采集處理功能在監(jiān)控系統(tǒng)和在線檢測都有很大的前景。 本作品是基于安芯一號SLH89F5162單片機,驅(qū)動并控制帶FIFO的OV7670CMOS攝像頭
    發(fā)表于 11-05 22:35

    【轉(zhuǎn)載分享】USB攝像頭采集圖像

    `如果你有USB攝像頭,就是隨便的那種。平時QQ視頻的就可以了(筆記本上自帶的攝像頭,也可以),那你就可以用LabVIEW進行圖像采集了。注意:由于LabVIEW8.6是個神奇的版本,有些函數(shù)改版了
    發(fā)表于 03-02 11:36

    USB攝像頭怎么調(diào)圖像效果?

    有沒有做USB攝像頭的,會調(diào)圖像效果的?
    發(fā)表于 11-14 16:38

    labview圖像采集怎么無法連接USB攝像頭

    在labview中圖像采集無法連接USB攝像頭,只能連接電腦自帶攝像頭是怎么回事,求指教
    發(fā)表于 05-08 17:55

    【案例分享】機器視覺應(yīng)用的攝像頭設(shè)計

    接收器等終端數(shù)據(jù)采集系統(tǒng)。幀接收器在存儲器中存儲數(shù)據(jù),隨后可由主機應(yīng)用軟件對數(shù)據(jù)進行存取以處理和控制。攝像頭連接到主機的電氣接口包括:1 火線 IEEE 1394 接口 2 USB 接
    發(fā)表于 07-19 04:30

    回收手機攝像頭,收購攝像頭芯片

    芯片,國外的有索尼,OV,鎂光,聯(lián)詠,安霸,國內(nèi)的有比亞迪微,格科微,銳芯微,思比科,中星微等等,這些品牌的圖像傳感器我們都高價回收。全新的感光芯片,攝像頭模組,拆機的CCD板,拆機的攝像頭,我們統(tǒng)統(tǒng)
    發(fā)表于 07-14 17:53

    【FPGA DEMO】Lab 4:攝像頭HDMI顯示(高速--HDMI&攝像頭)

    `項目名稱:攝像頭HDMI顯示。具體要求:攝像頭采集的視頻圖像數(shù)據(jù)通過HDMI實時顯示。 系統(tǒng)設(shè)計:Perf-V開發(fā)板可以連接高速口——HDMI&
    發(fā)表于 07-30 15:21

    如何讀取攝像頭圖像數(shù)據(jù)

    如何讀取攝像頭圖像數(shù)據(jù)?
    發(fā)表于 11-08 07:49

    OV7725攝像頭圖像處理設(shè)計實現(xiàn)

    這次更新圖像處理部分,主要是為了提取出=信標(biāo)燈,并求出信標(biāo)燈在圖像中的坐標(biāo)。程序代碼可完善的地方還有很多,主要還是提供一種當(dāng)時我們參賽的解決思路,拋磚引玉。攝像頭采用中斷的方式來采集圖像
    發(fā)表于 01-11 08:03

    用QT5的qml和gstreamer來渲染攝像頭圖像,qml在顯示相機的時候經(jīng)常會報錯的原因?

    你好我是用QT5的qml和gstreamer來渲染攝像頭圖像,但是我的CPU和內(nèi)存占用率很高,但是當(dāng)我用gst-launch-1.0顯示攝像頭實時
    發(fā)表于 04-06 06:57

    華為Mate30Pro最新渲染圖曝光,與之前攝像頭采用“十”字排列不同

    8月28日消息 近日,9TechEleven曝光了華為Mate 30 Pro最新渲染圖,和之前攝像頭采用“十”字排列不同,這次的渲染攝像頭組合為正方形排列。
    的頭像 發(fā)表于 08-28 08:58 ?3446次閱讀