Nvidia jetson nano Caffe Mobilnet-SSD 訓練自己的數據

參考自:

            https://blog.csdn.net/weixin_39750664/article/details/82502302

 

目錄

1.下載Mobilnet ssd

2.製作VOC數據集

修改create_list.sh

修改create_data.sh

修改好後,生成lmdb數據庫

訓練前準備

    1.把labelmap_voc.prototxt複製到工程文件下

    2.把上面兩個lmdb數據庫複製到工程下

    3.將labelmap_voc .prototxt改名爲labelmap.prototxt

    4.將VOC2007_test_lmdb改名爲test_lmdb

    5.將VOC2007_trainval_lmdb改名爲trainval_lmdb

    6.如下圖

    7.運行gen_model.sh腳本

    8.進入examples文件夾,打開編輯MobilNetSSD_train.prototxt(MobileNetSSD_test.prototxt文件類似地方也改下)

    9.回到上一層目錄,編輯train.sh文件

    10.修改solver_train.prototxt文件

訓練

訓練完成後,運行檢測

測試報錯解決


 

1.下載Mobilnet ssd

git下載:

git clone https://github.com/chuanqi305/MobileNet-SSD.git

網站下載:https://github.com/chuanqi305/MobileNet-SSD

 

2.製作VOC數據集

目錄結構是這樣的

|--VOCseahorse

           |--VOC2007

                    |--Annotations

                    |--ImageSets

                              |--Layout

                              |--Main

                              |--Segmentation

                    |--JPEGImages

    ·這裏解釋下Annotations是放xml的,就是放置標註(物體位置 類別)好了的文件,用的labelImg軟件標註的。

    ·ImageSets下面的Main放的是文本,裏面有4個文件  test.txt  val,txt  train.txt   trainval.txt,分別爲測試圖片,驗證圖片,訓練圖片,訓練驗證圖片的文件名。其他Layout和Segmentation佔時用不到,可以放Main中一樣的文件進去。

    ·JPEGImages是放置圖片的

這個目錄結構的文件我會提供,裏面也包含了標註好的圖片。下面說說如何製作。

我修改過的工程文件:https://download.csdn.net/download/ourkix/12076480

標註軟件下載:https://github.com/tzutalin/labelImg

我用的編譯好的,上面的是源碼,你們也可以去下載編譯好的。

想知道如何標註,可以自己查查 研究研究,比較簡單,看看應該會(就選好圖片文件夾路徑,右鍵選擇方框,左鍵拉框,標上label值,保存xml文件即可)

這裏默認標定好了數據 xml放入到annotations文件夾裏面了。

按照上面的目錄結構建立好文件夾,去到caffe的根目錄,切換到data/VOC0712/,將裏面的create_data.sh create_list.sh  labelmap_voc.prototxt文件複製到你建立的目錄的VOC2007下面

接下來進入imagesets文件夾的main

修改 test.txt 和 trainval.txt文件

trainval是要訓練的圖片,test是測試圖片,這裏直接填上圖片的名字就行了。圖片多的話可以用腳本來生成。

修改create_list.sh

#!/bin/bash
#你數據的路徑
root_dir=$HOME/caffe/caffe-ssd/data/VOCseahorse
sub_dir=ImageSets/Main
bash_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
for dataset in trainval test
do
  dst_file=$bash_dir/$dataset.txt
  if [ -f $dst_file ]
  then
    rm -f $dst_file
  fi
  for name in VOC2007
  do
    if [[ $dataset == "test" && $name == "VOC2012" ]]
    then
      continue
    fi
    echo "Create list for $name $dataset..."
    dataset_file=$root_dir/$name/$sub_dir/$dataset.txt

    img_file=$bash_dir/$dataset"_img.txt"
    cp $dataset_file $img_file
    sed -i "s/^/$name\/JPEGImages\//g" $img_file
    sed -i "s/$/.jpg/g" $img_file

    label_file=$bash_dir/$dataset"_label.txt"
    cp $dataset_file $label_file
    sed -i "s/^/$name\/Annotations\//g" $label_file
    sed -i "s/$/.xml/g" $label_file

    paste -d' ' $img_file $label_file >> $dst_file

    rm -f $label_file
    rm -f $img_file
  done

  # Generate image name and size infomation.
  if [ $dataset == "test" ]
  then
    $HOME/caffe/caffe-ssd/build/tools/get_image_size $root_dir $dst_file $bash_dir/$dataset"_name_size.txt"
  fi

  # Shuffle trainval file.
  if [ $dataset == "trainval" ]
  then
    rand_file=$dst_file.random
    cat $dst_file | perl -MList::Util=shuffle -e 'print shuffle(<STDIN>);' > $rand_file
    mv $rand_file $dst_file
  fi
