《點(diǎn)云庫PCL學(xué)習(xí)教程》第4章 輸入、輸出(IO)_第1頁
《點(diǎn)云庫PCL學(xué)習(xí)教程》第4章 輸入、輸出(IO)_第2頁
《點(diǎn)云庫PCL學(xué)習(xí)教程》第4章 輸入、輸出(IO)_第3頁
《點(diǎn)云庫PCL學(xué)習(xí)教程》第4章 輸入、輸出(IO)_第4頁
《點(diǎn)云庫PCL學(xué)習(xí)教程》第4章 輸入、輸出(IO)_第5頁
已閱讀5頁,還剩77頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第4章 輸入、輸出(IO)PCL中所有的處理都是基于點(diǎn)云展開的,利用不同的設(shè)備獲取點(diǎn)云、存儲(chǔ)點(diǎn)云等都是點(diǎn)云處理前后必須做的流程,PCL中有自己設(shè)計(jì)的內(nèi)部PCD文件格式,為此,設(shè)計(jì)讀寫該格式以及與其他3D文件格式之間進(jìn)行轉(zhuǎn)化的接口類都是很必要的,目前PCL內(nèi)部支持對常用的3D格式文件的打開和存儲(chǔ)操作,以及與PCD內(nèi)部格式之間的互相轉(zhuǎn)化。本章首先對PCL中支持的點(diǎn)云獲取設(shè)備(如kinect)以及OpenNI開源框架作一個(gè)基本介紹,其次對PCL中的I/O模塊及相關(guān)類進(jìn)行簡單說明,最后通過應(yīng)用實(shí)例來展示如何對PCL中I/O模塊進(jìn)行靈活運(yùn)用。本章各小節(jié)目錄4.1 I/O涉及的設(shè)備及相關(guān)概念簡介4.2 P

2、CL中I/O模塊及類介紹4.3 應(yīng)用實(shí)例解析4.1 I/O涉及的設(shè)備及相關(guān)概念簡介4.1.1 OpenNI開源框架開源框架OpenNI(開放式自然交互)來源于由業(yè)界領(lǐng)導(dǎo)的一個(gè)非營利性組織,創(chuàng)建于2010年11月,專注于提高和改善自然交互設(shè)備與應(yīng)用軟件的互操作能力。其官方網(wǎng)站于12月8號正式公開,主要成員之一是PrimeSense公司(Kinect的核心芯片正是由這家公司提供),其他成員還包括開發(fā)ROS的機(jī)器人公司W(wǎng)illow Garage,以及游戲公司Side-Kick等。OpenNI是一個(gè)多語言、跨平臺的框架,它定義了一套用于編寫通用自然交互應(yīng)用的API。OpenNI的主要目的就是形成標(biāo)準(zhǔn)的

3、API,便于下面兩個(gè)接口之間進(jìn)行通信:(1)視覺和音頻傳感器(用來感知周圍環(huán)境信息)。(2)視覺和音頻感知中間件(用來對應(yīng)用場景中所記錄的音頻和視覺數(shù)據(jù)進(jìn)行分析與理解,例如能夠接收一份可見的圖像數(shù)據(jù)并返回從中檢測到的手掌位置信息)。OpenNI提供了一組基于傳感器設(shè)備實(shí)現(xiàn)的API和另外一組由中間件組件實(shí)現(xiàn)的API,打破了傳感器和中間件之間的依賴關(guān)系。這樣,使用OpenNI API開發(fā)應(yīng)用程序時(shí)就不需要在各種中間件模塊的上層操作上浪費(fèi)時(shí)間,可以做到一次編寫、隨處部署。OpenNI的這種分層設(shè)計(jì)機(jī)制允許中間件開發(fā)者可以直接基于最原始的數(shù)據(jù)格式編寫算法,而不管這些數(shù)據(jù)是由何種傳感器設(shè)備產(chǎn)生,同時(shí)也讓

4、傳感器生產(chǎn)商制造的設(shè)備能用于任何OpenNI兼容的應(yīng)用程序。OpenNI的這套標(biāo)準(zhǔn)化API使得自然交互應(yīng)用開發(fā)人員可以利用由傳感器輸入并計(jì)算過的數(shù)據(jù)類型,很方便地跟蹤處理現(xiàn)實(shí)生活中的場景(例如,可以是表示人體全身的數(shù)據(jù),也可以是表示手的位置數(shù)據(jù),或者僅僅是深度圖里面的一組像素等)。這樣可以保證編寫應(yīng)用程序的時(shí)候,不用考慮傳感器或中間件供應(yīng)商相關(guān)的細(xì)節(jié)。圖4-1展示了OpenNI框架的應(yīng)用概念,分為三層:(1)應(yīng)用層:基于OpenNI實(shí)現(xiàn)的自然交互應(yīng)用軟件。(2)中間件接口層:代表OpenNI本身,提供了傳感器和中間件之間的交互接口。(3)硬件設(shè)備層:列出了捕捉視覺和音頻數(shù)據(jù)的多種硬件設(shè)備。4.

