導航:首頁 > 操作系統 > linux對攝像頭圖像採集

linux對攝像頭圖像採集

發布時間:2022-11-16 09:42:14

㈠ 如何實現嵌入式linux下USB攝像頭視頻採集

在linux下所有設備都是文件。所以對攝像頭的操作其實就是對文件的操作。USB攝像頭的設備文件就是在/dev目錄下的video0(假如只有一個攝像頭)。在linux下操作攝像頭就是使用v4l2對攝像頭進行視頻的操作,操作步驟如下

1. 打開設備文件。

int fd=open(」/dev/video0″,O_RDWR);

2. 取得設備的capability,看看設備具有什麼功能,比如是否具有視頻輸入,或者音頻輸入輸出等。VIDIOC_QUERYCAP,struct v4l2_capability

v4l2_std_idstd;
do{
ret=ioctl(fd,VIDIOC_QUERYSTD,&std);
}while(ret==-1&&errno==EAGAIN);
switch(std){
caseV4L2_STD_NTSC:
//……
caseV4L2_STD_PAL:
//……
}

3. 選擇視頻輸入,一個視頻設備可以有多個視頻輸入。VIDIOC_S_INPUT,struct v4l2_input(可不要)

4. 設置視頻的制式和幀格式,制式包括PAL,NTSC,幀的格式個包括寬度和高度等。

VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format

structv4l2_formatfmt;
memset(&fmt,0,sizeof(fmt));
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width=320;
fmt.fmt.pix.height=240;
fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_JPEG;
if(ioctl(fd,VIDIOC_S_FMT,&fmt)<0)
{
printf("setformatfailed ");
//return0;
}

5. 向驅動申請幀緩沖,一般不超過5個。struct v4l2_requestbuffers

structv4l2_requestbuffersreq;
memset(&req,0,sizeof(req));
req.count=4;
req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory=V4L2_MEMORY_MMAP;
if(ioctl(fd,VIDIOC_REQBUFS,&req)==-1)
{
perror("VIDIOC_REQBUFSerror ");
//return-1;
}

6.申請物理內存

將申請到的幀緩沖映射到用戶空間,這樣就可以直接操作採集到的幀了,而不必去復制。將申請到的幀緩沖全部入隊列,以便存放採集到的數據.VIDIOC_QBUF,struct v4l2_buffer

VideoBuffer*buffers=calloc(req.count,sizeof(VideoBuffer));
printf("sizeof(VideoBuffer)is%d ",sizeof(VideoBuffer));
structv4l2_bufferbuf;
for(numBufs=0;numBufs<req.count;numBufs++)
{
memset(&buf,0,sizeof(buf));
buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory=V4L2_MEMORY_MMAP;
buf.index=numBufs;
if(ioctl(fd,VIDIOC_QUERYBUF,&buf)<0)
{
printf("VIDIOC_QUERYBUFerror ");
//return-1;
}
printf("buflenis%d ",sizeof(buf));
//內存映射
buffers[numBufs].length=buf.length;
buffers[numBufs].offset=(size_t)buf.m.offset;
buffers[numBufs].start=mmap(NULL,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,buf.m.offset);
printf("buffers.length=%d,buffers.offset=%d,buffers.start[0]=%d ",buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);
printf("buf2lenis%d ",sizeof(buffers[numBufs].start));
if(buffers[numBufs].start==MAP_FAILED)
{
perror("bufferserror ");
//return-1;
}
if(ioctl(fd,VIDIOC_QBUF,&buf)<0)
{
printf("VIDIOC_QBUFerror ");
//return-1;
}
}

7. 開始視頻的採集。

enumv4l2_buf_typetype;
type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_STREAMON,&type)<0)
{
printf("VIDIOC_STREAMONerror ");
//return-1;
}

8. 出隊列以取得已採集數據的幀緩沖,取得原始採集數據。VIDIOC_DQBUF, 將緩沖重新入隊列尾,這樣可以循環採集。VIDIOC_QBUF

