ARM9+Linux下USB攝像頭影象採集
終於實現了在Micro2440+Linux2.6.29環境下通過NFS檔案系統實現USB攝像頭影象採集。在此,做一個總結,以備後續參考。
實驗條件:RedHat9.0(核心版本2.4.18),Micro2440開發板,Linux2.6.29(arm9),ANC (Vimicro Corp.) USB PC攝像頭,GCC,SDL-1.2.14.tar,servfox-R1_1_3[1].tar,spcaview-20061208[1].tar。
一、升級Redhat9.0核心
由於Readhat9.0核心版本是2.4,很多核心驅動未包含其中,尤其是USB萬能攝像頭GSPCA和UVC。
二、配置編譯Micro2440上執行核心
重新編譯Micro2440上執行的核心,配置V4L和USB驅動。選擇linux-2.6.29中的config-mini2440為參考,執行:cp config-mini2440 .config;然後make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-;出現相應的圖形化配置視窗。
如果需要在Linux作業系統中使用USB攝像頭進行視訊資料採集,則必須在進行核心配置時,應檢查Linux 核心中是否已經添加了對Video4Linux驅動和對USB攝像頭驅動模組的支援。
利用Linux核心配置make menuconfig命令對Video4Linux支援驅動進行配置,選中多媒體裝置選項“Multimedia device->”(如圖15-1所示)按回車,進入多媒體裝置配置介面。在多媒體配置介面中,選中“Video For Linux”,就可以使核心實現對Video4Linux驅動的支援,為視訊採集裝置提供程式設計介面。
配置好核心對Video4Linux驅動後,返回核心配置主介面,選中USB支援選項(如圖15-3 所示)“USB support—>” 按回車,進入USB支援配置介面
配置完成後,執行make uImage ARCH=arm CROSS_COMPILE=arm-linux-。完成後,uImage就生成在arch/arm/boot/中。通過uboot下載uImage到記憶體中,啟動核心,實現NFS起檔案系統。
三、安裝SDL-1.2.14
因為在redhat9.0中顯示視訊影象,呼叫spcaview(後面介紹)需要有SDL庫的支援,否則會報錯。所以,將SDL-1.2.14.tar下載傳送到系統中,解壓後執行.configure;make;make install。完成SDL庫的安裝。
四、servfox-R1_1_3工具
下載Servfox-R1_1_3解壓進入其目錄,將其中的Makefile.arm修改為Makefile,並修改Makefile裡面的CC為arm -linux -gcc,因為預設的是載入的動態庫,因此還需要修改Makefile中的SERVFLAGS為SERVFLAGS= -O2 –DLINUX $(WARNINGS) –static,其中-static是我們新增的內容,make之後生成servfox。
五、 spcaview,redhat9.0下的視訊顯示工具
下載spcaview原始碼包解壓,進入解壓後的目錄,make後會報錯,一般需要安裝SDL庫,去網上下載後安裝SDL庫,在PC 機上安裝SDL庫:
解壓:tar xvf SDL-1.2.13.tar.tar
配置:./configure
編譯:make
安裝:make install
進入spcaview解壓目錄修改Makefile中的修改Makefile中的SDLLIBS =$(shell sdl-config --libs) 和 SDLFLAGS = $(shell sdl-config --cflags),這兩句主要是指定了SDL庫的庫路徑和編譯選項。Make之後生成spcaview,在客戶端執行spcaview –w 伺服器ip:伺服器埠號。就可以採集影象了,
[[email protected] spcaview-20061208]# ./spcaview -g -w 10.103.4.211:7070
Spcaview version: 1.1.7 date: 06:11:2006 (C) [email protected]
using Server 10.103.4.211 Port 7070
六、測試
將新編譯的核心載入到ARM上,通過NFS檔案系統執行servfox :
# ./servfox -d /dev/video0 -g -s 640x480 -w 7070
servfox version: 1.1.3 date: 11:12:2005 (C) [email protected]
wrong spca5xx device
Waiting .... for connection. CTrl_c to stop !!!!
Got connection from 10.103.4.216
在redhat9.0中執行spcaview:
[[email protected] spcaview-20061208]# ./spcaview -g -w 10.103.4.211:7070
Spcaview version: 1.1.7 date: 06:11:2006 (C) [email protected]
using Server 10.103.4.211 Port 7070
此時,視訊能在redhat9.0視窗中顯示,如圖所示。
七、總結
在實現影象採集的過程中,碰到很多問題,嘗試過很多方法,走了很多彎路,雖然很多碰壁,但也有不少收穫。
編譯核心:嘗試編譯高版本的核心,或者編譯新核心的時候,最好選擇和現有的配置檔案相近的系統的配置檔案作為參考。在原有基礎上增加一些模組,編譯,然後試驗。如果一次性增加模組過多,容易造成編譯錯誤等問題。
編譯工具:在編譯某些外掛的時候,如:servfox、spcaview等,經常會報一些檔案未定義、庫不存在等錯誤,一般是由於系統缺少相應的庫檔案,需要下載安裝,如SDL,或者由於系統本身版本不匹配,庫檔案安裝位置不符造成。熟練運用goole、百度進行搜尋,找到問題解決方法。同時,很多工具、庫、外掛等在開源社群網站都有穩定版本下載,使用這些網站提供的版本可靠性更好。
重點難點:makefile、kconfig等檔案的書寫,kit工具使用等。
附錄:視訊採集原始碼分析(看程式碼採用Lucida Console或者Consolas等寬字型較好,0和o區別明顯,不易混淆)
/*
* V4L2 video capture example
*
* This program can be used and distributed without restrictions.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h> /* for videodev2.h */
#include <linux/videodev2.h>
#define CLEAR(x) memset (&(x), 0, sizeof (x))
typedef enum {
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
} io_method; //一共有三種視訊採集方式:使用read、write方式;記憶體對映方式和使用者指標模式
struct buffer {
void * start;
size_t length;
}; // 定義緩衝區
static char * dev_name = NULL; // 裝置名稱,可根據裝置名開啟裝置
static io_method io = IO_METHOD_MMAP;// 視訊採集方式,記憶體對映方式
static int fd = -1;
struct buffer * buffers = NULL;
static unsigned int n_buffers = 0;
static void errno_exit (const char *s)// 錯誤退出,並列印錯誤資訊
{
fprintf (stderr, "%s error %d, %s\n",s, errno, strerror (errno));
exit (EXIT_FAILURE);
}
static intxioctl (int fd,int request,void *arg)// 根據引數對裝置進行控制
{
int r;
do r = ioctl (fd, request, arg);
while (-1 == r && EINTR == errno);
return r;
}
static void process_image (const void * p)// 影象處理
{
fputc ('.', stdout);
fflush (stdout);// 重新整理輸出緩衝
}
static int read_frame (void)// 對影象幀進行讀取
{
struct v4l2_buffer buf;//這是視訊介面V4L2中相關檔案定義的,在videodev2.h中
unsigned int i;
switch (io)
case IO_METHOD_READ:
if (-1 == read (fd, buffers[0].start, buffers[0].length)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("read");
}
}
process_image (buffers[0].start);
break;
case IO_METHOD_MMAP://採用記憶體對映的方式
CLEAR (buf);//對緩衝區清零
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl (fd, VIDIOC_DQBUF, &buf)) {
//VIDIOC_DQBUF控制引數作用是申請視訊緩衝區
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("VIDIOC_DQBUF");
}
}
assert (buf.index < n_buffers);
process_image (buffers[buf.index].start);
if (-1 == ioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
break;
case IO_METHOD_USERPTR:
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
if (-1 == ioctl (fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("VIDIOC_DQBUF");
}
}
for (i = 0; i < n_buffers; ++i)
if (buf.m.userptr == (unsigned long) buffers[i].start
&& buf.length == buffers[i].length)
break;
assert (i < n_buffers);
process_image ((void *) buf.m.userptr);
if (-1 == ioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
break;
}
return 1;
}
static void mainloop (void)//迴圈採集
{
unsigned int count;
count = 100;
while (count-- > 0) {
for (;;) {
fd_set fds;
struct timeval tv;//時間結構體
int r;
FD_ZERO (&fds);//清零
FD_SET (fd, &fds);
/* Timeout. */
tv.tv_sec = 2;
tv.tv_usec = 0;
r = select (fd + 1, &fds, NULL, NULL, &tv);//等待一幀影象採集完成,超時定為2秒
if (-1 == r) {
if (EINTR == errno)
continue;
errno_exit ("select");
}
if (0 == r) {
fprintf (stderr, "select timeout\n");
exit (EXIT_FAILURE);
}
if (read_frame ())//讀取一幀影象
break;
/* EAGAIN - continue select loop. */
}
}
}
static void stop_capturing (void)//終止採集
{
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == ioctl (fd, VIDIOC_STREAMOFF, &type))
errno_exit ("VIDIOC_STREAMOFF");
break;
}
}
static void start_capturing (void)//開始採集
{
unsigned int i;
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == ioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == ioctl (fd, VIDIOC_STREAMON, &type))
errno_exit ("VIDIOC_STREAMON");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
buf.index = i;
buf.m.userptr = (unsigned long) buffers[i].start;
buf.length = buffers[i].length;
if (-1 == ioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == ioctl (fd, VIDIOC_STREAMON, &type))
errno_exit ("VIDIOC_STREAMON");
break;
}
}
static void uninit_device (void)//解除安裝裝置
{
unsigned int i;
switch (io) {
case IO_METHOD_READ:
free (buffers[0].start);
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap (buffers[i].start, buffers[i].length))
errno_exit ("munmap");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i)
free (buffers[i].start);
break;
}
free (buffers);
}
static void init_read (unsigned int buffer_size)//初始化讀取
{
buffers = calloc (1, sizeof (*buffers));
if (!buffers) {
fprintf (stderr, "Out of memory\n");
exit (EXIT_FAILURE);
}
buffers[0].length = buffer_size;
buffers[0].start = malloc (buffer_size);
if (!buffers[0].start) {
fprintf (stderr, "Out of memory\n");
exit (EXIT_FAILURE);
}
}
static void init_mmap (void)//初始化記憶體對映
{
struct v4l2_requestbuffers req;
CLEAR (req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl (fd, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
fprintf (stderr, "%s does not support "
"memory mapping\n", dev_name);
exit (EXIT_FAILURE);
} else {
errno_exit ("VIDIOC_REQBUFS");
}
}
if (req.count < 2) {
fprintf (stderr, "Insufficient buffer memory on %s\n",
dev_name);
exit (EXIT_FAILURE);
}
buffers = calloc (req.count, sizeof (*buffers));
if (!buffers) {
fprintf (stderr, "Out of memory\n");
exit (EXIT_FAILURE);
}
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
struct v4l2_buffer buf; //代表驅動中的一幀
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf))
errno_exit ("VIDIOC_QUERYBUF");
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start =
mmap (NULL /* start anywhere */,
buf.length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */,
fd, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start)
errno_exit ("mmap");
}
}
static void init_userp (unsigned int buffer_size)
{
struct v4l2_requestbuffers req;
unsigned int page_size;
page_size = getpagesize ();
相關推薦
ARM9+Linux下USB攝像頭影象採集
終於實現了在Micro2440+Linux2.6.29環境下通過NFS檔案系統實現USB攝像頭影象採集。在此,做一個總結,以備後續參考。 實驗條件:RedHat9.0(核心版本2.4.18),Micro2440開發板,Linux2.6.29(arm9),ANC
linux 下USB 攝像頭的使用說明
此處我只說用uvc通用驅動 查詢攝像頭是否是UVC裝置,參見官網 1 找到CAMERA ID 2 lsusb -d VID:PID -v | grep “14 Video” 如果輸出有下面資訊說明支援 bFunctionClass
在Ubuntu16.04安裝OpenCV3.1並實現USB攝像頭影象採集
硬體平臺:Windows7 64 bit + USB攝像頭C270 軟體平臺:VMware® Workstation 12 Pro+ Ubuntu16.04 + arm-linux-gcc4.3.2 + OpenCV3.1 一、知識補充 1.
Python+Opencv+Qt4編寫Windows下攝像頭影象採集顯示程式
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file '1.ui' # # Created: Tue Nov 14 09:45:29 2017 # by: Py
Opencv開發環境VS2017配置---USB攝像頭視訊採集
一、下載OpenCV3庫 (2)解壓縮安裝到 C盤根目錄下 二、開啟VS2017新建一個專案 配置【附加包含目錄】 新增附加庫Lib 設定依賴庫 opencv_world343.lib opencv_world343d.lib
Linux下USB轉串列埠驅動
Linux發行版自帶usb to serial驅動,以模組方式編譯驅動,在核心原始碼目錄下執行Make MenuConfig選擇Devces drivers-->USB seupport--> <M>USB Serial Converter support --> <M
linux下USB轉串列埠的設定
在linux下利用簡訊modem傳送簡訊,由於簡訊modem使用的是USB串列埠轉換器(晶片為PL2303),把在配置和除錯的過程和方法在此記錄下,希望給有同樣需求的同仁提供一點幫助。 【一】、驅動相關說明:如果直接使用串列埠線,而沒有用到USB轉串列埠裝置,就不需要安裝驅
OpenCV入門學習之讀取usb攝像頭影象,實時顯示
首先,新建一個.cpp的源程式檔案,例如,gedit test.cpp 在該檔案中新增以下程式: #include <opencv2/core/core.hpp> #include
基於arm平臺linux下USB音效卡驅動安裝和使用
核心配置 <*> Advanced Linux Sound Architecture —> usb音效卡安裝 1.apt-get install alsa-base 2
C語言高階應用---操作linux下V4L2攝像頭應用程式
#include "CameralOpt.h" int video_fd ; int length ; char *yuv[COUNT] ; struct v4l2_buffer enqueue , dequeue ; //定義出入隊的操作結構體成員 int Init_Cameral(int
OV7725攝像頭影象採集基礎知識
目前FPGA用於影象採集 傳輸 處理 顯示應用越來越多,主要原因是影象處理領域的火熱以及FPGA強大的並行處理能力。本文以OV7725為例,對攝像頭使用方面的基礎知識做個小的總結,為後續做個鋪墊。 XCLK:工作時鐘輸入,由主控器產生,頻率為24MH
linux下USB轉串列埠識別1
minicom是linux下串列埠通訊的軟體,它的使用完全依靠鍵盤的操作,雖然沒有“超級終端”那麼易用,但是使用習慣之後讀者將會體會到它的高效與便利,下面將講解minicom的安裝和配置。 一、安裝minicom: 使用以下命令: # sudo apt-get instal
關於怎樣把普通usb攝像頭影象釋出到ros的topic
前言:一個人搞某個領域的東西,沒個人帶真不行,整天糾結於各種小毛問題 這是一個很容易提出的問題,ORB_SLAM做線上單目必須牽扯到怎樣把usb_cam(這裡指筆記本自帶攝像頭)的資料釋出到ros的topic供使用,這裡給出方法如下: Step2:新
linux 和 windows 下用ffmpeg 操作usb攝像頭
windows : 列裝置 ffmpeg -list_devices true -f dshow -i dummy 編碼為H.264,儲存為本地檔案 ffmpeg -f&nb
USB攝像頭採集影象(DirectShow)
攝像頭除了可以捕獲視訊流還可以捕獲單張靜止的圖片,靜止的圖片質量比流的質量要高。支援輸出靜態圖片的攝像頭一般要提供一個靜態圖片PIN,這個PIN的種類是PIN_CATEGORY_STILL。 捕捉靜態圖片常用的filter是Sample Graber filter,它的用
Zedboard & Zynq 影象採集(五) 板端Linux下視訊TCP傳送 & Linux上位機QT視訊顯示
前面幾篇已經陸續講述了影象採集,傳輸,Linux系統搭建等,這一篇就講一下自制一個簡單的板端視訊傳送和Linux上位機視訊顯示客戶端。板端視訊傳送用Zedboard做視訊資料傳輸,我能想到的是兩條路,一條就是網口,一條就是USB,USB傳輸方式打算以後研究一下,用網口是比較熟
Linux下利用nginx流伺服器推送攝像頭實時採集視訊
應用環境:伺服器:Ubuntu 14.04.5 (cat /etc/issue檢視)。 USB攝像頭:直插在Linux上。 ffmpeg -f video4linux2 -i /dev/video0 -f flv rtmp://192.168.1.200/live/live
兩個usb攝像頭的同時採集影象的一般方法。
很多人都為兩個usb攝像頭同步採集影象而苦惱,而且在網上也有很多基於opencv的usb攝像頭的採集影象方法。 我也曾經為了實現同步採集而煩惱了。。。 可現在終於知道了很簡單而且很好地方法。 方法如下: 首先讓自己的電腦自帶的攝像頭禁用(這你可以搞定吧?如果不知道就問我。
Linux環境下使用V4L2+opencv以MJPEG格式讀取USB攝像頭並實時顯示
轉眼間,V4L2已經搞了很長時間,從最開始的一竅不通,到後來的漸漸熟悉,從最開始照貓畫虎的使用YUYV格式之間轉換,到後來使用MJPEG格式讀取,中間頗有周折。趁任務完成間隙,來簡單總結下V4L2的使用。(文章只主要寫了過程,完整程式已經附在最後) 有讀者要問,open
linux下通過V4L2驅動USB攝像頭
目錄 前言 在移植羅技C270攝像頭到6818的過程中,核心已經檢測到了USB攝像頭,但是直接用OpenCV的API(比如CvCapture*cvCaptureFromCAM(int index)介面,無法開啟USB攝像頭,至少目前我是這麼認為的。