5、1.2 OpenNI兼容設(shè)備兼容設(shè)備OpenNI目前已成為PCL集成進(jìn)來的第一個(gè)設(shè)備相關(guān)的第三方庫,用來抓取OpenNI兼容設(shè)備中的點(diǎn)云數(shù)據(jù)。上節(jié)描述的OpenNI應(yīng)用框架說明,只要底層的設(shè)備傳感器設(shè)備與OpenNI兼容,都可以作為點(diǎn)云數(shù)據(jù)輸入源,圖4-2則展示了目前流行的OpenNI兼容設(shè)備。其中,Primesense Reference Design、Microsoft Kinect和Asus XtionPro這3種攝像頭設(shè)備均進(jìn)行了OpenNI兼容性測試。選擇其中任何一個(gè)設(shè)備進(jìn)行點(diǎn)云數(shù)據(jù)采集,都可以經(jīng)OpenNI處理后轉(zhuǎn)化為標(biāo)準(zhǔn)數(shù)據(jù)供上層應(yīng)用使用。如今,OpenNI已成為微軟xbox36

6、0配件kinect在PC上的開源驅(qū)動(dòng)中必須安裝的一個(gè)API。4.2 PCL中I/O模塊及類介紹PCL中I/O庫提供了點(diǎn)云文件輸入輸出相關(guān)的操作類,并封裝了OpenNI兼容的設(shè)備源數(shù)據(jù)獲取接口,可直接從眾多感知設(shè)備獲取點(diǎn)云圖像等數(shù)據(jù)。I/O模塊利用21個(gè)類與28個(gè)函數(shù)實(shí)現(xiàn)了對點(diǎn)云的獲取、讀入、存儲(chǔ)等相關(guān)操作,其依賴于pcl_common和pcl_octree模塊以及OpenNI外部開發(fā)包。4.2.1 I/O模塊中類以及全局函數(shù)說明模塊中類以及全局函數(shù)說明I/O模塊中目前共有21個(gè)類,隨著RGDB設(shè)備的流行必將引入更多的設(shè)備相關(guān)的I/O擴(kuò)展,以后有可能增加以下幾類。1. class pcl:Fil

7、eReader類FileReader定義了PCD文件的讀取接口,主要用做其他讀取類的父類。從它繼承的子類必須實(shí)現(xiàn)自己的讀取函數(shù),即該類中的純虛函數(shù)其繼承關(guān)系如圖4-3所示。但為了保持向后兼容,提供了FILE_V6版本文件讀取的實(shí)現(xiàn)函數(shù)。類FileReader關(guān)鍵成員函數(shù):virtual intreadHeader(const std:string& file_name, sensor_msgs:PointCloud2& cloud, Eigen:Vector4f& origin, Eigen:Quaternionf& orientation, int&

8、file_version, int& data_type, unsigned int& data_idx, const int offset=0)=0純虛函數(shù),定義讀取點(diǎn)云文件頭的接口函數(shù),其參數(shù)意義:file_name讀取文件的文件名。cloud存儲(chǔ)讀取后的點(diǎn)云數(shù)據(jù),但只填充文件頭(關(guān)于PCD文件格式詳見本章后面實(shí)例分析)。origin點(diǎn)云獲取原點(diǎn),該參數(shù)只有在文件版本大于FILE_V7才存在,否則為NULL。orientation點(diǎn)云獲取方向,該參數(shù)只有在文件版本大于FILE_V7才存在,否則為NULL。file_version文件版本(FILE_V7或者FILE_V6)。

9、data_type數(shù)據(jù)類型(二進(jìn)制置為1,ASCII碼置為0)。data_idx數(shù)據(jù)偏移文件頭末尾的偏移量。offset文件頭偏移文件開始的偏移量。virtual int read(const std:string&file_name, sensor_msgs:PointCloud2& cloud, Eigen:Vector4f& origin, Eigen:Quaternionf& orientation, int& file_version, const int offset=0)=0為純虛函數(shù),定義讀取文件數(shù)據(jù)的接口函數(shù),讀取文件中的點(diǎn)云數(shù)據(jù)存儲(chǔ)到

10、cloud對象中,其他參數(shù)同上函數(shù)。int read(const std:string &file_name, sensor_msgs:PointCloud2& cloud, const int offset = 0)功能同上函數(shù)(僅適用于FILE_V6版本文件獲取,因?yàn)閟ensor_msgs:PointCloud2不包含傳感器原點(diǎn)和方向數(shù)據(jù),若讀取高版本數(shù)據(jù)會(huì)產(chǎn)生警告信息)。templateint read(const std:string& file_name, pcl:PointCloud& cloud, const int offset=0)功能同上函數(shù)

11、,只是帶有模板參數(shù)的成員函數(shù)。2. class pcl:FileWriter類FileWriter與FileReader對應(yīng),是寫入PCD文件的類接口定義,可以作為其他寫入類的父類。從它繼承的子類必須實(shí)現(xiàn)自己的寫入函數(shù),即該類中的純虛函數(shù),其繼承關(guān)系如圖4-4所示。類FileWriter關(guān)鍵成員函數(shù):virtual int write(const std:string& file_name, const sensor_msgs:PointCloud2& cloud, const Eigen:Vector4f& origin=Eigen:Vector4f:Zero(),

12、const Eigen:Quaternionf& orientation=Eigen:Quaternionf:Identity(), const bool binary=false)=0;點(diǎn)云寫入到對應(yīng)文件的純虛函數(shù)接口定義,其參數(shù)意義:file_name寫入文件的文件名。cloud需要寫入的點(diǎn)云對象。origin寫入文件頭的點(diǎn)云獲取原點(diǎn),默認(rèn)為(0, 0, 0, 0)。orientation寫入文件頭的點(diǎn)云獲取方向。binary設(shè)置寫入時(shí)的類型(true為二進(jìn)制,false為ASCII碼,默認(rèn)為ASCII碼)。templateintwrite(const std:string&

13、; file_name, const pcl:PointCloud& cloud, const bool binary=false)功能同上函數(shù),只是添加了模板參數(shù)的模板成員函數(shù)。3. class pcl:Grabber類Grabber為PCL1.X對應(yīng)的設(shè)備驅(qū)動(dòng)接口的基類定義,繼承關(guān)系如圖4-5所示。類Grabber關(guān)鍵成員函數(shù):templateboost:signals2:connectionregisterCallback(const boost:function& callback)提供回調(diào)函數(shù)指針,當(dāng)獲取每幀圖像或點(diǎn)云數(shù)據(jù)時(shí)都會(huì)啟動(dòng)回調(diào)函數(shù):templatebool