if(ioctl(fd,VIDIOC_DQBUF,&buf)<0)
{
perror("VIDIOC_DQBUFfailed. ");
//return-1;
}
buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory=V4L2_MEMORY_MMAP;
unsignedchar*ptcur=buffers[numBufs].start;
DEBUG("buf.bytesused=%d ",buf.bytesused);
inti1;
for(i1=0;i1<buf.bytesused;i1++)
{
if((buffers[numBufs].start[i1]==0x000000FF)&&(buffers[numBufs].start[i1+1]==0x000000C4))
{
DEBUG("huffmantablefinded! buf.bytesused=%d FFC4=%d ",buf.bytesused,i1);
break;
}
}
if(i1==buf.bytesused)printf("huffmantabledon'texist! ");
inti;
for(i=0;i<buf.bytesused;i++)
{
if((buffers[numBufs].start[i]==0x000000FF)&&(buffers[numBufs].start[i+1]==0x000000D8))break;
ptcur++;
}
DEBUG("i=%d,FF=%02x,D8=%02x ",i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);
intimagesize=buf.bytesused-i;
DEBUG("buf.bytesused=%d ",buf.bytesused);
DEBUG("imagesize=%d ",imagesize);

9. 停止視頻的採集。VIDIOC_STREAMOFF

10. 關閉視頻設備。close(fd);

㈡ linux下QT+V4l2+FFMPEG攝像頭採集程序,怎麼配置

這個軟體是你自己寫的嗎?在V4L2編程中在圖像處理的時候就有一個參數是讓截取的圖像改變格式的,目前V4L2的支持大部分圖像格式!

㈢ linux下怎麼樣進行攝像頭編程

在linux下所有設備都是文件。所以對攝像頭的操作其實就是對文件的操作。USB攝像頭的設備文件就是在/dev目錄下的video0(假如只有一個攝像頭)。在linux下操作攝像頭就是使用v4l2對攝像頭進行的操作,操作步驟如下

㈣ Linux v4l2圖片採集問題

源碼中:
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
ioctl (fd, VIDIOC_S_FMT, &fmt);
指定了採集圖像的格式為YUYV格式。
要像採集成JPEG圖像,得查詢一下攝像頭是否有相應功能,如果沒有相應功能即使將fmt設置為jpeg最終採集到的還是yuyv格式。
yuyv可以轉換為bmp數據,然後調用jpeglib庫轉換為jpg圖像,稍稍有些麻煩,但沒辦法硬體不足就要用軟體來彌補了。
至於你說的read沒讀到數據,我現在沒有開發環境,沒法測試。

㈤ linux 視頻監控

本系統使用linux操作系統,採用H.264/AVC圖像壓縮標准利用 rP協議,和多線程式控制制實時地傳輸視頻數據,同時合理地設置緩存和利用有效的錯誤隱藏技術,使監控終端能得到較好的監控效果。能在帶寬有限的情況下很好地實現監控效果,同時,監控中心在邏輯上採用了分層的結構,更利於系統的組建,具有很好的擴展能力,方便了跨地域的大型監控系統的組建,具有較好的發展前景。

l 視頻監控伺服器總體設計
視頻監控伺服器解決方案和實現的流程
本監控方案的結構所示。基於分層網路的視頻監控系統由監控中心,遠程監控終端和網路構成。每個監控中心都由監控伺服器、監控終端、監控前端、攝像頭、報警器和區域網組成。監控伺服器負責本地區域網用戶的管理,音視頻數據、報警信號的轉發、音視頻數據的本地存儲,管理監控前端,給遠程用戶或其他監控中心提供監控資源訪問服務等。監控前端是一個Linux的嵌入式系統,它採集攝像頭的視頻數據,並用H.264標准壓縮,把壓縮數據打包並發送到IP網路上,也可以把音頻信號壓縮並打包和發送到IP網路;它支持雲台控制協議;還支持報警器的信號編碼。在物理結構上,每個監控中心都是一個功能完備的監控系統,它們是同級的,沒有地域區分;在邏輯結構上,監控中心劃分成樹狀的層次結構,每個監控中心由它上層的監控中心(稱為分控中心)管理,最上層的監控中心是總控中心。這樣的系統結構既可以使每個控制中心單獨組成監控系統,又可以通過網路分層連接起來組成規模較大的監控系統,具有很好的擴展能力,適用於各種規模的實時監控。當上層的監控中心癱瘓或是網路發生故障的時候,每個監控中心還能獨立正常地工作,提高了監控系統的健壯性。用戶可以通過登錄遠程監控終端或者監控中心內部的監控終端,通過伺服器的身份認證並獲取操作許可權後對系統進行監控和管理。
1)監控前端的設計
監控前端是一個基於ARM處理器的Linu)【嵌入式系統。監控前端的主要硬體模塊如圖2所示,監控前端硬體部分可分為ARM CPU、系統內存、乙太網介面、H.264編碼模塊、圖像採集模塊、視頻存儲模塊,Flash存儲模塊,視頻伺服器管理模塊,網路傳送數據等幾個部分。各模塊由CPU統一管理和調度,Flash存儲模塊負責存放linux嵌入式操作系統和各部分硬體驅動程序。攝像頭的視頻信號通過模數轉換以後得到視頻圖像幀的數字信號,數字信號通過H.264編碼模塊壓縮後的數據存放在H.264編碼模塊的緩沖區內,用戶可以通過對WEB伺服器的操作,讀取或修改這些壓縮信號,最後圖像信號到達網路傳送模塊,將經過H.264編碼後的數據封裝成RTP包,同時周期地發送RTCP包,以流媒體的方式傳送到遠程的客服端。
2)客服端(監控終端的設計)
監控終端軟體的運行平台是基於Windows操作系統的PC機,可以高速連接到公共網路。監控終端軟體採用了vi—sualc++MFC Windows界面編程的文檔一視圖編程模式,系統的類圖設計如圖3所示。CClientsocket類負責接收、解析網路數據包和發送用戶命令。網路接收到的RTPARTCP包經過C~lientsocket類解析以後,如果是視頻數據,則放在CVideoBufer類裡面,如果是音頻數據則放CAudioBufer類裡面,其它的如報警,重啟,刪除等消息則放在C_ConTrolMes—sages類buffer里,CVideobufer是個圖像緩沖區,CAudiobufer是音頻緩沖區,我們通過線程同步,來實現音視頻的同步播放。通過CConTrolMessages類里的成員函數,來響應用戶需要的單路多放,回查,自動報警設置等功能。

