日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Ubuntu >内容正文

Ubuntu

[深度学习] RCNNs系列(1) Ubuntu下Faster RCNN配置及训练和测试自己的数据方法

發布時間:2024/9/21 Ubuntu 63 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [深度学习] RCNNs系列(1) Ubuntu下Faster RCNN配置及训练和测试自己的数据方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近用到Faster RCNN進行目標檢測,前前后后兩周把RCNN,SPPNet,Fast RCNN和Faster RCNN大體調查了一遍,準備寫一個RCNNs系列,后面還要加上今年最新的Mask RCNN。

要想開個頭,知道RCNNs在目標檢測方向的優勢,那就先用用作者的代碼,跑跑自己的代碼,下面就是在Ubuntu下進行Faster RCNN配置的方法。

一、Faster RCNN環境配置及demo運行

雖然Faster RCNN中作者加入了很多新的東西,比如怎么選Anchar,怎么計算多任務的loss等等,所幸的是作者開源了代碼,讓我們很容易就能夠用他的算法實現我們自己的任務。在運行自己的任務之前,我們首先要做的就是確保我們已經配置好源代碼的運行環境。 本文是在Caffe已經配置好的條件下進行的,如果Caffe的需求庫,比如opencv等等還沒有弄好,建議先去把Caffe配置好。 (1)首先使用git把Faster RCNN的源碼下載到本地: [html] view plaincopy
  • git?clone?--recursive?https://github.com/rbgirshick/py-faster-rcnn.git????
  • (2)安裝cpython和python-opencv [html] view plaincopy
  • pip?install?cpython??
  • apt-get?install?python-opencv??
  • (3)下載Faster RCNN并安裝好cpython以后,進入py-faster-rcnn/lib中使用命令編譯一下 [html] view plaincopy
  • make??
  • (4)進入py-faster-rcnn/caffe-fast-rcnn,配置Makefile.config文件,目錄中有Makefile.config.example文件,可以按照這個文件進行修改,或者使用你配置caffe時的Makefile.config文件。我這里有一個配置文件,可以參考。我的配置文件用到了cuDNN,開始我使用cuDNN的時候總會在編譯時報錯,后來在在windows上配置py-faster-rcnn和調參經驗中找到了解決辦法,解決辦法如下:
    • 把Caffe中的include/caffe/layers/cudnn_relu_layer.hpp,/include/caffe/layers/cudnn_sigmoid_layer.hpp,/include/caffe/layers/cudnn_tanh_layer.hpp和/include/caffe/util/cudnn.hpp替換py-faster-rcnn/caffe-fast-rcnn中對應的文件;
    • 把Caffe中的src/caffe/layers/cudnn_relu_layer.cpp,src/caffe/layers/cudnn_relu_layer.cu,src/caffe/layers/cudnn_sigmoid_layer.cpp,src/caffe/layers/cudnn_sigmoid_layer.cu,src/caffe/layer/cudnn_tanh_layer.cpp,src/caffe/layers/cudnn_tanh_layer.cu替換掉py-faster-rcnn/caffe-fast-rcnn中對應的文件;
    • 把py-faster-rcnn/caffe-fast-rcnn中src/caffe/layers/cudnn_conv_layer.cu文件中的cudnnConvolutionBackwardData_v3全部換為cudnnConvolutionBackwardData,把cudnnConvolutionBackwardFilter_v3全部換為cudnnConvolutionBackwardFilter。
    如果自己的顯卡配置足夠的話,強烈建議開啟cudnn,cudnn不僅可以起到加速的作用,而且我跑實驗的時候發現加入cudnn以后可以明顯的降低顯存的使用。如下圖所示: 開啟cudnn之前:
    開啟cudnn之后:
    可以看到顯存減少了將近2G,非常可觀,強烈建議開啟。 (5)配置好Makefile以后,在caffe-fast-rcnn中執行命令進行編譯 [html] view plaincopy
  • make?-j8?&&?make?pycaffe??
  • (6)這個時候,基本上faster RCNN也就配置好了,讓我們看一下是否真的能夠運行。首先我們下載幾個作者已經訓練好的caffemodel,如果現在直接運行demo.py的話會提示你沒有caffemodel文件,然后詢問是否運行過py-faster-rcnn/data/scripts/fetch_faster_rcnn_models.sh文件,我們可以找到該文件中的下載鏈接,用迅雷一會就可以下載好,如果直接運行該文件可能要不少時間。把下載好的文件中VGG16_faster_rcnn_final.caffemodel文件復制到py-faster-rcnn/data/faster_rcnn_models中 (7)運行py-faster-rcnn/experiments/tools/demo.py文件,不出意外的話,會出現如下錯誤:
    修改py-faster-rcnn/lib/fast_rcnn/train.py文件,在文件中引入text_format [python] view plaincopy
  • import?google.protobuf.text_format??
  • 再次運行demo.py文件,這次應該可以運行成功!

    二、Faster RCNN訓練自己的數據

    既然已經把Faster RCNN配置好,下一步我們來訓練自己的數據吧。Faster RCNN論文中采用的訓練方法分為幾個階段,訓練起來比較麻煩,我們這里采用源碼中的end to end的訓練方式,更簡便一些。

    2.1 建立數據集

    為了讓我們的訓練更簡單些,我們不去改動源碼中讀寫數據的方式,而是把我們的數據集改成Pascal VOC的數據集格式,Pascal VOC數據集主要分為三個部分:Annotations,JPEGImages和ImageSets。其中JPEGImages中存放的是訓練和測試時需要的圖像;Annotations存放的是每個圖像中所有目標的bounding box信息,每個圖像對應一個xml文件;ImageSet文件中存放的Main目錄,而Main目錄中就是訓練和測試時需要的文件列表,主要分為train.txt, test.txt, trainval.txt, val.txt可以根據文件名就知道哪些是訓練數據列表,哪些是測試數據列表。 這里如果我們有這樣結構的數據集當然最好了,如果沒有這樣的數據集的話就需要自己建立。建立數據集的話可以參考:將數據集做成VOC2007格式用于Faster-RCNN訓練——小咸魚_的博客。 這里解說一下我的獲取方法,因為我的數據比較特殊,是由在線數據轉換過來的,所以我很容易的就獲得了各個目標的bounding box信息,所以沒有使用參考博客的方法。我最終獲得的bounding box信息文件如下所示: [html] view plaincopy
  • Train_IMG\000001.jpg?97?6?174?202?305??
  • Train_IMG\000001.jpg?8?56?198?282?162??
  • ......省略若干行??
  • Train_IMG\000001.jpg?90?537?194?699?314??
  • 其中每個圖像對應一個bounding box文件,每個文件中的每一行表示一個目標的bounding box,每一行由6列數據組成,第1列數據為圖像的路徑,第2列為該目標的分類,第3列為bounding box的左上角的x(對應圖像的列,即mincol),第4列為bounding box的左上角的y(對應圖像的行,即minrow),第5列為bounding box的右下角的x(對應圖像的列,即maxcol),第6列為bounding box右下角的y(對應圖像的行,即maxrow)。 然后我們接下來要做的就是把這些bounding box文件轉換為VOC數據集格式的xml文件,我這里是從github上找到的一個Python開源代碼(但是作者的原址找不到了,所以這里沒能給出參考鏈接,如果有人有原址歡迎告知,我會把原址貼上)上進行的改動,源碼如下: [python] view plaincopy
  • #?-*-?coding:utf-8?-*-??
  • ??
  • __author__?=?"peic"??
  • ??
  • import?xml.dom??
  • import?xml.dom.minidom??
  • import?os??
  • ??
  • from?PIL?import?Image??
  • ??
  • '''''?
  • 根據下面的路徑和文件,將output.txt制作成xml的標注?
  • '''??
  • ??
  • #?xml文件規范定義??
  • _INDENT?=?'?'?*?4??
  • _NEW_LINE?=?'\n'??
  • _FOLDER_NODE?=?'VOC2007'??
  • _ROOT_NODE?=?'annotation'??
  • _DATABASE_NAME?=?'CROHME?offline?ME?Dataset'??
  • _CLASS?=?'person'??
  • _ANNOTATION?=?'PASCAL?VOC2007'??
  • _AUTHOR?=?'hanchao'??
  • ??
  • _SEGMENTED?=?'0'??
  • _DIFFICULT?=?'0'??
  • _TRUNCATED?=?'0'??
  • _POSE?=?'Unspecified'??
  • #需要注意,這一項是存放bounding?box對應圖像的目錄??
  • _IMAGE_PATH?=?'Train_IMG'??
  • #這一項是保存生成xml文件的目錄??
  • _ANNOTATION_SAVE_PATH?=?'Annotations'??
  • ??
  • _IMAGE_CHANNEL?=?3??
  • ??
  • ??
  • #?封裝創建節點的過程??
  • def?createElementNode(doc,?tag,?attr):??
  • ????#?創建一個元素節點??
  • ????element_node?=?doc.createElement(tag)??
  • ??
  • ????#?創建一個文本節點??
  • ????text_node?=?doc.createTextNode(attr)??
  • ??
  • ????#?將文本節點作為元素節點的子節點??
  • ????element_node.appendChild(text_node)??
  • ??????
  • ????return?element_node??
  • ??
  • ??
  • #?封裝添加一個子節點的過程??
  • def?createChildNode(doc,?tag,?attr,?parent_node):??
  • ??
  • ????child_node?=?createElementNode(doc,?tag,?attr)??
  • ????parent_node.appendChild(child_node)??
  • ??
  • #?object節點比較特殊??
  • def?createObjectNode(doc,?attrs):??
  • ????object_node?=?doc.createElement('object')??
  • ????createChildNode(doc,?'name',?attrs['classification'],?object_node)??
  • ????createChildNode(doc,?'pose',?_POSE,?object_node)??
  • ????createChildNode(doc,?'truncated',?_TRUNCATED,?object_node)??
  • ????createChildNode(doc,?'difficult',?_DIFFICULT,?object_node)??
  • ??
  • ????bndbox_node?=?doc.createElement('bndbox')??
  • ????createChildNode(doc,?'xmin',?attrs['xmin'],?bndbox_node)??
  • ????createChildNode(doc,?'ymin',?attrs['ymin'],?bndbox_node)??
  • ????createChildNode(doc,?'xmax',?attrs['xmax'],?bndbox_node)??
  • ????createChildNode(doc,?'ymax',?attrs['ymax'],?bndbox_node)??
  • ????object_node.appendChild(bndbox_node)??
  • ??
  • ????return?object_node??
  • ??
  • #?將documentElement寫入XML文件中??
  • def?writeXMLFile(doc,?filename):??
  • ????tmpfile?=?open('tmp.xml',?'w')??
  • ????doc.writexml(tmpfile,?addindent='?'*4,?newl='\n',?encoding='utf-8')??
  • ????tmpfile.close()??
  • ??
  • ??
  • ????#?刪除第一行默認添加的標記??
  • ????fin?=?open('tmp.xml')??
  • ????fout?=?open(filename,?'w')??
  • ????lines?=?fin.readlines()??
  • ??
  • ????for?line?in?lines[1:]:??
  • ????????if?line.split():??
  • ????????????fout.writelines(line)??
  • ??
  • ????#new_lines?=?''.join(lines[1:])??
  • ????#fout.write(new_lines)??
  • ????fin.close()??
  • ????fout.close()??
  • ??
  • #?創建XML文檔并寫入節點信息??
  • def?createXMLFile(attrs,?width,?height,?filename):??
  • ??
  • ????#?創建文檔對象,?文檔對象用于創建各種節點??
  • ????my_dom?=?xml.dom.getDOMImplementation()??
  • ????doc?=?my_dom.createDocument(None,?_ROOT_NODE,?None)??
  • ??
  • ????#?獲得根節點??
  • ????root_node?=?doc.documentElement??
  • ??
  • ????#?folder節點??
  • ????createChildNode(doc,?'folder',?_FOLDER_NODE,?root_node)??
  • ??????
  • ????#?filename節點??
  • ????createChildNode(doc,?'filename',?attrs['name'],?root_node)??
  • ??
  • ????#?source節點??
  • ????source_node?=?doc.createElement('source')??
  • ????#?source的子節點??
  • ????createChildNode(doc,?'database',?_DATABASE_NAME,?source_node)??
  • ????createChildNode(doc,?'annotation',?_ANNOTATION,?source_node)??
  • ????createChildNode(doc,?'image',?'flickr',?source_node)??
  • ????createChildNode(doc,?'flickrid',?'NULL',?source_node)??
  • ????root_node.appendChild(source_node)??
  • ??
  • ????#?owner節點??
  • ????owner_node?=?doc.createElement('owner')??
  • ????#?owner的子節點??
  • ????createChildNode(doc,?'flickrid',?'NULL',?owner_node)??
  • ????createChildNode(doc,?'name',?_AUTHOR,?owner_node)??
  • ????root_node.appendChild(owner_node)??
  • ??
  • ????#?size節點??
  • ????size_node?=?doc.createElement('size')??
  • ????createChildNode(doc,?'width',?str(width),?size_node)??
  • ????createChildNode(doc,?'height',?str(height),?size_node)??
  • ????createChildNode(doc,?'depth',?str(_IMAGE_CHANNEL),?size_node)??
  • ????root_node.appendChild(size_node)??
  • ??
  • ????#?segmented節點??
  • ????createChildNode(doc,?'segmented',?_SEGMENTED,?root_node)??
  • ??
  • ????#?object節點??
  • ????object_node?=?createObjectNode(doc,?attrs)??
  • ????root_node.appendChild(object_node)??
  • ??
  • ????#?寫入文件??
  • ????writeXMLFile(doc,?filename)??
  • ??
  • def?generate_xml(txt_filename):??
  • ????#注意,這里的txt_filename文件是待轉換的bounding?box文件??
  • ????ouput_file?=?open(txt_filename)??
  • ????current_dirpath?=?os.path.dirname(os.path.abspath('__file__'))??
  • ??
  • ????if?not?os.path.exists(_ANNOTATION_SAVE_PATH):??
  • ????????os.mkdir(_ANNOTATION_SAVE_PATH)??
  • ??
  • ????lines?=?ouput_file.readlines()??
  • ????for?line?in?lines:??
  • ????????s?=?line.rstrip()??
  • ????????array?=?s.split('?')??
  • ????????#print?len(array)??
  • ????????attrs?=?dict()??
  • ????????attrs['name']?=?array[0].split('\\')[1]??
  • ????????attrs['classification']?=?array[1]??
  • ????????attrs['xmin']?=?array[2]??
  • ????????attrs['ymin']?=?array[3]??
  • ????????attrs['xmax']?=?array[4]??
  • ????????attrs['ymax']?=?array[5]??
  • ??
  • ????????#?構建XML文件名稱??
  • ????????xml_file_name?=?os.path.join(_ANNOTATION_SAVE_PATH,?(attrs['name'].split('.'))[0]?+?'.xml')??
  • ????????#print?xml_file_name??
  • ??
  • ????????if?os.path.exists(?xml_file_name):??
  • ????????????#?print('do?exists')??
  • ????????????existed_doc?=?xml.dom.minidom.parse(xml_file_name)??
  • ????????????root_node?=?existed_doc.documentElement??
  • ??????????????
  • ????????????#?如果XML存在了,?添加object節點信息即可??
  • ????????????object_node?=?createObjectNode(existed_doc,?attrs)??
  • ????????????root_node.appendChild(object_node)??
  • ??
  • ????????????#?寫入文件??
  • ????????????writeXMLFile(existed_doc,?xml_file_name)??
  • ??????????????
  • ????????else:??
  • ????????????#?print('not?exists')??
  • ????????????#?如果XML文件不存在,?創建文件并寫入節點信息??
  • ????????????img_name?=?attrs['name']??
  • ????????????img_path?=?os.path.join(current_dirpath,?_IMAGE_PATH,?img_name)??
  • ????????????#?獲取圖片信息??
  • ????????????img?=?Image.open(img_path)??
  • ????????????width,?height?=?img.size??
  • ????????????img.close()??
  • ??????????????
  • ????????????#?創建XML文件??
  • ????????????createXMLFile(attrs,?width,?height,?xml_file_name)??
  • ??????????????
  • 執行的Main程序如下: [python] view plaincopy
  • #coding=utf-8??
  • '''''?
  • Created?on?2017年4月18日?
  • ?
  • @author:?hanchao?
  • '''??
  • import?generate_xml??
  • import?os.path??
  • import?cv2??
  • #???
  • if?__name__?==?"__main__":??
  • ????for?dir,path,filenames?in?os.walk('Train_BB'):#Train_BB是存放bounding?box文件的目錄??
  • ????????for?filename?in?filenames:??
  • ????????????print?dir??+?'/'?+?filename??
  • ????????????generate_xml.generate_xml(dir??+?'/'?+?filename)??
  • 最終生成的xml文件會保存在Annotations目錄中。 對于ImageSets/Main中的幾個文件就比較好建立了,只需要把訓練、驗證和測試集中圖像名稱寫入到對應的文件中即可。 接下來,可以自己在py-faster-rcnn/data中建立一個VOCdevkit2007目錄,在該目錄中建立VOC2007子目錄,然后把JPEGImages,Annotaions和ImageSets目錄復制到該目錄中,即準備好了自己的數據。 注意:Faster RCNN對圖像和目標的大小以及長寬比是有一定要求的,具體的討論見用ImageNet的數據集(ILSVRC2014)訓練Faster R-CNN——Jiajun的博客 在這里我有深痛的教訓T_T,我的數據集中設置目標的長寬比在0.1~10之間,圖像的長寬比在0.3~7之間

    2.2 訓練自己的數據

    經過前面的鋪墊,我們終于可以訓練自己的數據了。 接下來我們需要下載幾個模型,看過論文的都知道,作者的訓練首先使用在ImageNet上訓練好的模型對網絡結構進行初始化,然后再訓練的網絡,我們現在下載的模型就是進行初始化的模型,下載地址:https://pan.baidu.com/s/1c2tfkRm?下載完成后,把文件加壓把模型放在py-faster-rcnn/data/imagenet_models中即可。 接下來,我們只需要更改幾個文件即可。(注意,我這里使用的是端到端的訓練方式,所以改動全部為end to end的,如果使用論文中的分階段訓練的方式,則需要改動alt_opt對應的文件) (1)更改py-faster-rcnn/experiments/scripts/faster_rcnn_end2end.sh文件,該文件中的問題在于沒有設置各個文件的絕對路徑,所以運行起來可能有問題,把兩個time后的路徑設置加上py-faster-rcnn的絕對路徑即可,我更改后示例如下: [python] view plaincopy
  • time?/home/hanchao/py-faster-rcnn/tools/train_net.py?--gpu?${GPU_ID}?\??
  • ??--solver?/home/hanchao/py-faster-rcnn/models/${PT_DIR}/${NET}/faster_rcnn_end2end/solver.prototxt?\??
  • ??--weights?/home/hanchao/py-faster-rcnn/data/imagenet_models/${NET}.v2.caffemodel?\??
  • ??--imdb?${TRAIN_IMDB}?\??
  • ??--iters?${ITERS}?\??
  • ??--cfg?/home/hanchao/py-faster-rcnn/experiments/cfgs/faster_rcnn_end2end.yml?\??
  • ??${EXTRA_ARGS}??
  • (2)更改py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_end2end目錄中的train,test和solver文件(我采用的是VGG16網絡,如果使用ZF網絡,去修改對應目錄下文件即可)。把train和test中所有的21和84改成你的分類類型數+1(你的分類類型數+1)×4即可。在solver文件中加入絕對路徑; (3)更改py-faster-rcnn/lib/datasets/pascal_voc.py文件,更改self._classes中標簽換成自己的標簽,即 [python] view plaincopy
  • self._classes?=?('__background__',?#?always?index?0??
  • ?????????????????'你的標簽1',?'你的標簽2',?'你的標簽3')??
  • 注意這里的標簽不要有大寫符號。 (4)文章中還采用了horizontal flip以擴充數據, 我的數據是字符,因此不能擴充,所以我把py-faster-rcnn/lib/datasets/imdb.py中append_flipped_images(self)函數改為 [python] view plaincopy
  • ????def?append_flipped_images(self):??
  • #????????num_images?=?self.num_images??
  • #????????widths?=?self._get_widths()??
  • #????????for?i?in?xrange(num_images):??
  • #????????????boxes?=?self.roidb[i]['boxes'].copy()??
  • #????????????oldx1?=?boxes[:,?0].copy()??
  • #????????????oldx2?=?boxes[:,?2].copy()??
  • #????????????boxes[:,?0]?=?widths[i]?-?oldx2?-?1??
  • #????????????boxes[:,?2]?=?widths[i]?-?oldx1?-?1??
  • #????????????assert?(boxes[:,?2]?>=?boxes[:,?0]).all()??
  • #????????????entry?=?{'boxes'?:?boxes,??
  • #?????????????????????'gt_overlaps'?:?self.roidb[i]['gt_overlaps'],??
  • #?????????????????????'gt_classes'?:?self.roidb[i]['gt_classes'],??
  • #?????????????????????'flipped'?:?True}??
  • #????????????self.roidb.append(entry)??
  • #????????self._image_index?=?self._image_index?*?2??
  • ????????self._image_index?=?self._image_index??
  • 如果你的數據比較多的話同樣也可以去掉這個函數,該函數也可能會引發一些問題,具體更改和解決方法參見Faster-RCNN+ZF用自己的數據集訓練模型(Python版本)——小咸魚_的博客 好啦,接下來應該就可以愉快的訓練自己的數據了,進入py-faster-rcnn/experiments/scripts目錄,使用命令 [python] view plaincopy
  • faster_rcnn_end2end.sh?0?VGG16?pascal_voc??
  • 其中0表示你訓練時使用的gpu標號,VGG16是模型類型,具體的內容可以去讀faster_rcnn_end2end.sh的源碼。 (注意:如果更改數據以后,再次訓練以前一定要把py-faster-rcnn/data中的cache目錄刪掉,否則訓練時用的還是以前的數據) 訓練結束后,把訓練好的模型放入到py-faster-rcnn/data/faster_rcnn_models中,然后調用把demo.py中的測試圖片換成自己的測試圖像,運行進行測試,如果有需要,也可以自己修改demo文件,程序還是很容易看懂的。
    這就是訓練的全部過程了,因為配置起來也有一定的時間了,有些錯誤也記不太清了,我把我還記得的坑都寫在上面了,如果配置過程中有其他的一些錯誤,歡迎在評論里一起交流。

    附錄

    ———————————————————————— 1. 在測試的時候,可能會出現IndexError: too many indices for array,出現這個錯誤的原因是你的測試集中有的類別沒有出現,在這里只需要在py-faster-rcnn/lib/datasets/voc_eval.py中BB = BB[sorted_ind, :]前一句加上if len(BB) != 0:即可。 2. 在測試時還有可能出現KeyError: '某樣本名',這是因為你數據更改了,但是程序有cache文件,把py-faster-rcnn/data/VOCdevkit2007/annotations_cache目錄刪除即可。

    總結

    以上是生活随笔為你收集整理的[深度学习] RCNNs系列(1) Ubuntu下Faster RCNN配置及训练和测试自己的数据方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。