14、providesCallback() const判斷是否提供回調(diào)函數(shù):virtual void start()=0啟動(dòng)設(shè)備,開始傳輸數(shù)據(jù)流:virtual void stop()=0停止設(shè)備上的數(shù)據(jù)流傳輸:virtual std:string getName() const = 0返回明確的子類名字:virtual bool isRunning() const = 0判斷是否在傳輸數(shù)據(jù)流:virtual float getFramesPerSecond() const = 0獲取FPS幀率,即每秒多少幀數(shù)據(jù)。4. class openni_wrapper:OpenNIDevice類OpenNI

15、Device定義OpenNI設(shè)備的基類,繼承該基類可以實(shí)現(xiàn)不同的OpenNI設(shè)備子類,用于獲取包括紅外數(shù)據(jù)、RGB數(shù)據(jù)、深度圖像數(shù)據(jù)等。繼承關(guān)系如圖4-6所示,目前包括如下設(shè)備Primesense PSDK,Microsoft Kinect,Asus Xtion Pro/Live。類OpenNIDevice關(guān)鍵成員函數(shù):bool findCompatibleImageMode(const XnMapOutputMode& output_mode, XnMapOutputMode& mode)const throw()查詢是否有與output_mode對應(yīng)的圖像模式匹配的輸出模式

16、,如果有則返回true并且存儲(chǔ)兼容模式在mode中,否返回值為false。例如設(shè)備支持30Hz的VGA模式,而請求輸出為30Hz的QVGA模式則通過下采樣是可以兼容的,但是設(shè)備支持25Hz的VGA而請求為30Hz的SXGA就不兼容。bool findCompatibleDepthMode(const XnMapOutputMode& output_mode, XnMapOutputMode& mode)const throw()功能和參數(shù)同上,只是針對深度圖像的模式,并非上述彩色圖像的模式。bool isImageModeSupported(const XnMapOutputM

17、ode& output_mode) const throw()只判斷是否支持該output_mode所給定的圖像模式,支持返回true,否則返回false。bool isDepthModeSupported(const XnMapOutputMode& output_mode) const throw()只判斷是否支持該output_mode所給定的深度圖像模式,支持返回true,否則返回false。const XnMapOutputMode& getDefaultImageMode() const throw()const XnMapOutputMode& g

18、etDefaultDepthMode() const throw()const XnMapOutputMode& getDefaultIRMode() const throw()以上三個(gè)函數(shù)分別是獲取默認(rèn)的RGB、深度、紅外圖像的輸出模式。void setImageOutputMode(const XnMapOutputMode& output_mode)void setDepthOutputMode(const XnMapOutputMode& output_mode)void setIROutputMode(const XnMapOutputMode& ou

19、tput_mode)以上三個(gè)函數(shù)分別是設(shè)置RGB、深度、紅外圖像的輸出模式。XnMapOutputMode getImageOutputMode() constXnMapOutputMode getDepthOutputMode() constXnMapOutputMode getIROutputMode() const以上三個(gè)函數(shù)分別是獲取當(dāng)前的RGB、深度、紅外圖像的輸出模式。void setDepthRegistration(bool on_off)設(shè)置深度圖像是否與RGB圖像對齊。bool isDepthRegistrationSupported() const throw()判斷設(shè)備

20、是否支持深度圖像與RGB圖像對齊void setSynchronization(bool on_off)設(shè)置設(shè)備是否同步輸出RGB和深度圖像。bool isSynchronized() const throw()判斷設(shè)備是否同步輸出RGB和深度圖像,如果是返回true,否則返回false。bool isSynchronizationSupported() const throw()判斷設(shè)備是否支持同步輸出RGB和深度圖像。bool isDepthCropped() const返回深度圖像是否被裁剪過,是為true,否則為false。void setDepthCropping(unsigned

21、x, unsigned y, unsigned width, unsigned height)打開深度圖像的裁剪,x、y分別為兩個(gè)方向上的起始裁剪位置,width和height分別為保留的x與y方向上的尺寸。float getImageFocalLength(int output_x_resolution=0) const throw()獲取RGB圖像的焦距長度(像素)。float getDepthFocalLength(int output_x_resolution=0) const throw()獲取深度圖像的焦距長度(像素)。float getBaseline() const throw

22、()獲取基線長度。virtual void startImageStream()virtual void stopImageStream()上面一對函數(shù)為啟動(dòng)和停止RGB數(shù)據(jù)流的采集。virtual void startDepthStream()virtual void stopDepthStream()上面一對函數(shù)為啟動(dòng)和停止深度數(shù)據(jù)流的采集。virtual void startIRStream()virtual void stopIRStream()上面一對函數(shù)為啟動(dòng)和停止紅外數(shù)據(jù)流的采集。bool hasImageStream() const throw()bool hasDepthSt