㈥ 如何利用Video4Linux獲取攝像頭數據

1. 攝像頭的安裝

在Linux下常用的攝像頭驅動是spca5xx。這個網站還給出了這款驅動支持的攝像頭的種類。另外,ov511晶元直接就支持Linux,使用者款晶元的攝像頭有網眼V2000。我使用的是網眼V2000的攝像頭,和Z-Star
301p+現代7131R晶元的攝像頭。後一種需要spca5xx的驅動。關於spca5xx的安裝方法,網上有很多介紹,這里就不說了。

2. 攝像頭的調試

安裝好攝像頭後,為了測試攝像頭能否正常工作,可以用一下軟體。比較著名的是xawtv,在網上搜以下可以下載到。安裝好後,打開xawtv則可以調試攝像頭。

3. Video4Linux 編程獲取數據

現有的video4linux有兩個版本,v4l和v4l2。本文主要是關於v4l的編程。利用v4l API獲取視頻圖像一般有以下幾步:

a> 打開設備

b> 設置設備的屬性,比如圖像的亮度,對比度等等

c> 設定傳輸格式和傳輸方式

d> 開始傳輸數據,一般是一個循環,用以連續的傳輸數據

e> 關閉設備

下面具體介紹v4l編程的過程。首先指出,在video4linux編程時要包含頭文件,其中包含了video4linux的數據結構和函數定義。

1)v4l的數據結構

在video4linux API中定義了如下數據結構,詳細的數據結構定義可以參考v4l API的文檔,這里就編程中經常使用的數據結構作出說明。

首先我們定義一個描述設備的數據結構,它包含了v4l中定義的所有數據結構:
typedef struct
_v4ldevice
{int fd;//設備號
struct video_capability capability;
struct
video_channel channel[10];
struct video_picture picture;
struct video_clip
clip;
struct video_window window;
struct video_capture capture;
struct
video_buffer buffer;
struct video_mmap mmap;
struct video_mbuf
mbuf;
struct video_unit unit;
unsigned char
*map;//mmap方式獲取數據時,數據的首地址
pthread_mutex_t mutex;
int frame;
int
framestat[2];
int overlay;
}v4ldevice;
下面解釋上面這個數據結構中包含的數據結構,這些結構的定義都在中。
* struct
video_capability
name[32] Canonical name for this interface
type Type of
interface
channels Number of radio/tv channels if appropriate
audios
Number of audio devices if appropriate
maxwidth Maximum capture width in
pixels
maxheight Maximum capture height in pixels
minwidth Minimum capture
width in pixels
minheight Minimum capture height in pixels

這一個數據結構是包含了攝像頭的屬性,name是攝像頭的名字,maxwidth maxheight是攝像頭所能獲取的最大圖像大小,用像素作單位。

