, ,
(東華大學 機械工程學院,上海 201620)
手機屏幕作為最重要的信息輸出部件,承擔著人機交互的功能,它的質量好壞直接影響著用戶體驗,因此,在手機的生產(chǎn)過程中,屏幕的質量檢測至關重要。目前國內(nèi)手機屏幕檢測的方法仍然是依靠人工檢測,這種方式耗時耗力,并且不能夠形成規(guī)?;?、標準化。
本系統(tǒng)以手機屏幕缺陷采集為應用背景,旨在研究一種小型的低成本的能夠實時的適用于手機液晶屏幕流水線生產(chǎn)的圖像采集與圖象處理的系統(tǒng)裝置?;谇度胧絃inux平臺,以S5PV210微控制器為主控單元,7寸LCD液晶屏為圖像顯示單元;UVC(USB video class)視頻設備協(xié)議的usb攝像頭為系統(tǒng)的圖像采集單元,基于最優(yōu)秀多路IO復用機制Epoll框架利用V4L2編程接口,進行多路圖像采集,圖像編解碼顯示,并為后續(xù)的圖像缺陷檢測做準備工作。
為了得到滿足圖像采集與顯示系統(tǒng)需要的最小硬件平臺。對S5PV210開發(fā)板的硬件資源進行裁剪,系統(tǒng)通過攝像頭進行圖像采集,并將采集數(shù)據(jù)送至 ARM 處理器進行圖像處理,配載 512M 的 SDRAM 作為系統(tǒng)內(nèi)存和 1G的Nand Flash為系統(tǒng)存儲器以掛載嵌入式 Linux 操作系統(tǒng)和運行圖形用戶應用程序,期間通過 LCD 顯示屏將采集圖像實時顯示給用戶,處理結果既可以保存于掉電數(shù)據(jù)不丟失的 Flash 存儲器中。為了調(diào)試程序、燒寫系統(tǒng)以及與 PC 機的通信,保留了 USB 轉串口和網(wǎng)線接口以連接到上位機 PC,最后加入電源管理,組成了整個硬件開發(fā)平臺。
軟件平臺采用Linux,內(nèi)核版本2.6.35,為針對目標平臺S5PV210的硬件特性,首先將啟動介質Uboot下載到了nandflash中,利用Busy box制作了ext3格式的根文件系統(tǒng)。由于程序開發(fā)的需要,本系統(tǒng)在uboot的命令行界面中設置了啟動內(nèi)核與掛載根文件的系統(tǒng)的方式。設置啟動命令bootcmd,使開發(fā)板通過tftp下載鏡像(zImage)。設置啟動參數(shù)bootargs,使開發(fā)板從nfs去掛載rootfs(內(nèi)核配置應使能nfs形式的rootfs)。考慮到內(nèi)核版本與硬件的不兼容問題,本系統(tǒng)基于linux內(nèi)核驅動框架,移植了framebuffer驅動程序。如圖1所示,是系統(tǒng)的軟件框架圖。
圖1 系統(tǒng)軟件框架圖
framebuffer幀緩沖(簡稱fb)是Linux內(nèi)核中虛擬出的一個設備,提供給用戶態(tài)進程一個統(tǒng)一標準接口實現(xiàn)直接寫屏操作。從驅動來看,framebuffer是一個典型的字符設備,而且創(chuàng)建了一個類/sys/class/graphics,用戶可以把Framebuffer當作是顯示內(nèi)存的一個虛擬映像設備,將framebuffer映射到進程地址空間之后,就可以實現(xiàn)對LCD屏幕的直接讀寫操作,而這種寫操作可以立刻反應在屏幕上。這種操作是統(tǒng)一的、抽象的,用戶完全不必關心物理顯存的位置、工作原理、刷新頁面等具體細節(jié),這些都是由 Framebuffer設備驅動來完成。
驅動框架部分,是內(nèi)核開發(fā)人員編寫,此部分不涉及具體硬件操作,主要包含4個文件。
1)fbmem.c此文件主要任務是:調(diào)用fbmem_init(void)此函數(shù)通過register_chrdev接口向系統(tǒng)注冊一個framebuffer主設備號29即fb字符設備驅動,同時通過class_create創(chuàng)建graphics類, 配合mdev機制生成一個供給用戶訪問的設備文件(/dev目錄下)。linux驅動設備中,所有的緩存顯示設備都是由framebuffer子系統(tǒng)來管理,即linux設備驅動框架只需要知道一個主設備號為29的framebuffer設備即可。應用層如果要訪問framebuffer均會被推送給fb_fops,統(tǒng)一由此結構體進行分發(fā)操作。register_framebuffer(struct fb_info *fb_info)此函數(shù)提供register_framebuffer接口給具體framebuffer驅動編寫著來注冊fb設備。
單獨的顯示緩存設備都被視作一個framebuffer從虛擬設備,必須要在驅動加載初始化時,通過register_framebuffer接口向framebuffer子系統(tǒng)注冊自己,才能使自己能夠被驅動程序接口調(diào)用。如此,當應用程序要訪問該fb從設備時,才能方便framebuffer子系統(tǒng)進行有序操作和管理分發(fā)。
2)fbsys.c此文件中的函數(shù)將會被register_frame buffer接口調(diào)用,用來實現(xiàn)frame buffer在/sys目錄下的一些屬性文件bits_per_pixel、modes、stride、rotate…等。
3)modedb.c即顯示模式庫文件,此文件是管理顯示模式,如分辨率,刷新率,VGA、720P等。
4)fb_notify.c其具體作用:被系統(tǒng)調(diào)用,它管理了一個鏈表,提供給linux內(nèi)核管理,主要用來做一個反向喚醒機制。當注冊了一個framebuffer驅動之后,系統(tǒng)將會通知這個鏈表中所有的驅動。
本系統(tǒng)中framebuffer驅動部分是被實現(xiàn)成為了platform平臺總線驅動,這部分由驅動開發(fā)人員來編寫,主要做一些硬件相關的工作,硬件初始化,初始化時鐘,寄存器,GPIO,中斷等等,包括如下4個文件。
1)s3cfb.c驅動主體。屬于一個platform_driver,通過此文件中的s3cfb_probe()函數(shù),調(diào)用操作硬件的函數(shù)接口,實現(xiàn)對硬件的操作算法。主要做的工作是:ioremap實現(xiàn)了寄存器地址的動態(tài)映射,分配frame buffer的緩存….等
2)s3cfb_fimd6x.c文件中定義了所有LCD硬件寄存器操作的函數(shù),負責對硬件設備做一些具體的初始化,配置時鐘,內(nèi)存映射等。
3)mach-x210.c負責提供platform_device,platformdevices是在開機時,自動被注冊,當platformdriver注冊之后,二者將會配對。
4)devs.c為platform_device負責提供具體用到的硬件描述信息即resource資源數(shù)據(jù),資源數(shù)據(jù)主要包括LCD有關的寄存器地址、IO資源、中斷號等。
開發(fā)Framebuffer設備驅動,存在幾個重要結構體,需要重點研究,根據(jù)Framebuffer設備驅動程序的結構,驅動主要跟struct fb_info此結構體有關,此結構體記錄了Framebuffer設備的幾乎全部信息,具體包括設備的參數(shù)設置、狀態(tài)信息和底層硬件操作的函數(shù)指針等。在Linuxkernel驅動中,每一個Framebuffer設備都對應一個fb_info才能完成驅動框架部分的接口函數(shù)。
1)struct fb_info此結構體定封裝了frame buffer驅動的所有有效信息。
2)struct fb_ops,是fb_info成員結構體,fb_ops硬件操作接口集包含很多接口,如設置可變參數(shù)、設置顏色寄存器、清屏接口、畫位圖接口、內(nèi)存映射等。
3)fb_fix_screeninf此結構體是fb_info成員結構體,填充用戶不可修改的參數(shù),包如顯示內(nèi)存的物理地址和長度等。
4)struct fb_var_screeninfo是fb_info成員結構體,填充用戶可以修改的參數(shù),包括屏幕分辨率、每個像素比特數(shù)等。
5)struct fb_fops,是Framebuffer屬于字符設備,用戶通過fb_fops結構中定義的文件操作接口函數(shù)可以操作Framebuffer設備。移植需要的具體操作如下:
1)打開kerneldriversvideoKconfig文件,添加代碼:config FB_S3C_EK070TN93
bool "EK070TN93"
depends on MACH_SMDKV210 || MACH_SMDKC110
select BACKLIGHT_PWM
2)初始化LCD控制器。包括時鐘信號的配置,信號的極性設置,VSYNC、HSYNC時序配置,像素配置,使能通道,LCD屏幕坐標設置,framebuffer始末位置設置,frame buffer在虛擬屏幕中的偏移量設置,輸出模式等。
3)添加信息到設備devs.c中實現(xiàn)的加入控制器信息到device設備,如此,驅動框架才會認識新加入的設備名字,通過設備名字去查找相應的probe函數(shù)。
4)在系統(tǒng)初始化中增加對lcd的初始。即在系統(tǒng)初始化文件中添加:.init_machine = x210_lcd_init;5)make menuconfig配置,在console選項中還要加入frambuffer support選項。
6)最后make編譯并執(zhí)行,移植步驟完畢,如果移植完畢后,檢測沒有移植成功,可以在如下3個文中件排查問題,:menuconfig、Makefiel、Kconfig。
經(jīng)過如上步驟,已經(jīng)完成了framebuffer驅動在linux kernel中的移植工作,已經(jīng)與S5PV210開發(fā)板的硬件完美兼容,接下來的只需要編寫應用程序調(diào)用framebuffer驅動,將采集到的圖像顯示在開發(fā)板的LCD屏幕上。
Epoll是Linux內(nèi)核為處理大批量文件描述符而作了改進的poll,是Linux下多路復用IO接口select/poll的增強版本,其工作原理如圖2所示:在大量并發(fā)連接中只有少量活躍的情況下,能顯著提高程序系統(tǒng)CPU利用率。獲取事件的時,無須遍歷整個被監(jiān)聽描述符集,只要遍歷被內(nèi)核IO事件異步喚醒而加入Ready隊列的描述符集合。
圖2 Epoll機制工作原理
V4L2(Video For Linux Two)是Linux操作系統(tǒng)下用于采集圖片、視頻和音頻數(shù)據(jù)的API接口,配合適當?shù)囊曨l采集設備和相應的驅動程序,可以實現(xiàn)圖像采集。在Linux操作系統(tǒng)中一切皆文件,在本系統(tǒng)中,攝像頭設備文件是"/dev/video0"。V4L2支持兩種方式來采集圖像:內(nèi)存映射方式(mmap)和直接讀取方式(read)。V4L2在videodev.h文件中定義了一些重要的數(shù)據(jù)結構,在采集圖像的過程中,通過對這些數(shù)據(jù)的操作來獲得最終的圖像數(shù)據(jù)。如圖3所示是V4L2在linux中的驅動框架如圖3所示。
圖3 V4L2驅動框架圖
如圖4所示是epoll框架的V4L2圖像采集流程:
第一步,打開視頻設備文件,通過V4L2接口進行視頻采集的參數(shù)初始化。
第二步,申請若干視頻采集的幀緩沖區(qū),并將這些幀緩沖區(qū)從內(nèi)核空間映射到用戶空間,便于應用程序讀取并處理圖像數(shù)據(jù)。
第三步,將申請到的幀緩沖區(qū)在視頻采集輸入隊列排隊,并啟動視頻采集。
第四步,開始視頻數(shù)據(jù)的采集,應用程序從視頻采集輸出隊列取出幀緩沖區(qū),處理完后,將幀緩沖區(qū)重新放入視頻采集輸入隊列,循環(huán)往復采集連續(xù)的視頻數(shù)據(jù)。
第五步,在事件處理函數(shù)void cammer_handler(int fd,void *arg)里面保存圖像數(shù)據(jù)。
第六步,由于次攝像頭只支持YUVU格式圖片采集,需要調(diào)用函數(shù)對圖片格進行轉化,最后采集到的圖像數(shù)據(jù)image_jpeg.jpg和image_bmp.bmp。
framebuffer幀緩沖(簡稱fb)是Linux內(nèi)核中虛擬出的一個設備,它向應用層提供一個統(tǒng)一的標準編程接口,它向應用層屏蔽了驅動層的一些細節(jié),方便用戶進行應用編程。從驅動來看,fb是一個典型的字符設備。如圖4是frame buffer驅動框架圖。本系統(tǒng)中基于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 采集的圖像數(shù)據(jù),映射到 Framebuffer 的內(nèi)存區(qū)域中,便可以直接顯示到 LCD上。也可將攝像頭采集到的數(shù)據(jù)直接保存成 JPG 或BMP 等格式的圖像文件后,利用jpeglib解碼,映射到Framebuffer的內(nèi)存區(qū)域中,同樣可以顯示到LCD上。
JPEG靜態(tài)圖片壓縮標準是一種被廣泛認可的圖像格式標準,JPEG 標準是在變換編碼的基礎上,綜合應用了 DCT 和哈夫曼編碼兩種手段達到了很好的圖像壓縮效果, 基于 D C T 的編碼方法是JPEG 算法的核心內(nèi)容。JPEG算法的實現(xiàn)流程主要包括圖像分割、顏色空間轉換、DCT(Discrete cosine transform)、Quantization(數(shù)據(jù)量化)、Huffman coding(數(shù)據(jù)進行編碼)。如圖5是DCT基壓縮解壓框圖。
圖5 DCT壓縮解壓框圖
如圖5所示:圖像壓縮大致可以概括成3個步驟,原始圖像經(jīng)映射變換后的數(shù)據(jù),經(jīng)量化器和熵編碼器后以碼流的形式輸出。
1)映射變換。通過映射改變圖像像素的特性,更加有利于對圖像進行壓縮編碼。
2)量化器。對映射后的數(shù)據(jù)進行量化,可分為標準量化和矢量量化。對映射后的數(shù)據(jù)進行逐個的量化,稱標準量化,若對映射后的數(shù)據(jù)成組的進行量化,稱矢量量化。量化必然會造成圖像的某些信息丟失,導致失真,即量化失真或量化噪聲。量化的精細程度與壓縮比例始終是對立的,所以應選用適當?shù)牧炕墧?shù)和量化曲線形狀來平衡這對矛盾。量化器的使用是圖像編碼產(chǎn)生失真的根本原因,如果使用了量化器,不可能保證復原圖像與原始圖完全一致。
3)熵編碼器。其作用是用來消除符號編碼冗余度的,一般不導致失真,理論上,編出的碼流的平均碼長應該等于量化后數(shù)據(jù)的信息熵。
DCT變換就是利用傅立葉變換的特性.采用圖像邊界褶翻將像變換為偶函數(shù)形式,接著對圖像數(shù)據(jù)進行二維傅立葉變換,變后就只包含余弦項。所以稱之為離散余弦變換。
首先,將圖像分割成8*8的小塊,在JPEG壓縮算法中,通常情況是將顏色空間轉換成YCbCr空間,Y表示亮度,Cb和Cr分別表示藍色和紅色的色差值,其轉換公式為:
Y=0.289R+0.589G+0.124B
Cr=(0.501R-0.4186G-0.0823B)+128
Cb=(-0.1687R+0.3313G+0.500B)+128
DCT變換的本質就是將原來的小塊圖像投影到新的空間中,經(jīng)過DCT變換后,原本雜亂的數(shù)據(jù)將變得工整。如下是DCT變換的公式:
F=AfAT
在DCT變換之后,圖像的數(shù)據(jù)信息并沒有丟失,需要對其進行量化處理Quantization,根據(jù)圖像中的數(shù)據(jù)元素的使用頻率,調(diào)整元素的編碼長度,以獲最優(yōu)壓縮比,進行哈弗曼編碼壓縮,至此在保證不丟失信息的前提下,則可以實現(xiàn)數(shù)據(jù)的無損壓縮。本系統(tǒng)通過上面的基于epoll框架的圖片采集可以得到的是經(jīng)過編碼壓縮后的jpg格式的圖片,jpg格式的圖片數(shù)據(jù)量比bmp格式圖片小很多,有利于圖片傳輸與保存。
libjpeg是一個完全用C語言編寫的庫,被廣泛應用于JPEG解碼、JPEG編碼等應用中。首先需要移植libjpeg到系統(tǒng)中,編寫int is_jpg(const char *path)函數(shù),判斷是否是jpg圖片。static int jpg_analyze(struct pic_info *pPic)此函數(shù)功能: 解碼jpg圖片,并將解碼出來的數(shù)據(jù)存儲;函數(shù)參數(shù): pPic,記錄源jpg圖片,解碼出來的圖片寬高、圖片數(shù)據(jù)緩沖區(qū)等信息。如圖6所示,是本系統(tǒng)jpg圖片解碼顯示軟件流程圖。具體實現(xiàn)如下:
第1步: 錯誤處理函數(shù)部分的綁定,給解碼器做必要的內(nèi)存分配和數(shù)據(jù)結構的初始化。
cinfo.err = jpeg_std_error(&jerr.pub);jerr.pub.error_exit = my_error_exit;
jpeg_create_decompress(&cinfo);
第2步: 將fopen打開的源jpg圖片和解碼器關聯(lián)jpeg_stdio_src(&cinfo, infile);
第3步: 讀jpg文件頭;
jpeg_read_header(&cinfo, TRUE);
第4步: 啟動解碼器jpeg_start_decompress(&cinfo);
第5步: 逐行解碼并將解碼出的數(shù)據(jù)丟到緩沖區(qū)jpeg_read_scanlines(&cinfo, &buffer, 1);
第6步: 解碼完了,做清理工作jpeg_destroy_decompress(&cinfo);
第7步:調(diào)用函數(shù),從圖片存放路徑,遞歸檢索圖片,顯示到LCD;
int display_jpg(const char *pathname);
fb_draw2(&picture);
圖6 jpg圖片解碼顯示軟件流程圖
本程序能夠實現(xiàn)遞歸檢索文件夾,bmp、jpg圖片解碼顯示LCD屏幕上,同時還是實現(xiàn)了觸摸屏播放顯示。本系統(tǒng)選取了手機屏幕缺陷中的白屏黑點屏,黑屏亮點屏,綠屏黑點屏,花屏黑點屏進行實驗測試,如圖7所示,是jpeg解碼顯示測試圖,本系統(tǒng)能夠將攝像頭采集到的手機液晶屏幕缺陷圖像顯示在開發(fā)板的LCD顯示屏上。
圖7 jpeg解碼顯示測試圖
本文設計了基于嵌入式Linux的圖像采集與顯示系統(tǒng),能夠實現(xiàn)多路攝像頭實時采集圖像,并且能夠實時顯示在LCD屏幕上,還實現(xiàn)了圖像的BMP格式與JPEG格式保存,有利于后續(xù)對圖片做一些圖像檢測,例如TFT手機屏幕缺陷檢測,基于深度學習模式識別等應用。在大型工廠車間多條流水線快速作業(yè)的手機屏幕生產(chǎn)線上,可以利用此系統(tǒng)裝置實時快速的對手機液晶屏幕總成缺陷進行自動檢測,代替人工肉眼檢測的同時,又避免了耗費大量的人力物力財力。不僅減少了人工的重復勞動和生產(chǎn)成本,節(jié)約了時間和空間,提高了生產(chǎn)效率,
而且提高了手機液晶屏生產(chǎn)線的自動化程度。本系統(tǒng)適合工業(yè)自動化領域,它成本低、功耗低、體積小,可以方便的應用到圖像采集,圖象處理,視頻監(jiān)控,安全防范等項目中。
[1]劉崢嶸,張曉薇,俞 輝,等編著.嵌入式Linux應用開發(fā)[M].北京:機械工業(yè)出版社,2004
[2]韋東山.嵌入式Linux應用開發(fā)完全手冊[M].北京:人民郵電出版社,2008.
[3]劉 森.嵌入式系統(tǒng)接口設計與Linux驅動程序開發(fā)[M].北京:北京航空航天大學出版社,2006
[4]于殿泓.圖像檢測與處理技術[ M].西安: 西安電子科技大學出版社,2006.
[5]譚浩強.C語言程序設計[M].北京:清華大學出版社,1992.
[6] 許宏松.Linux 應用程序開發(fā)指南[M].北京:機械工業(yè)出版社, 2000.
[7] 杜春雷.ARM體系結構與編程[M]. 北京:清華大學出版社, 2003.
[8] 宋寶華.Linux設備驅動開發(fā)詳解[M]. 北京:人民郵電出版社, 2008.