23、ream() const throw()bool hasIRStream() const throw()以上三個(gè)函數(shù)分別判斷設(shè)備是否支持RGB、深度、紅外圖像數(shù)據(jù)采集,如果是返回true,否則返回false。virtual bool isImageStreamRunning() const throw()virtual bool isDepthStreamRunning() const throw()virtual bool isIRStreamRunning() const throw()以上三個(gè)函數(shù)分別判斷設(shè)備是否正在進(jìn)行RGB、深度、紅外圖像數(shù)據(jù)采集。CallbackHandle reg

24、isterImageCallback(const ImageCallbackFunction& callback, void* cookie=NULL) throw()bool unregisterImageCallback(const CallbackHandle& callbackHandle) throw()上面一對函數(shù)分別為RGB圖像數(shù)據(jù)流的回調(diào)函數(shù)注冊與注銷。CallbackHandle registerDepthCallback(const DepthImageCallbackFunction& callback, void* cookie=NULL) th

25、row()bool unregisterDepthCallback(const CallbackHandle& callbackHandle) throw()上面一對函數(shù)分別為深度圖像數(shù)據(jù)流的回調(diào)函數(shù)注冊與注銷。CallbackHandle registerIRCallback(const IRImageCallbackFunction& callback, void* cookie=NULL) throw()bool unregisterIRCallback(const CallbackHandle& callbackHandle)throw()上面一對函數(shù)分別為紅外

26、圖像數(shù)據(jù)流的回調(diào)函數(shù)注冊與注銷。const char* getSerialNumber() const throw()獲取設(shè)備對應(yīng)的序列號,注意該返回值有可能為空字符串。const char* getConnectionString() const throw()獲取設(shè)備連接字符串,一般格式為vendorID/productIDBusID/DeviceID。const char* getVendorName() const throw()const char* getProductName() const throw()unsigned short getVendorID() const th

27、row()unsigned short getProductID() const throw()以上4個(gè)函數(shù)分別獲取廠商和產(chǎn)品的名字字符串及ID編號。unsigned char getBus() const throw()獲取設(shè)備所在的USB總線。unsigned char getAddress() const throw()獲取設(shè)備所在USB地址。void setRGBFocalLength(float focal_length)void setDepthFocalLength(float focal_length)以上兩個(gè)函數(shù)分別設(shè)定RGB與深度圖像獲取時(shí)的焦距大小。5. class op

28、enni_wrapper:DeviceKinect6. class openni_wrapper:DevicePrimesense7. class openni_wrapper:DeviceXtionPro以上3個(gè)類分別封裝了Kinect、Primesense、XtionPro相關(guān)設(shè)備操作和數(shù)據(jù)獲取操作實(shí)現(xiàn),其詳細(xì)接口參考其父類OpenNIDevice的關(guān)鍵函數(shù)說明。8. Class openni_wrapper:DeviceONI封裝了利用ONI文件回放虛擬類kinect設(shè)備的操作和數(shù)據(jù)獲取操作實(shí)現(xiàn),其詳細(xì)接口參考其父類OpenNIDevice的關(guān)鍵函數(shù)說明。9. Class openni_

29、wrapper:OpenNIDriver類OpenNIDriver采用單例模式實(shí)現(xiàn)對底層驅(qū)動(dòng)的封裝,里面包含一xn:Context對象,提供給所有設(shè)備使用。該類提供了枚舉和訪問所有設(shè)備的方法實(shí)現(xiàn)。類OpenNIDevice關(guān)鍵成員函數(shù):unsigned updateDeviceList()枚舉所有系統(tǒng)可以獲取的設(shè)備列表,返回獲取設(shè)備的數(shù)目。unsigned getNumberDevices() const throw()獲取系統(tǒng)可用設(shè)備的數(shù)目。boost:shared_ptr createVirtualDevice(const std:string& path, bool repeat

30、, bool stream) const從ONI文件創(chuàng)建一虛擬設(shè)備,其中path為ONI文件的路徑,repeat設(shè)置是否虛擬設(shè)備支持無限循環(huán)從ONI文件獲取數(shù)據(jù),stream設(shè)置虛擬設(shè)備是支持?jǐn)?shù)據(jù)流形式的數(shù)據(jù)獲取還是引發(fā)式的數(shù)據(jù)獲取。boost:shared_ptr getDeviceByIndex(unsigned index) const返回一設(shè)備,index為給定的設(shè)備索引。boost:shared_ptr getDeviceBySerialNumber(const std:string& serial_number) const返回一設(shè)備,serial_number為給定的設(shè)備

31、的序列號。boost:shared_ptr getDeviceByAddress(unsigned char bus, unsigned char address) const返回一設(shè)備,bus為USB設(shè)備總線號,address為USB設(shè)備地址。const char* getSerialNumber(unsigned index) const throw()獲取索引為index的設(shè)備序列號,但該設(shè)備未被創(chuàng)建。const char* getConnectionString(unsigned index) const throw()獲取索引為index的設(shè)備連接字符串,但該設(shè)備未被創(chuàng)建。void

