摘要:針對工業控制領域的自動化生產需要, 設計了一種基于Linux內核驅動framebuffer和UVC類型攝像頭的圖像采集與顯示系統;以三星公司的S5PV210微控制器為控制單元, 基于Linux內核移植了framebuffer驅動, 調用Linux內核提供的V4L2編程接口, 基于Epoll架構進行多路圖像采集;對采集到YUVU格式圖像進行編碼, 轉化成BMP和JPEG保存, 以便后續對圖片做相應的應用開發;最后調用libjpeg庫函數對jpeg圖片進行解碼, 并顯示在TFTLCD屏幕上;實驗結果顯示:能夠采集到圖片數據, 并能成功在LCD屏幕上顯示, framebuffer驅動能正常工作, 滿足工業自動化生產圖象處理的需求。
關鍵詞:S5PV210; framebuffer; V4L2; Epoll; libjpeg; 圖像采集與顯示;
Abstract:According to the need of automatic production in the field of industrial control, an image acquisition and display system based on embedded Linux kernel framebuffer and USB Video Class type camera is designed.The system uses Samsung S5 Pv210 as core controller, and transplated framebuffer driver based on Linux kernel.Calling V4 L2 programming interface provided by the Linux kernel, using the UVC types of USB camera multi-channel images acquisition based on Epoll architecture.The image data collected YUVU format is encoded, saved as BMP and JPEG file formats for subsequent development and application.Libjpeg library called by the system to decode JPEG images, and make image displayed in the TFT LCD screen.The result of experiments show that the images can be collected, saved and displayed in the LCD screen, and framebuffer driver can work so that can meet the needs of image process in automatic production.
Keyword:S5PV210; framebuffer; V4L2; Epoll; Libjpeg; image acquisition and display;
手機屏幕作為最重要的信息輸出部件, 承擔著人機交互的功能, 它的質量好壞直接影響著用戶體驗, 因此, 在手機的生產過程中, 屏幕的質量檢測至關重要。目前國內手機屏幕檢測的方法仍然是依靠人工檢測, 這種方式耗時耗力, 并且不能夠形成規;、標準化。
本系統以手機屏幕缺陷采集為應用背景, 旨在研究一種小型的低成本的能夠實時的適用于手機液晶屏幕流水線生產的圖像采集與圖象處理的系統裝置;谇度胧絃inux平臺, 以S5PV210微控制器為主控單元, 7寸LCD液晶屏為圖像顯示單元;UVC (USB video class) 視頻設備協議的usb攝像頭為系統的圖像采集單元, 基于最優秀多路IO復用機制Epoll框架利用V4L2編程接口, 進行多路圖像采集, 圖像編解碼顯示, 并為后續的圖像缺陷檢測做準備工作。
1、系統環境的搭建
1.1、系統的硬件平臺
為了得到滿足圖像采集與顯示系統需要的最小硬件平臺。對S5PV210開發板的硬件資源進行裁剪, 系統通過攝像頭進行圖像采集, 并將采集數據送至ARM處理器進行圖像處理, 配載512M的SDRAM作為系統內存和1G的Nand Flash為系統存儲器以掛載嵌入式Linux操作系統和運行圖形用戶應用程序, 期間通過LCD顯示屏將采集圖像實時顯示給用戶, 處理結果既可以保存于掉電數據不丟失的Flash存儲器中。為了調試程序、燒寫系統以及與PC機的通信, 保留了USB轉串口和網線接口以連接到上位機PC, 最后加入電源管理, 組成了整個硬件開發平臺。
1.2、系統的軟件框架
軟件平臺采用Linux, 內核版本2.6.35, 為針對目標平臺S5PV210的硬件特性, 首先將啟動介質Uboot下載到了nandflash中, 利用Busy box制作了ext3格式的根文件系統。由于程序開發的需要, 本系統在uboot的命令行界面中設置了啟動內核與掛載根文件的系統的方式。設置啟動命令bootcmd, 使開發板通過tftp下載鏡像 (zImage) 。設置啟動參數bootargs, 使開發板從nfs去掛載rootfs (內核配置應使能nfs形式的rootfs) ?紤]到內核版本與硬件的不兼容問題, 本系統基于linux內核驅動框架, 移植了framebuffer驅動程序。如圖1所示, 是系統的軟件框架圖。
圖1 系統軟件框架圖
2、Framebuffer原理及驅動移植
framebuffer幀緩沖 (簡稱fb) 是Linux內核中虛擬出的一個設備, 提供給用戶態進程一個統一標準接口實現直接寫屏操作。從驅動來看, framebuffer是一個典型的字符設備, 而且創建了一個類/sys/class/graphics, 用戶可以把Framebuffer當作是顯示內存的一個虛擬映像設備, 將framebuffer映射到進程地址空間之后, 就可以實現對LCD屏幕的直接讀寫操作, 而這種寫操作可以立刻反應在屏幕上。這種操作是統一的、抽象的, 用戶完全不必關心物理顯存的位置、工作原理、刷新頁面等具體細節, 這些都是由Framebuffer設備驅動來完成。
2.1、驅動框架部分
驅動框架部分, 是內核開發人員編寫, 此部分不涉及具體硬件操作, 主要包含4個文件。
1) fbmem.c此文件主要任務是:調用fbmem_init (void) 此函數通過register_chrdev接口向系統注冊一個framebuffer主設備號29即fb字符設備驅動, 同時通過class_create創建graphics類, 配合mdev機制生成一個供給用戶訪問的設備文件 (/dev目錄下) 。linux驅動設備中, 所有的緩存顯示設備都是由framebuffer子系統來管理, 即linux設備驅動框架只需要知道一個主設備號為29的framebuffer設備即可。應用層如果要訪問framebuffer均會被推送給fb_fops, 統一由此結構體進行分發操作。register_framebuffer (struct fb_info*fb_info) 此函數提供register_framebuffer接口給具體framebuffer驅動編寫著來注冊fb設備。單獨的顯示緩存設備都被視作一個framebuffer從虛擬設備, 必須要在驅動加載初始化時, 通過register_framebuffer接口向framebuffer子系統注冊自己, 才能使自己能夠被驅動程序接口調用。如此, 當應用程序要訪問該fb從設備時, 才能方便framebuffer子系統進行有序操作和管理分發。
2) fbsys.c此文件中的函數將會被register_frame buffer接口調用, 用來實現frame buffer在/sys目錄下的一些屬性文件bits_per_pixel、modes、stride、rotate…等。
3) modedb.c即顯示模式庫文件, 此文件是管理顯示模式, 如分辨率, 刷新率, VGA、720P等。
4) fb_notify.c其具體作用:被系統調用, 它管理了一個鏈表, 提供給linux內核管理, 主要用來做一個反向喚醒機制。當注冊了一個framebuffer驅動之后, 系統將會通知這個鏈表中所有的驅動。
2.2、驅動部分
本系統中framebuffer驅動部分是被實現成為了platform平臺總線驅動, 這部分由驅動開發人員來編寫, 主要做一些硬件相關的工作, 硬件初始化, 初始化時鐘, 寄存器, GPIO, 中斷等等, 包括如下4個文件。
1) s3cfb.c驅動主體。屬于一個platform_driver, 通過此文件中的s3cfb_probe () 函數, 調用操作硬件的函數接口, 實現對硬件的操作算法。主要做的工作是:ioremap實現了寄存器地址的動態映射, 分配frame buffer的緩存….等
2) s3cfb_fimd6x.c文件中定義了所有LCD硬件寄存器操作的函數, 負責對硬件設備做一些具體的初始化, 配置時鐘, 內存映射等。
3) mach-x210.c負責提供platform_device, platformdevices是在開機時, 自動被注冊, 當platformdriver注冊之后, 二者將會配對。
4) devs.c為platform_device負責提供具體用到的硬件描述信息即resource資源數據, 資源數據主要包括LCD有關的寄存器地址、IO資源、中斷號等。
2.3、具體移植操作
開發Framebuffer設備驅動, 存在幾個重要結構體, 需要重點研究, 根據Framebuffer設備驅動程序的結構, 驅動主要跟struct fb_info此結構體有關, 此結構體記錄了Framebuffer設備的幾乎全部信息, 具體包括設備的參數設置、狀態信息和底層硬件操作的函數指針等。在Linuxkernel驅動中, 每一個Framebuffer設備都對應一個fb_info才能完成驅動框架部分的接口函數。
1) struct fb_info此結構體定封裝了frame buffer驅動的所有有效信息。
2) struct fb_ops, 是fb_info成員結構體, fb_ops硬件操作接口集包含很多接口, 如設置可變參數、設置顏色寄存器、清屏接口、畫位圖接口、內存映射等。
3) fb_fix_screeninf此結構體是fb_info成員結構體, 填充用戶不可修改的參數, 包如顯示內存的物理地址和長度等。
4) struct fb_var_screeninfo是fb_info成員結構體, 填充用戶可以修改的參數, 包括屏幕分辨率、每個像素比特數等。
5) struct fb_fops, 是Framebuffer屬于字符設備, 用戶通過fb_fops結構中定義的文件操作接口函數可以操作Framebuffer設備。移植需要的具體操作如下:
1) 打開\kernel\drivers\video\Kconfig文件, 添加代碼:config FB_S3C_EK070TN93
2) 初始化LCD控制器。包括時鐘信號的配置, 信號的極性設置, VSYNC、HSYNC時序配置, 像素配置, 使能通道, LCD屏幕坐標設置, framebuffer始末位置設置, frame buffer在虛擬屏幕中的偏移量設置, 輸出模式等。
3) 添加信息到設備devs.c中實現的加入控制器信息到device設備, 如此, 驅動框架才會認識新加入的設備名字, 通過設備名字去查找相應的probe函數。
4) 在系統初始化中增加對lcd的初始。即在系統初始化文件中添加:.init_machine=x210_lcd_init;5) make menuconfig配置, 在console選項中還要加入frambuffer support選項。
6) 最后make編譯并執行, 移植步驟完畢, 如果移植完畢后, 檢測沒有移植成功, 可以在如下3個文中件排查問題, :menuconfig、Makefiel、Kconfig。
經過如上步驟, 已經完成了framebuffer驅動在linux kernel中的移植工作, 已經與S5PV210開發板的硬件完美兼容, 接下來的只需要編寫應用程序調用framebuffer驅動, 將采集到的圖像顯示在開發板的LCD屏幕上。
3、基于Epoll框架的圖像采集
Epoll是Linux內核為處理大批量文件描述符而作了改進的poll, 是Linux下多路復用IO接口select/poll的增強版本, 其工作原理如圖2所示:在大量并發連接中只有少量活躍的情況下, 能顯著提高程序系統CPU利用率。獲取事件的時, 無須遍歷整個被監聽描述符集, 只要遍歷被內核IO事件異步喚醒而加入Ready隊列的描述符集合。
圖2 Epoll機制工作原理
V4L2 (Video For Linux Two) 是Linux操作系統下用于采集圖片、視頻和音頻數據的API接口, 配合適當的視頻采集設備和相應的驅動程序, 可以實現圖像采集。在Linux操作系統中一切皆文件, 在本系統中, 攝像頭設備文件是"/dev/video0"。V4L2支持兩種方式來采集圖像:內存映射方式 (mmap) 和直接讀取方式 (read) 。V4L2在videodev.h文件中定義了一些重要的數據結構, 在采集圖像的過程中, 通過對這些數據的操作來獲得最終的圖像數據。如圖3所示是V4L2在linux中的驅動框架如圖3所示。
圖3 V4L2驅動框架圖
如圖4所示是epoll框架的V4L2圖像采集流程:
第一步, 打開視頻設備文件, 通過V4L2接口進行視頻采集的參數初始化。
第二步, 申請若干視頻采集的幀緩沖區, 并將這些幀緩沖區從內核空間映射到用戶空間, 便于應用程序讀取并處理圖像數據。
第三步, 將申請到的幀緩沖區在視頻采集輸入隊列排隊, 并啟動視頻采集。
第四步, 開始視頻數據的采集, 應用程序從視頻采集輸出隊列取出幀緩沖區, 處理完后, 將幀緩沖區重新放入視頻采集輸入隊列, 循環往復采集連續的視頻數據。
第五步, 在事件處理函數void cammer_handler (int fd, void*arg) 里面保存圖像數據。
第六步, 由于次攝像頭只支持YUVU格式圖片采集, 需要調用函數對圖片格進行轉化, 最后采集到的圖像數據image_jpeg.jpg和image_bmp.bmp。
圖4 基于Epoll框架的圖像采集軟件流程圖
4、基于framebuffer圖像解碼顯示
4.1、framebuffer圖像顯示
framebuffer幀緩沖 (簡稱fb) 是Linux內核中虛擬出的一個設備, 它向應用層提供一個統一的標準編程接口, 它向應用層屏蔽了驅動層的一些細節, 方便用戶進行應用編程。從驅動來看, fb是一個典型的字符設備。如圖4是frame buffer驅動框架圖。本系統中基于framebuffer驅動, 圖像顯示程序的關鍵如下:
(1) 設備文件fbfd=open (FBDEVICE, O_RDWR) ;
(2) 獲取設備信息vinfo.xres, vinfo.yres, vinfo.bits_per_pixel
(3) mmap做映射pfb=mmap (NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fbfd, 0) ;
(4) 填充framebuffervoid fb_draw2 (const struct pic_info*pPic)
由此可以直接利用Video4Linux采集的圖像數據, 映射到Framebuffer的內存區域中, 便可以直接顯示到LCD上。也可將攝像頭采集到的數據直接保存成JPG或BMP等格式的圖像文件后, 利用jpeglib解碼, 映射到Framebuffer的內存區域中, 同樣可以顯示到LCD上。
4.2、libjpeg庫的移植及JPEG圖片解碼
JPEG靜態圖片壓縮標準是一種被廣泛認可的圖像格式標準, JPEG標準是在變換編碼的基礎上, 綜合應用了DCT和哈夫曼編碼兩種手段達到了很好的圖像壓縮效果, 基于D C T的編碼方法是JPEG算法的核心內容。JPEG算法的實現流程主要包括圖像分割、顏色空間轉換、DCT (Discrete cosine transform) 、Quantization (數據量化) 、Huffman coding (數據進行編碼) 。如圖5是DCT基壓縮解壓框圖。
圖5 DCT壓縮解壓框圖
如圖5所示:圖像壓縮大致可以概括成3個步驟, 原始圖像經映射變換后的數據, 經量化器和熵編碼器后以碼流的形式輸出。
1) 映射變換。通過映射改變圖像像素的特性, 更加有利于對圖像進行壓縮編碼。
2) 量化器。對映射后的數據進行量化, 可分為標準量化和矢量量化。對映射后的數據進行逐個的量化, 稱標準量化, 若對映射后的數據成組的進行量化, 稱矢量量化。量化必然會造成圖像的某些信息丟失, 導致失真, 即量化失真或量化噪聲。量化的精細程度與壓縮比例始終是對立的, 所以應選用適當的量化級數和量化曲線形狀來平衡這對矛盾。量化器的使用是圖像編碼產生失真的根本原因, 如果使用了量化器, 不可能保證復原圖像與原始圖完全一致。
3) 熵編碼器。其作用是用來消除符號編碼冗余度的, 一般不導致失真, 理論上, 編出的碼流的平均碼長應該等于量化后數據的信息熵。
DCT變換就是利用傅立葉變換的特性.采用圖像邊界褶翻將像變換為偶函數形式, 接著對圖像數據進行二維傅立葉變換, 變后就只包含余弦項。所以稱之為離散余弦變換。
首先, 將圖像分割成8*8的小塊, 在JPEG壓縮算法中, 通常情況是將顏色空間轉換成YCbCr空間, Y表示亮度, Cb和Cr分別表示藍色和紅色的色差值, 其轉換公式為:
DCT變換的本質就是將原來的小塊圖像投影到新的空間中, 經過DCT變換后, 原本雜亂的數據將變得工整。如下是DCT變換的公式:
上面兩式中, C (u) , 當u, v=0, f表示像素值的數組, f (i, j) 表示i行j列的值, 則離散余弦變換后定義一個新的數組F (u, v) , 表示u行v列的值。
在DCT變換之后, 圖像的數據信息并沒有丟失, 需要對其進行量化處理Quantization, 根據圖像中的數據元素的使用頻率, 調整元素的編碼長度, 以獲最優壓縮比, 進行哈弗曼編碼壓縮, 至此在保證不丟失信息的前提下, 則可以實現數據的無損壓縮。本系統通過上面的基于epoll框架的圖片采集可以得到的是經過編碼壓縮后的jpg格式的圖片, jpg格式的圖片數據量比bmp格式圖片小很多, 有利于圖片傳輸與保存。
4.3、libjpg解碼顯示具體實現
libjpeg是一個完全用C語言編寫的庫, 被廣泛應用于JPEG解碼、JPEG編碼等應用中。首先需要移植libjpeg到系統中, 編寫int is_jpg (const char*path) 函數, 判斷是否是jpg圖片。static int jpg_analyze (struct pic_info*pPic) 此函數功能:解碼jpg圖片, 并將解碼出來的數據存儲;函數參數:pPic, 記錄源jpg圖片, 解碼出來的圖片寬高、圖片數據緩沖區等信息。如圖6所示, 是本系統jpg圖片解碼顯示軟件流程圖。具體實現如下:
圖6 jpg圖片解碼顯示軟件流程圖
本程序能夠實現遞歸檢索文件夾, bmp、jpg圖片解碼顯示LCD屏幕上, 同時還是實現了觸摸屏播放顯示。本系統選取了手機屏幕缺陷中的白屏黑點屏, 黑屏亮點屏, 綠屏黑點屏, 花屏黑點屏進行實驗測試, 如圖7所示, 是jpeg解碼顯示測試圖, 本系統能夠將攝像頭采集到的手機液晶屏幕缺陷圖像顯示在開發板的LCD顯示屏上。
圖7 jpeg解碼顯示測試圖
5、結論
本文設計了基于嵌入式Linux的圖像采集與顯示系統, 能夠實現多路攝像頭實時采集圖像, 并且能夠實時顯示在LCD屏幕上, 還實現了圖像的BMP格式與JPEG格式保存, 有利于后續對圖片做一些圖像檢測, 例如TFT手機屏幕缺陷檢測, 基于深度學習模式識別等應用。在大型工廠車間多條流水線快速作業的手機屏幕生產線上, 可以利用此系統裝置實時快速的對手機液晶屏幕總成缺陷進行自動檢測, 代替人工肉眼檢測的同時, 又避免了耗費大量的人力物力財力。不僅減少了人工的重復勞動和生產成本, 節約了時間和空間, 提高了生產效率, 而且提高了手機液晶屏生產線的自動化程度。本系統適合工業自動化領域, 它成本低、功耗低、體積小, 可以方便的應用到圖像采集, 圖象處理, 視頻監控, 安全防范等項目中。
參考文獻
[1]劉崢嶸, 張曉薇, 俞輝, 等編著.嵌入式Linux應用開發[M].北京:機械工業出版社, 2004
[2]韋東山.嵌入式Linux應用開發完全手冊[M].北京:人民郵電出版社, 2008.
[3]劉森.嵌入式系統接口設計與Linux驅動程序開發[M].北京:北京航空航天大學出版社, 2006
[4]于殿泓.圖像檢測與處理技術[M].西安:西安電子科技大學出版社, 2006.
[5]譚浩強.C語言程序設計[M].北京:清華大學出版社, 1992.
[6]許宏松.Linux應用程序開發指南[M].北京:機械工業出版社, 2000.
[7]杜春雷.ARM體系結構與編程[M].北京:清華大學出版社, 2003.
[8]宋寶華.Linux設備驅動開發詳解[M].北京:人民郵電出版社, 2008.