在程序中,通過ioctl函數的VIDIOCGCAP控制命令讀寫設備通道已獲取這個結構,有關ioctl的使用,比較復雜,這里就不說了。下面列出獲取這一數據結構的代碼:
int v4lgetcapability(v4ldevice *vd)
{
if(ioctl(vd->fd,
VIDIOCGCAP, &(vd->capability)) < 0)
{
v4lperror("v4lopen:VIDIOCGCAP");
return -1;
}
return 0;
}
*
struct video_picture
brightness Picture brightness
hue Picture hue (colour
only)
colour Picture colour (colour only)
contrast Picture
contrast
whiteness The whiteness (greyscale only)
depth The capture depth
(may need to match the frame buffer depth)
palette Reports the palette that
should be used for this image

這個數據結構主要定義了圖像的屬性,諸如亮度,對比度,等等。這一結構的獲取通過ioctl發出VIDIOCGPICT控制命令獲取。
* struct video_mbuf
size The number of bytes to
map
frames The number of frames
offsets The offset of each frame

這個數據結構在用mmap方式獲取數據時很重要:

size表示圖像的大小,如果是640*480的彩色圖像,size=640*480*3

frames表示幀數

offsets表示每一幀在內存中的偏移地址,通過這個值可以得到數據在圖像中的地址。

得到這個結構的數據可以用ioctl的VIDIOCGMBUF命令。源碼如下:
int v4lgetmbuf(v4ldevice
*vd)
{
if(ioctl(vd->fd, VIDIOCGMBUF, &(vd->mbuf))<0)
{
v4lperror("v4lgetmbuf:VIDIOCGMBUF");
return -1;
}
return
0;
}

而數據的地址可以有以下方式計算:
unsigned char
*v4lgetaddress(v4ldevice *vd)
{
return (vd->map +
vd->mbuf.offsets[vd->frame]);
}

2)獲取影像mmap方式。

在video4Linux下獲取影像有兩種方式:overlay和mmap。由於我的攝像頭不支持overlay方式,所以這里只談mmap方式。

mmap方式是通過內存映射的方式獲取數據,系統調用ioctl的VIDIOCMCAPTURE後,將圖像映射到內存中,然後可以通過前面的v4lgetmbuf(vd)函數和v4lgetaddress(vd)函數獲得數據的首地址,這是李可以選擇是將它顯示出來還是放到別的什麼地方。

下面給出獲取連續影像的最簡單的方法(為了簡化,將一些可去掉的屬性操作都去掉了):
char*
devicename="/dev/video0";
char* buffer;
v4ldevice device;
int width =
640;
int height = 480;
int frame =
0;
v4lopen("/dev/video0",&device);//打開設備
v4lgrabinit(&device,width,height);//初始化設備,定義獲取的影像的大小
v4lmmap(&device);//內存映射
v4lgrabstart(&device,frame);//開始獲取影像
while(1){
v4lsync(&device,frame);//等待傳完一幀
frame
= (frame+1)%2;//下一幀的frame
v4lcapture(&device,frame);//獲取下一幀
buffer =
(char*)v4lgetaddress(&device);//得到這一幀的地址
//buffer給出了圖像的首地址,你可以選擇將圖像顯示或保存......
//圖像的大小為
width*height*3
..........................
}
轉載僅供參考,版權屬於原作者。祝你愉快,滿意請採納哦

㈦ linux系統下的tq2440的mose攝像頭採集的圖像存儲在哪

open函數 打開串口設備close函數 關閉串口設備tcgetattr函數 得到設備設置狀態tcsetattr函數 設置設備tcflush函數 刷清cfgetispeed函數 得到輸入波特率cfgetospeed函數 得到輸出波特率cfsetispeed函數 設置輸入波特率cfsetospeed函數 設置輸出波特率read函數 讀設備,接收數據write函數 寫設備,發送數據 每個函數的具體用法參考linux C語言參考手冊參考termios.h中的函數,大多數都在這個頭文件中。

㈧ linux v4l2圖像採集

如果要自己實現的話,那麼第9步你能通過VIDIOC_DQBUF請求來獲取到一幀視頻。
如果你想存成AVI的,那麼你得了解AVI文件格式。avi是一種RIFF的實現balabalabala......
總之你大概在初始化的時候就把avi的文件頭寫好(strh strl之類的,具體看手冊),然後第九步
的時候取出一幀數據,把長度和偏移連同這幀數據寫入文件,同時保存下索引。
當寫入全部的視頻幀後再把索引寫入文件,最後關閉錄像文件,停止視頻採集。

如果覺得自己實現麻煩,就移植個ffmpeg啥的,直接支持v4l2和avi容器,一條命令就搞定了

㈨ linux下怎樣進行攝像頭編程