32、stopAll()停止所有設(shè)備。static OpenNIDriver& getInstance()為靜態(tài)成員函數(shù),獲取唯一的設(shè)備實(shí)例。static void getDeviceType(const std:string&connection_string, unsigned short&vendorId, unsigned short& productId);為靜態(tài)成員函數(shù),獲取設(shè)備連接字符串存儲(chǔ)在connection_string,設(shè)備廠商及產(chǎn)品ID,存儲(chǔ)在為靜態(tài)成員函數(shù),獲取設(shè)備連接字符串存儲(chǔ)在connection_string,設(shè)備廠商及產(chǎn)品ID,存儲(chǔ)在

33、vendorId、productId中。10. Class openni_wrapper:OpenNIException類OpenNIException封裝一般的異常處理實(shí)現(xiàn),其關(guān)鍵成員函數(shù)如下:virtual const char* what() const throw()返回異常消息字符串。const std:string &getFunctionName() const throw()返回發(fā)生異常的函數(shù)名。const std:string &getFileName() const throw()返回發(fā)生異常的文件名。unsigned getLineNumber() con

34、st throw()返回發(fā)生異常的行號。11. Class openni_wrapper:Image類Image是簡單的圖像數(shù)據(jù)封裝基類,其繼承關(guān)系如圖4-7所示。virtual bool isResizingSupported(unsigned input_width, unsigned input_height, unsigned output_width, unsigned output_height) const = 0純虛函數(shù),具體實(shí)現(xiàn)見子類,判斷圖像是否支持尺寸變換,input_width、input_height為設(shè)定的寬度和高度,output_width、output_heig

35、ht變換后的寬度和高度。virtual void fillRGB(unsigned width, unsigned height, unsigned char *rgb_buffer, unsigned rgb_line_step=0) const = 0用RGB數(shù)據(jù)填充用戶給定的rgb_buffer,返回圖像的寬度和高度為width、height,隔rgb_line_step行輸出到輸出緩存中。virtual Encoding getEncoding() const = 0返回原始編碼的方式。void fillRaw(unsigned char *rgb_buffer) const thro

36、w()用原始數(shù)據(jù)填充用戶給定的rgb_buffer。virtual void fillGrayscale(unsigned width, unsigned height, unsigned char* gray_buffer, unsigned gray_line_step=0)const = 0用灰度數(shù)據(jù)填充給定的gray_buffer,其他參數(shù)參考函數(shù)fillRGB。unsigned getWidth() const throw()unsigned getHeight() const throw()以上兩個(gè)函數(shù)分別獲取圖像寬度和高度。unsigned getFrameID() const

37、throw()獲取幀的ID號。Unsigned longgetTimeStamp() const throw()獲取圖像的時(shí)間戳。const xn:ImageMetaData &getMetaData() const throw()獲取圖像原始OpenNI格式數(shù)據(jù)。12. Class openni_wrapper:ImageBayerGRBG13. Class openni_wrapper:ImageRGB2414. Class openni_wrapper:ImageYUV422以上3個(gè)類分別實(shí)現(xiàn)了對原始數(shù)據(jù)BayerGRBG、RGB24、YUV422到圖像轉(zhuǎn)化接口,詳細(xì)參考其父類關(guān)

38、鍵函數(shù)說明。15. Class pcl:OpenNIGrabber類OpenNIGrabber實(shí)現(xiàn)對OpenNI設(shè)備(例如Primesense PSDK,Microsoft Kinect,Asus XTion Pro/Live)數(shù)據(jù)的采集接口,詳細(xì)參考其父類Grabber關(guān)鍵函數(shù)說明。16. class pcl:PCDReader17. class pcl:PLYReader以上兩個(gè)類分別是PCD、PLY文件格式讀入接口的實(shí)現(xiàn),詳細(xì)參考其父類pcl:FileReader。18. class pcl:PLYWriter19. Class pcl:PCDWriter以上兩個(gè)類分別是PCD、PLY文

39、件格式寫出接口的實(shí)現(xiàn),詳細(xì)參考其父類pcl:FileWriter。20. Class pcl:PCLIOException類PCLIOException是I/O相關(guān)的異常處理接口實(shí)現(xiàn),詳細(xì)參考其父類PCLException。4.2.2 I/O模塊其他關(guān)鍵成員說明模塊其他關(guān)鍵成員說明PCL_EXPORTS int pcl:io:saveOBJFile(const std:string& file_name, const pcl:TextureMesh& tex_mesh, unsigned precision=5)該函數(shù)實(shí)現(xiàn)對TextureMesh保存到OBJ文件,file_na

40、me為OBJ文件名,tex_mesh為網(wǎng)格模型數(shù)據(jù),precision為保存時(shí)的精度(默認(rèn)為5)。PCL_EXPORTS int pcl:io:saveOBJFile(const std:string& file_name, const pcl:PolygonMesh& mesh, unsigned precision=5)功能同上,存儲(chǔ)對象為PolygonMesh。int pcl:io:loadPCDFile(const std:string& file_name, sensor_msgs:PointCloud2& cloud)打開一版本V6.0的PCD文件,