done

修改create_data.sh

cur_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
#咖啡根目錄路徑
root_dir=$HOME/caffe/caffe-ssd

cd $root_dir

redo=1
#你的數據的路徑
data_root_dir="$HOME/caffe/caffe-ssd/data/VOCseahorse"
dataset_name="VOC2007"
#labelmap路徑
mapfile="$root_dir/data/VOCdevkits/$dataset_name/labelmap_voc.prototxt"
anno_type="detection"
db="lmdb"
min_dim=0
max_dim=0
width=300 #0
height=300 #0

extra_cmd="--encode-type=jpg --encoded"
if [ $redo ]
then
  extra_cmd="$extra_cmd --redo"
fi
for subset in test trainval
do
  python $root_dir/scripts/create_annoset.py --anno-type=$anno_type --label-map-file=$mapfile --min-dim=$min_dim --max-dim=$max_dim --resize-width=$width --resize-height=$height --check-label $extra_cmd $data_root_dir $root_dir/data/VOCseahorse/$dataset_name/$subset.txt $data_root_dir/$dataset_name/$db/$dataset_name"_"$subset"_"$db examples/$dataset_name
done
#如果你路基不同的話 上面這裏面的路徑也要改

 修改labelmap_voc.prototxt文件(背景層爲0,有幾個類就寫幾個item)

item {
  name: "none_of_the_above"
  label: 0
  display_name: "background"
}
item {
  name: "seahorse"
  label: 1
  display_name: "seahorse"
}

修改好後,生成lmdb數據庫

chmod +x creat_list.sh creat_data.sh
./creat_list.sh
./creat_data.sh

執行完成後會創建出lmdb文件夾進入此文件夾

訓練前準備

    1.把labelmap_voc.prototxt複製到工程文件下

    2.把上面兩個lmdb數據庫複製到工程下

    3.將labelmap_voc .prototxt改名爲labelmap.prototxt

    4.將VOC2007_test_lmdb改名爲test_lmdb

    5.將VOC2007_trainval_lmdb改名爲trainval_lmdb

    6.如下圖

    7.運行gen_model.sh腳本

執行命令:./gen_model.sh 2

數字爲類別數,注意,實際類別+1,有個默認的背景類

之後,生成examples文件夾,裏面的3個prototxt就是從模板生成的正式網絡定義,根據作者設置,其中的deploy文件是已經合併過bn層的,需要後面配套使用。

    8.進入examples文件夾,打開編輯MobilNetSSD_train.prototxt(MobileNetSSD_test.prototxt文件類似地方也改下)

#找到這個,改成你自己的數據庫路徑  
#batch_size 爲批量大小,根據自己的平臺內存大小來 4 和 8 都可以
data_param {
    source: "trainval_lmdb/"
    batch_size: 4
    backend: LMDB
  }

#找到這個,改成你自己的labelmap路徑 
 label_map_file: "/home/ubuntuq/mobilenet/MobileNet-SSD/labelmap.prototxt"

    9.回到上一層目錄,編輯train.sh文件

/home/ubuntuq/caffe/caffe-ssd/build/tools/caffe 是你的caffe的路徑

solver="solver_train.prototxt"  這個是訓練參數文件

weights="mobilenet_iter_73000.caffemodel" 這個是預訓練模型

#!/bin/sh
if ! test -f example/MobileNetSSD_train.prototxt ;then
	echo "error: example/MobileNetSSD_train.prototxt does not exist."
	echo "please use the gen_model.sh to generate your own model."
        exit 1
fi
mkdir -p snapshot
/home/ubuntuq/caffe/caffe-ssd/build/tools/caffe train -solver="solver_train.prototxt" \
-weights="mobilenet_iter_73000.caffemodel" \
-gpu 0 

    10.修改solver_train.prototxt文件