在linux下所有設備都是文件。所以對攝像頭的操作其實就是對文件的操作。USB攝像頭的設備文件就是在/dev目錄下的video0(假如只有一個攝像頭)。在linux下操作攝像頭就是使用v4l2對攝像頭進行的操作,操作步驟如下

  1. 打開設備文件。

  2. int fd=open(」/dev/video0″,O_RDWR);

  3. 2. 取得設備的capability,看看設備具有什麼功能,比如是否具有輸入,或者音頻輸入輸出等。VIDIOC_QUERYCAP,struct v4l2_capability

  4. v4l2_std_id std;

  5. do {

  6. ret= ioctl(fd, VIDIOC_QUERYSTD, std);

  7. } while (ret == -1 errno == EAGAIN);

  8. switch (std) {

  9. case V4L2_STD_NTSC:

  10. //……

  11. case V4L2_STD_PAL:

  12. //……

  13. }

  14. 3. 選擇輸入,一個設備可以有多個輸入。VIDIOC_S_INPUT,struct v4l2_input(可不要)

  15. 4. 設置的制式和幀格式,制式包括PAL,NTSC,幀的格式個包括寬度和高度等。

  16. VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format

  17. struct v4l2_format fmt;

  18. memset ( fmt, 0, sizeof(fmt) );

  19. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  20. fmt.fmt.pix.width = 320;

  21. fmt.fmt.pix.height = 240;

  22. fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;

  23. if (ioctl(fd, VIDIOC_S_FMT, fmt) < 0)

  24. {

  25. printf("set format failed ");

  26. //return 0;

  27. }

  28. 5. 向驅動申請幀緩沖,一般不超過5個。struct v4l2_requestbuffers

  29. struct v4l2_requestbuffers req;

  30. memset(req, 0, sizeof (req));

  31. req.count = 4;

  32. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  33. req.memory = V4L2_MEMORY_MMAP;

  34. if (ioctl(fd,VIDIOC_REQBUFS,req) == -1)

  35. {

  36. perror("VIDIOC_REQBUFS error ");

  37. //return -1;

  38. }

  39. 6.申請物理內存

  40. 將申請到的幀緩沖映射到用戶空間,這樣就可以直接操作採集到的幀了,而不必去復制。將申請到的幀緩沖全部入隊列,以便存放採集到的數據.VIDIOC_QBUF,struct v4l2_buffer

  41. VideoBuffer* buffers = calloc( req.count, sizeof(VideoBuffer) );

  42. printf("sizeof(VideoBuffer) is %d ",sizeof(VideoBuffer));

  43. struct v4l2_buffer buf;

  44. for (numBufs = 0; numBufs < req.count; numBufs++)

  45. {

  46. memset( buf, 0, sizeof(buf) );

  47. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  48. buf.memory = V4L2_MEMORY_MMAP;

  49. buf.index = numBufs;

  50. if (ioctl(fd, VIDIOC_QUERYBUF, buf) < 0)

  51. {

  52. printf("VIDIOC_QUERYBUF error ");

  53. //return -1;

  54. }

  55. printf("buf len is %d ",sizeof(buf));

  56. //內存映射

  57. buffers[numBufs].length = buf.length;

  58. buffers[numBufs].offset = (size_t) buf.m.offset;

  59. buffers[numBufs].start = mmap (NULL, buf.length,PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);

  60. printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d ",buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);

  61. printf("buf2 len is %d ",sizeof(buffers[numBufs].start));

  62. if (buffers[numBufs].start == MAP_FAILED)

  63. {

  64. perror("buffers error ");

  65. //return -1;

  66. }

  67. if (ioctl (fd, VIDIOC_QBUF, buf) < 0)

  68. {

  69. printf("VIDIOC_QBUF error ");

  70. //return -1;

  71. }

  72. }

  73. 7. 開始的採集。

  74. enum v4l2_buf_type type;

  75. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  76. if (ioctl (fd, VIDIOC_STREAMON, type) < 0)

  77. {

  78. printf("VIDIOC_STREAMON error ");

  79. // return -1;

  80. }

  81. 8. 出隊列以取得已採集數據的幀緩沖,取得原始採集數據。VIDIOC_DQBUF, 將緩沖重新入隊列尾,這樣可以循環採集。VIDIOC_QBUF

  82. if (ioctl(fd, VIDIOC_DQBUF, buf) < 0)

  83. {

  84. perror("VIDIOC_DQBUF failed. ");

  85. //return -1;

  86. }

  87. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  88. buf.memory = V4L2_MEMORY_MMAP;

  89. unsigned char *ptcur = buffers[numBufs].start;

  90. DEBUG("buf.bytesused = %d ",buf.bytesused);

  91. int i1;

  92. for(i1=0; i1<buf.bytesused; i1++)

  93. {

  94. if((buffers[numBufs].start[i1] == 0xFF) (buffers[numBufs].start[i1+1] == 0xC4))

  95. {

  96. DEBUG("huffman table finded! buf.bytesused = %d FFC4 = %d ",buf.bytesused,i1);

  97. break;

  98. }

  99. }

  100. if(i1 == buf.bytesused)printf("huffman table don't exist! ");

  101. int i;

  102. for(i=0; i<buf.bytesused; i++)

  103. {

  104. if((buffers[numBufs].start[i] == 0xFF) (buffers[numBufs].start[i+1] == 0xD8)) break;

  105. ptcur++;

  106. }

  107. DEBUG("i=%d,FF=%02x,D8=%02x ",i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);

  108. int imagesize =buf.bytesused - i;

  109. DEBUG("buf.bytesused = %d ",buf.bytesused);

  110. DEBUG ("imagesize = %d ",imagesize);

  111. 9. 停止的採集。VIDIOC_STREAMOFF

  112. 10. 關閉設備。close(fd);