41、file_name為文件名,cloud存儲(chǔ)讀入的點(diǎn)云數(shù)據(jù)。templateint pcl:io:loadPCDFile(const std:string& file_name, pcl:PointCloud& cloud)打開任何類型的PCD點(diǎn)云文件,file_name為文件名,cloud存儲(chǔ)讀入的點(diǎn)云數(shù)據(jù)。int pcl:io:savePCDFile(const std:string& file_name, const sensor_msgs:PointCloud2& cloud, constEigen:Vector4f& origin=Eigen:V

42、ector4f:Zero(), const Eigen:Quaternionf& orientation=Eigen:Quaternionf:Identity(), const bool binary_mode=false)保存點(diǎn)云到PCD文件,file_name文件名,cloud需要保存的點(diǎn)云數(shù)據(jù),origin為獲取點(diǎn)云的原點(diǎn),orientation為獲取點(diǎn)云的方向,binary_mode設(shè)置是否保存為二進(jìn)制格式,默認(rèn)為false。templateint pcl:io:savePCDFile(const std:string& file_name, const pcl:Poi

43、ntCloud& cloud, bool binary_mode=false)保存點(diǎn)云到PCD文件,file_name文件名,cloud需要保存的點(diǎn)云數(shù)據(jù),binary_mode設(shè)置是否保存為二進(jìn)制格式,默認(rèn)為false。templateint pcl:io:savePCDFileASCII(const std:string& file_name, const pcl:PointCloud& cloud)以ASCII方式保存點(diǎn)云到PCD文件,file_name文件名,cloud需要保存的點(diǎn)云數(shù)據(jù)。templateint pcl:io:savePCDFileBinary(

44、const std:string& file_name, constpcl:PointCloud& cloud)以二進(jìn)制方式保存點(diǎn)云到PCD文件,file_name文件名,cloud需要保存的點(diǎn)云數(shù)據(jù)。void pcl:throwPCLIOException(const char function_name, const char file_name, unsigned line_number, const char format, )異常處理函數(shù),function_name發(fā)生異常的函數(shù)名,file_name發(fā)生異常的文件名,發(fā)生異常的行號line_number,發(fā)生異常的拋

45、出消息format。templateint pcl:io:loadPLYFile(const std:string& file_name, pcl:PointCloud& cloud)打開ply文件,file_name文件名,cloud保存打開的點(diǎn)云數(shù)據(jù)。templateint pcl:io:savePLYFile(const std:string& file_name, const pcl:PointCloud& cloud, bool binary_mode=false)保存點(diǎn)云到PLY文件,file_name文件名,cloud需要保存的點(diǎn)云數(shù)據(jù),binar

46、y_mode設(shè)置是否保存為二進(jìn)制格式,默認(rèn)為false。templateint pcl:io:savePLYFileASCII(const std:string& file_name, const pcl:PointCloud& cloud)templateint pcl:io:savePLYFileBinary(const std:string& file_name, const pcl:PointCloud& cloud)以上兩個(gè)函數(shù)分別以為ASCII和二進(jìn)制方式保存點(diǎn)云到ply文件,file_name文件名,cloud需要保存的點(diǎn)云數(shù)據(jù)。PCL_EXPOR

47、TS int pcl:io:savePLYFile(const std:string&file_name, const pcl:PolygonMesh& mesh, unsigned precision=5)保存PolygonMesh對象到PLY文件,file_name為PLY文件名,mesh為需要保存的對象數(shù)據(jù),precision為保存精度(默認(rèn)為5)。CL_EXPORTS void pcl:io:saveRgbPNGFile(const std:string &file_name, const unsigned char rgb_image, int width,

48、int height)保存RGB數(shù)據(jù)為PNG文件,file_name為PNG文件名,rgb_image為RGB數(shù)據(jù),width、height為圖像數(shù)據(jù)的寬度和高度。PCL_EXPORTS void pcl:io:saveMonoPNGFile(const std:string& file_name, const unsigned char mono_image, int width, int height)功能同上,只是保存的數(shù)據(jù)為灰度圖像格式。PCL_EXPORTS void pcl:io:saveShortPNGFile(const std:string& file_nam

49、e, const unsigned short short_image, int width, int height)功能同上,只是保存的數(shù)據(jù)為16位灰度圖像格式。templatevoid pcl:io:savePNGFile(const std:string& file_name, const pcl:PointCloud& cloud)保存點(diǎn)云中RGB域?yàn)閜ng文件,cloud為包含RGB域的點(diǎn)云對象,file_name為png文件名。PCL_EXPORTS int pcl:io:saveVTKFile(const std:string& file_name, co

50、nst pcl:PolygonMesh& triangles, unsigned precision=5)保存PolygonMesh對象數(shù)據(jù)為VTK文件,file_name為VTK文件名,triangles為需要保存的數(shù)據(jù),precision為保存精度(默認(rèn)為5)。4.3 應(yīng)用實(shí)例解析4.3.1 PCD(點(diǎn)云數(shù)據(jù)點(diǎn)云數(shù)據(jù))文件格式文件格式本小節(jié)描述PCD(點(diǎn)云數(shù)據(jù))文件格式,及其他在點(diǎn)云庫(PCL)中應(yīng)用的方法。1. 為什么用一種新的文件格式?為什么用一種新的文件格式?PCD文件格式并非白費(fèi)力氣地做重復(fù)工作,現(xiàn)有的文件結(jié)構(gòu)因本身組成的原因不支持由PCL庫引進(jìn)n維點(diǎn)類型機(jī)制處理過程中的某