#訓練網絡的文件路徑
train_net: "example/MobileNetSSD_train.prototxt"
#基礎學習率
base_lr: 0.0005
display: 10
#最大訓練迭代次數
max_iter: 5000
lr_policy: "multistep"
gamma: 0.5
weight_decay: 0.00005
#訓練多少次一次快照
snapshot: 2500
#快照模型保存路徑
snapshot_prefix: "snapshot/mobilenet"
#訓練方式 GPU 還是 CPU
solver_mode: GPU
debug_info: false
snapshot_after_train: true
test_initialization: false
average_loss: 10
stepvalue: 20000
stepvalue: 40000
iter_size: 1
type: "RMSProp"
eval_type: "detection"
ap_version: "11point"

訓練

./train.sh

訓練完成後,運行檢測

如果下載我的上傳的文件,進入testmodel文件夾,裏面是我之前訓練好的,你把裏面的文件換成你自己的

deploy.prototxt文件是example文件夾裏面的MobileNetSSD_deploy.prototxt,複製過來改名即可

labelmap.prototxt就是我們之前改的那個,複製進來

mobilenet_iter_5000.caffemodel是訓練完的模型文件,在snapshot文件夾裏面複製過來

image裏面是測試圖片

 

裏面的demo.py也修改下。

import numpy as np  
import sys,os  
import cv2
#caffe路徑 根目錄
caffe_root = '/home/ubuntuq/caffe/caffe-ssd/'
sys.path.insert(0, caffe_root + 'python')  
import caffe  

#部署文件路徑
net_file= 'deploy.prototxt'  
#模型文件路徑
caffe_model='mobilenet_iter_5000.caffemodel'  
#測試圖片路徑
test_dir = "image"

if not os.path.exists(caffe_model):
    print(caffe_model + " does not exist")
    exit()
if not os.path.exists(net_file):
    print(net_file + " does not exist")
    exit()
net = caffe.Net(net_file,caffe_model,caffe.TEST)  

#分類顯示名字修改
CLASSES = ('background',
           'seahorse')


def preprocess(src):
    img = cv2.resize(src, (300,300))
    img = img - 127.5
    img = img * 0.007843
    return img

def postprocess(img, out):   
    h = img.shape[0]
    w = img.shape[1]
    box = out['detection_out'][0,0,:,3:7] * np.array([w, h, w, h])

    cls = out['detection_out'][0,0,:,1]
    conf = out['detection_out'][0,0,:,2]
    return (box.astype(np.int32), conf, cls)

def detect(imgfile):
    origimg = cv2.imread(imgfile)
    img = preprocess(origimg)
    
    img = img.astype(np.float32)
    img = img.transpose((2, 0, 1))

    net.blobs['data'].data[...] = img
    out = net.forward()  
    box, conf, cls = postprocess(origimg, out)

    #print("box is ",box)

    for i in range(len(box)):
       p1 = (box[i][0], box[i][1])
       p2 = (box[i][2], box[i][3])
       cv2.rectangle(origimg, p1, p2, (0,255,0))
       p3 = (max(p1[0], 15), max(p1[1], 15))
       #print("---",i)
       title = "%s:%.2f" % (CLASSES[int(cls[i])], conf[i])
       cv2.putText(origimg, title, p3, cv2.FONT_ITALIC, 0.6, (0, 255, 0), 1)


    cv2.imshow("SSD", origimg)
 
    k = cv2.waitKey(0) & 0xff
        #Exit if ESC pressed
    if k == 27 : return False
    return True

for f in os.listdir(test_dir):
    if detect(test_dir + "/" + f) == False:
       break

測試(回車下一張,esc退出)

python demo.py

測試報錯解決

原因是caffe-ssd缺少了relu6層,要修改caffe源碼重新編輯就行了。

下載這兩個文件

下載地址:https://github.com/chuanqi305/MobileNetv2-SSDLite/tree/master/src

去到你的caffe根目錄,進入src/caffe/layers將這兩個文件複製進去覆蓋掉原來的文件。

然後去到你的caffe構建目錄,我的是build目錄

make -j4
make pycaffe
make install

完成後重新打開終端,運行demo.py

發佈了19 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章