㈩ video4linux(v4l)使用攝像頭圖像採集的實驗 在fedora下ioctl(vd->fd, VIDIOCGMBUF, &(vd->mbuf)) 執行失敗

1.video4linux基礎相關
1.1 v4l的介紹與一些基礎知識的介紹
I.首先說明一下video4linux(v4l)。
它是一些視頻系統,視頻軟體,音頻軟體的基礎,經常使用在需要採集圖像的場合,如視頻監控,webcam,可視電話,經常應用在embedded linux中是linux嵌入式開發中經常使用的系統介面。它是linux內核提供給用戶空間的編程介面,各種的視頻和音頻設備開發相應的驅動程序後,就可以通過v4l提供的系統API來控制視頻和音頻設備,也就是說v4l分為兩層,底層為音視頻設備在內核中的驅動,上層為系統提供的API,而對於我們來說需要的就是使用這些系統的API。
II.Linux系統中的文件操作
有關Linux系統中的文件操作不屬於本文的內容。但是還是要了解相關系統調用的作用和使用方法。其中包括open(),read(),close(),ioctl(),mmap()。詳細的使用不作說明。在Linux系統中各種設備(當然包括視頻設備)也都是用文件的形式來使用的。他們存在與dev目錄下,所以本質上說,在Linux中各種外設的使用(如果它們已經正確的被驅動),與文件操作本質上是沒有什麼區別的。
1.2 建立一套簡單的v4l函數庫
這一節將一邊介紹v4l的使用方法,一邊建立一套簡單的函數,應該說是一套很基本的函數,它完成很基本的夠能但足夠展示如何使用v4l。這些函數可以用來被其他程序使用,封裝基本的v4l功能。本文只介紹一些和攝像頭相關的編程方法,並且是最基礎和最簡單的,所以一些內容並沒有介紹,一些與其他視頻設備(如視頻採集卡)和音頻設備有關的內容也沒有介紹,本人也不是很理解這方面的內容。
這里先給出接下來將要開發出來函數的一個總覽。
相關結構體和函數的定義我們就放到一個名為v4l.h的文件中,相關函數的編寫就放在一個名為v4l.c的文件中把。
對於這個函數庫共有如下的定義(也就是大體v4l.h中的內容):
#ifndef _V4L_H_
#define _V4L_H_
#include <sys/types.h>
#include <linux/videodev.h> //使用v4l必須包含的頭文件
這個頭文件可以在/usr/include/linux下找到,裡麵包含了對v4l各種結構的定義,以及各種ioctl的使用方法,所以在下文中有關v4l的相關結構體並不做詳細的介紹,可以參看此文件就會得到你想要的內容。
下面是定義的結構體,和相關函數,突然給出這么多的代碼很唐突,不過隨著一點點解釋條理就會很清晰了。
struct _v4l_struct
{
int fd;//保存打開視頻文件的設備描述符
struct video_capability capability;//該結構及下面的結構為v4l所定義可在上述頭文件中找到
struct video_picture picture;
struct video_mmap mmap;
struct video_mbuf mbuf;
unsigned char *map;//用於指向圖像數據的指針
int frame_current;
int frame_using[VIDEO_MAXFRAME];//這兩個變數用於雙緩沖在後面介紹。
};
typedef struct _v4l_struct v4l_device;
//上面的定義的結構體,有的文中章有定義channel的變數,但對於攝像頭來說設置這個變數意義不大通常只有一個channel,本文不是為了寫出一個大而全且成熟的函數庫,只是為了介紹如何使用v4l,再加上本人水平也有限,能夠給讀者一個路線我就很知足了,所以並沒有設置這個變數同時與channel相關的函數也沒有給出。