51、些擴(kuò)展,而PCD文件格式能夠很好地補(bǔ)足這一點(diǎn)。PCD不是第一個(gè)支持3D點(diǎn)云數(shù)據(jù)的文件類型,尤其是計(jì)算機(jī)圖形學(xué)和計(jì)算幾何學(xué)領(lǐng)域,已經(jīng)創(chuàng)建了很多格式來描述任意多邊形和激光掃描儀獲取的點(diǎn)云。包括下面幾種格式:(1)PLY是一種多邊形文件格式,由Stanford大學(xué)的Turk等人設(shè)計(jì)開發(fā)。(2)STL是3D Systems公司創(chuàng)建的模型文件格式,主要應(yīng)用于CAD、CAM領(lǐng)域;(3)OBJ是從幾何學(xué)上定義的文件格式,首先由Wavefront Technologies開發(fā);(4)X3D是符合ISO標(biāo)準(zhǔn)的基于XML的文件格式,表示3D計(jì)算機(jī)圖形數(shù)據(jù);(5)其他許多種格式。以上所有的文件格式都有缺點(diǎn),在下一節(jié)

52、會(huì)講到。這是很自然的,因?yàn)樗鼈兪窃诓煌瑫r(shí)間為了不同的使用目的所創(chuàng)建的,那時(shí)今天的新的傳感器技術(shù)和算法都還沒有發(fā)明出來。2. PCD版本版本在點(diǎn)云庫(PCL)1.0版本發(fā)布之前,PCD文件格式有不同的修訂號。這些修訂號用PCV_Vx來編號(例如,PCD_V5、PCD_V6、PCD_V7等等),代表PCD文件的0.x版本號。然而PCL中PCD文件格式的正式發(fā)布是0.7版本(PCD_V7)。3. 文件頭格式文件頭格式每一個(gè)PCD文件包含一個(gè)文件頭,它確定和聲明文件中存儲(chǔ)的點(diǎn)云數(shù)據(jù)的某種特性。PCD文件頭必須用ASCII碼來編碼。PCD文件中指定的每一個(gè)文件頭字段以及ascii點(diǎn)數(shù)據(jù)都用一個(gè)新行(n)

53、分開了,從0.7版本開始,PCD文件頭包含下面的字段:(1)VERSION指定PCD文件版本。(2)FIELDS指定一個(gè)點(diǎn)可以有的每一個(gè)維度和字段的名字。例如:FIELDS x y z #XYZ dataFIELDS x y z rgb #XYZ+colorsFIELDS x y z normal_x normal_y normal_z #XYZ+surface normalsFIELDS j1 j2 j3(3)SIZE用字節(jié)數(shù)指定每一個(gè)維度的大小。例如:unsigned char/char? has 1 byteunsigned short/short? has 2 bytesunsigne

54、d int/int/float? Has 4 bytesdouble?has 8 bytes(4)TYPE用一個(gè)字符指定每一個(gè)維度的類型?,F(xiàn)在被接受的類型有:I表示有符號類型int8(char)、int16(short)和int32(int);U表示無符號類型uint8(unsigned char)、uint16(unsigned short)和uint32(unsigned int);F表示浮點(diǎn)類型。(5)COUNT指定每一個(gè)維度包含的元素?cái)?shù)目。例如,X這個(gè)數(shù)據(jù)通常有一個(gè)元素,但是像VFH這樣的特征描述子就有308個(gè)。實(shí)際上這是在給每一點(diǎn)引入n維直方圖描述符的方法,把它們當(dāng)做單個(gè)的連續(xù)存儲(chǔ)塊

55、。默認(rèn)情況下,如果沒有COUNT,所有維度的數(shù)目被設(shè)置成1。(6)WIDTH用點(diǎn)的數(shù)量表示點(diǎn)云數(shù)據(jù)集的寬度。數(shù)據(jù)是有序點(diǎn)云還是無序點(diǎn)云,WIDTH有兩層解釋:它能確定無序數(shù)據(jù)集的點(diǎn)云中點(diǎn)的個(gè)數(shù)(和下面的POINTS一樣)。它能確定有序點(diǎn)云數(shù)據(jù)集的數(shù)據(jù)(一行中點(diǎn)的數(shù)目)。注意:有序點(diǎn)云數(shù)據(jù)集,意味著點(diǎn)云是類似于圖像(或者矩陣)的結(jié)構(gòu),數(shù)據(jù)分為行和列。這種點(diǎn)云的實(shí)例包括立體攝像機(jī)和時(shí)間飛行攝像機(jī)生成的數(shù)據(jù)。有序數(shù)據(jù)集的優(yōu)勢在于,預(yù)先了解相鄰點(diǎn)(和像素點(diǎn))的關(guān)系,鄰域操作更加高效,這樣就加速了計(jì)算并降低了PCL中某些算法的成本。例如:WIDTH 640 #每行有640個(gè)點(diǎn)(7)HEIGHT用點(diǎn)的數(shù)目

56、表示點(diǎn)云數(shù)據(jù)集的高度。類似于WIDTH,HEIGHT也有兩層解釋:它表示有序點(diǎn)云數(shù)據(jù)集的高度(行的總數(shù));對于無序數(shù)據(jù)集它被設(shè)置成1(被用來檢查一個(gè)數(shù)據(jù)集是有序還是無序)。有序點(diǎn)云例子:WIDTH 640 #像圖像一樣的有序結(jié)構(gòu),有640行和480列HEIGHT 480 #這樣該數(shù)據(jù)集中共有640 480=307200個(gè)點(diǎn)無序點(diǎn)云例子:WIDTH 307200HEIGHT 1 #有307200個(gè)點(diǎn)的無序點(diǎn)云數(shù)據(jù)集(8)VIEWPOINT指定數(shù)據(jù)集中點(diǎn)云的獲取視點(diǎn)。VIEWPOINT有可能在不同坐標(biāo)系之間轉(zhuǎn)換的時(shí)候應(yīng)用,在輔助獲取其他特征時(shí)也比較有用,例如曲面法線,在判斷方向一致性時(shí),需要知道視

57、點(diǎn)的方位,視點(diǎn)信息被指定為平移(txtytz)+四元數(shù)(qwqxqyqz)。默認(rèn)值是:VIEWPOINT 0 0 0 1 0 0 0(9)POITNS指定點(diǎn)云中點(diǎn)的總數(shù)。從0.7版本開始該字段就有點(diǎn)多余了,因此有可能在將來的版本中將它移除。例子:POINTS 307200 #點(diǎn)云中點(diǎn)的總數(shù)為307200(10)DATA指定存儲(chǔ)點(diǎn)云數(shù)據(jù)的數(shù)據(jù)類型。從0.7版本開始支持兩種數(shù)據(jù)類型:ASCII碼和二進(jìn)制。查看下一節(jié)可以獲得更多細(xì)節(jié)。注意:文件頭最后一行(DATA)的下一個(gè)字節(jié)就被看成是點(diǎn)云的數(shù)據(jù)部分了,它會(huì)被解釋為點(diǎn)云數(shù)據(jù)。警告:PCD文件的文件頭部分必須以上面的順序精確指定,也就是如下順序:VE

58、RSION、FIELDS、SIZE、TYPE、COUNT、WIDTH、HEIGHT、VIEWPOINT、POINTS、DATA之間用換行隔開。4. 數(shù)據(jù)存儲(chǔ)類型數(shù)據(jù)存儲(chǔ)類型在0.7版本中,PCD文件格式用兩種模式存儲(chǔ)數(shù)據(jù):如果以ASCII形式,每一點(diǎn)占據(jù)一個(gè)新行:p_1p_2p_n注意:從PCL1.0.1版本開始,用字符串“nan”表示NaN,此字符表示該點(diǎn)的值不存在或非法等。如果以二進(jìn)制形式,這里數(shù)據(jù)是數(shù)組(向量)pcl:PointCloud.points的一份完整拷貝,在Linux系統(tǒng)上,我們用mmap/munmap操作來盡可能快地讀寫數(shù)據(jù),存儲(chǔ)點(diǎn)云數(shù)據(jù)可以用簡單的ASCII形式,每點(diǎn)占據(jù)

59、一行,用空格鍵或Tab鍵分開,沒有其他任何字符。也可以用二進(jìn)制存儲(chǔ)格式,它既簡單又快速,當(dāng)然這依賴于用戶應(yīng)用。ASCII格式允許用戶打開點(diǎn)云文件,使用例如gunplot這樣的標(biāo)準(zhǔn)軟件工具更改點(diǎn)云文件數(shù)據(jù),或者用sed、awk等工具來對它們進(jìn)行操作。5. 相對其他文件格式的優(yōu)勢相對其他文件格式的優(yōu)勢提高適用性和速度。(1)存儲(chǔ)和處理有序點(diǎn)云數(shù)據(jù)集的能力(2)二進(jìn)制mmap/munmap數(shù)據(jù)類型是把數(shù)據(jù)下載和存儲(chǔ)到磁盤上最快的方法;(3)存儲(chǔ)不同的數(shù)據(jù)類型(4)特征描述子的n維直方圖另一個(gè)優(yōu)勢是通過控制文件格式,我們能夠使其最大程度上適應(yīng)PCL,這樣能獲得PCL應(yīng)用程序的最好性能,而不用把一種不同

60、的文件格式改變成PCL的內(nèi)部格式,這樣的話通過轉(zhuǎn)換函數(shù)會(huì)引起額外的延時(shí)。注意:盡管PCD(點(diǎn)云數(shù)據(jù))是PCL中的內(nèi)部文件格式,pcl_I/O庫也提供在前面提到的所有其他文件格式中保存和加載數(shù)據(jù)。6. 例子例子下面是PCD文件的一個(gè)片段。把它留給讀者以解析這些數(shù)據(jù),看看它的組成。#.PCD v.7 Point Cloud Data file formatVERSION .7FIELDS x y z rgbSIZE 4 4 4 4TYPE F FFFCOUNT 1 1 1 1 WIDTH 213HEIGHT 1VIEWPORT 0 0 0 1 0 0 0 POINTS 213DATA ascii0

61、.93773 0.33763 0 4.2108e+060.90805 0.35641 0 4.2108e+064.3.2 從從PCD文件中讀取點(diǎn)云數(shù)據(jù)文件中讀取點(diǎn)云數(shù)據(jù)在本小節(jié)我們學(xué)習(xí)如何從PCD文件中讀取點(diǎn)云數(shù)據(jù)。在本書提供光盤的第4章例1文件夾中,打開名為pcd_read.cpp的代碼文件。同目錄下可找到測試點(diǎn)云文件test_pcd.pcd。1. 代碼解釋說明代碼解釋說明現(xiàn)在解析上面打開的代碼。#include /標(biāo)準(zhǔn)C+庫中的輸入輸出類相關(guān)頭文件#include /pcd讀寫類相關(guān)的頭文件#include /PCL中支持的點(diǎn)類型頭文件與本程序相關(guān)的頭文件聲明。pcl:PointCloud:Ptr c

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論