extern int v4l_open(char *, v4l_device *);
extern int v4l_close(v4l_device *);
extern int v4l_get_capability(v4l_device *);
extern int v4l_get_picture(v4l_device *);
extern int v4l_get_mbuf(v4l_device *);
extern int v4l_set_picture(v4l_device *, int, int, int, int, int,);
extern int v4l_grab_picture(v4l_device *, unsigned int);
extern int v4l_mmap_init(v4l_device *);
extern int v4l_grab_init(v4l_device *, int, int);
extern int v4l_grab_frame(v4l_device *, int);
extern int v4l_grab_sync(v4l_device *);
上述函數會在下文中逐漸完成,功能也會逐漸介紹,雖然現在看起來沒什麼感覺只能從函數名上依稀體會它的功能,或許看起來很煩,不過看完下文就會好了。
前面已經說過使用v4l視頻編程的流程和對文件操作並沒有什麼本質的不同,大概的流程如下:
1.打開視頻設備(通常是/dev/video0)
2.獲得設備信息。
3.根據需要更改設備的相關設置。
4.獲得採集到的圖像數據(在這里v4l提供了兩種方式,直接通過打開的設備讀取數據,使用mmap內存映射的方式獲取數據)。
5.對採集到的數據進行操作(如顯示到屏幕,圖像處理,存儲成圖片文件)。
6.關閉視頻設備。
知道了流程之後,我們就需要根據流程完成相應的函數。

那麼我們首先完成第1步打開視頻設備,需要完成int v4l_open(char *, v4l_device *);
具體的函數如下
#define DEFAULT_DEVICE 「/dev/video0」
int v4l_open(char *dev , v4l_device *vd)
{
if(!dev)dev= DEFAULT_DEVICE;
if((vd-fd=open(dev,O_RDWR))<0){perror(「v4l_open:」);return -1;}
if(v4l_get_capability(vd))return -1;
if(v4l_get_picture(vd))return -1;//這兩個函數就是即將要完成的獲取設備信息的函數
return 0
}
同樣對於第6步也十分簡單,就是int v4l_close(v4l_device *);的作用。
函數如下:
int v4l_close(v4l_device *vd)
{close(vd->fd);return 0;}
現在我們完成第2步中獲得設備信息的任務,下面先給出函數在對函數作出相應的說明。
int v4l_get_capability(v4l_device *vd)
{
if (ioctl(vd->fd, VIDIOCGCAP, &(vd->capability)) < 0) {
perror("v4l_get_capability:");
return -1;
}
return 0;
}
int v4l_get_picture(v4l_device *vd)
{
if (ioctl(vd->fd, VIDIOCGPICT, &(vd->picture)) < 0) {
perror("v4l_get_picture:");
return -1;
}
return 0;
}
對於以上兩個函數我們不熟悉的地方可有vd->capability和vd->picture兩個結構體,和這兩個函數中最主要的語句ioctl。對於ioctl的行為它是由驅動程序提供和定義的,在這里當然是由v4l所定義的,其中宏VIDIOCGCAP和VIDIOCGPICT的分別表示獲得視頻設備的capability和picture。對於其他的宏功能定義可以在你的Linux系統中的/usr/include/linux/videodev.h中找到,這個頭文件也包含了capability和picture的定義。例如:
struct video_capability
{
char name[32];
int type;
int channels;
int audios;
int maxwidth;
int maxheight;
int minwidth;
int minheight;
};capability結構它包括了視頻設備的名稱,頻道數,音頻設備數,支持的最大最小寬度和高度等信息。
struct video_picture
{
__u16 brightness;
__u16 hue;
__u16 colour;
__u16 contrast;
__u16 whiteness;
__u16 depth;
__u16 palette;
}picture結構包括了亮度,對比度,色深,調色板等等信息。頭文件里還列出了palette相關的值,這里並沒有給出。
了解了以上也就了解了這兩個簡單函數的作用,現在我們已經獲取到了相關視頻設備的capabilty和picture屬性。
這里直接給出另外一個函數
int v4l_get_mbuf(v4l_device *vd)
{
if (ioctl(vd->fd, VIDIOCGMBUF ,&(vd->mbuf)) < 0) {
perror("v4l_get_mbuf:");
return -1;
}
return 0;
}
int v4l_get_mbuf(v4l_device *vd)
{
if (ioctl(vd->fd, VIDIOCGMBUF ,&(vd->mbuf)) < 0) {
perror("v4l_get_mbuf:");
return -1;
}
return 0;
}
對於結構體video_mbuf在v4l中的定義如下,video_mbuf結構體是為了服務使用mmap內存映射來獲取圖像的方法而設置的結構體,通過這個結構體可以獲得攝像頭設備存儲圖像的內存大小。具體的定義如下,各變數的使用也會在下文詳細說明。
struct video_mbuf
{
int size; 可映射的攝像頭內存大小
int frames; 攝像頭可同時存儲的幀數
int offsets[VIDEO_MAX_FRAME];每一幀圖像的偏移量
};
下面完成第3步按照需要更改設備的相應設置,事實上可以更改的設置很多,本文以更改picture屬性為例說明更改屬性的一般方法。
那麼我們就完成extern int v4l_set_picture(v4l_device *, int, int, int, int, int,);這個函數吧
int v4l_set_picture(v4l_device *vd,int br,int hue,int col,int cont,int white)
{
if(br) vd->picture.brightnesss=br;
if(hue) vd->picture.hue=hue;
if(col) vd->picture.color=col;
if(cont) vd->picture.contrast=cont;
if(white) vd->picture.whiteness=white;
if(ioctl(vd->fd,VIDIOCSPICT,&(vd->picture))<0)
{perror("v4l_set_picture: ");return -1;}
return 0;
}
int v4l_get_mbuf(v4l_device *vd)
{
if (ioctl(vd->fd, VIDIOCGMBUF ,&(vd->mbuf)) < 0) {
perror("v4l_get_mbuf:");
return -1;
}
return 0;
}
對於結構體video_mbuf在v4l中的定義如下,video_mbuf結構體是為了服務使用mmap內存映射來獲取圖像的方法而設置的結構體,通過這個結構體可以獲得攝像頭設備存儲圖像的內存大小。具體的定義如下,各變數的使用也會在下文詳細說明。
struct video_mbuf
{
int size; 可映射的攝像頭內存大小
int frames; 攝像頭可同時存儲的幀數
int offsets[VIDEO_MAX_FRAME];每一幀圖像的偏移量
};
下面完成第3步按照需要更改設備的相應設置,事實上可以更改的設置很多,本文以更改picture屬性為例說明更改屬性的一般方法。
那麼我們就完成extern int v4l_set_picture(v4l_device *, int, int, int, int, int,);這個函數吧
int v4l_set_picture(v4l_device *vd,int br,int hue,int col,int cont,int white)
{
if(br) vd->picture.brightnesss=br;
if(hue) vd->picture.hue=hue;
if(col) vd->picture.color=col;
if(cont) vd->picture.contrast=cont;
if(white) vd->picture.whiteness=white;
if(ioctl(vd->fd,VIDIOCSPICT,&(vd->picture))<0)
{perror("v4l_set_picture: ");return -1;}
return 0;
}
上述函數就是更改picture相關屬性的例子,其核心還是v4l給我們提供的ioctl的相關調用,通過這個函數可以修改如亮度,對比度等相關的值。

閱讀全文

與linux對攝像頭圖像採集相關的資料

熱點內容
dvd光碟存儲漢子演算法 瀏覽:757
蘋果郵件無法連接伺服器地址 瀏覽:963
phpffmpeg轉碼 瀏覽:671
長沙好玩的解壓項目 瀏覽:145
專屬學情分析報告是什麼app 瀏覽:564
php工程部署 瀏覽:833
android全屏透明 瀏覽:737
阿里雲伺服器已開通怎麼辦 瀏覽:803
光遇為什麼登錄時伺服器已滿 瀏覽:302
PDF分析 瀏覽:485
h3c光纖全工半全工設置命令 瀏覽:143
公司法pdf下載 瀏覽:382
linuxmarkdown 瀏覽:350
華為手機怎麼多選文件夾 瀏覽:683
如何取消命令方塊指令 瀏覽:350
風翼app為什麼進不去了 瀏覽:778
im4java壓縮圖片 瀏覽:362
數據查詢網站源碼 瀏覽:150
伊克塞爾文檔怎麼進行加密 瀏覽:892
app轉賬是什麼 瀏覽:163