yolo-v2修改只識別person
問題1:為什么classes改為1就是檢測person了還不是其它的目標,可能是因為 cfg/coco.data 中,names = data/coco.names,而coco.names中person排第一個
查看run_detector和draw_detections函數的源碼,修改的兩個參數都是代表類別數
驗證:將上面的1全部都改為2,查看coco.names里前兩個分別為 person 和 bicycle 經測試,此時只檢測這兩類
問題2: 當輸入為 ./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg 時,調用的函數為test_detector
而當輸入為 ./darknet detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights data/dog.jpg 時,調用的函數為 run_detector,在run_detector中再次調用了test_detector
所以如果用第一行的命令,是不是只需修改test_detector即可?
驗證:可行
~/darknet/examples/darknet.c
main函數
line 408 ~/darknet/ 下的darknet文件是怎么得來的,為什么只有輸入./darknet 時才會顯示 usage: ./darknet <function>
line 412 給gpu-index賦值時為什么是find_int_arg函數的參數是 " -i "
line 425 這里開始的 if 語句就是 ./darknet<function> 中的各種 function 了
目標:使輸入一張圖片,只檢測人體
這里測試時用的是
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
找到 “detect" 所對應的函數
line 435 test_detector("cfg/coco.data", argv[2], argv[3], filename, thresh, .5, outfile, fullscreen) 函數,找到其定義在下面的文件中
~/darknet/examples/detector.c
test_detector函數
line 565 第一個輸入參數為datacfg,根據前文,默認輸入為 cfg/coco.data 查看此文件,coco.data 中的 train,valid,backup的路徑都沒有找到在哪
options是read_data_cfg函數讀取datacfg后返回的一個list類
line 566 這里的data/name.list 是什么意思
line 570 load_network函數是如何構建net的,見后文network.c
line 576 nms的用途沒看明白,見line 604
line 587 image im = load_image_color(input,0,0)這個函數涉及OpenCV操作,與圖片顯示有關,后面再細看
image結構體里有w,h,c,data四個變量,w,h,應該是表示寬度和高度,單位應該是像素,c表示通道數,data還不知道表示什么
line 593 這幾行還得仔細看看 net,network結構體中有一個變量layers,其類型為layer,layer也是一個結構體,因此,net中保存的應該是整個網絡共有參數,而layer中
保存的應該是每一層的參數
line 598 調用函數network_predict(net,X),后一行就開始輸出結果了,因些這一行比較關鍵,下面查看network_predict()函數定義。見下方network.c line 497-line 787
line 600 根據image.c中draw_detections()函數猜測nboxes應該指的時bounding boxes的數量?但和顯示的不一樣應該是有一些沒顯示出來
line 602 輸出的是識別出的目標類別的編號
下一行的輸出目標名稱和概率在代碼中沒找到在哪里。見image.c
line 604 do_nms_sort(),按概率大小排序?
line 605 顯示圖片部分重點查看,draw_detections()這個函數是關鍵,可以修改names使其把概率包含進去。見image.c
line 613 OpenCV是只是用來顯示圖片,重點在上一部分
~/darknet/src/network.c
line 53 network *load_network(char *cfg, char *weights, int clear)
調用parse_network_cfg函數為結構體net賦值,net包含了網絡的各種參數。見后文 parse.c
line 59 net->seen是哪個參數還沒太看明白,詳見network的定義 ~darknet/include/darknet.h line 495
line 177 network *make_network(int n) calloc(n)是一個C函數
在內存的動態存儲區中分配n個長度為size的連續空間,函數返回一個指向分配起始地址的指針;如果分配不成功,返回NULL。
line 497 關鍵處調用了一個forward_network(net)函數,查看此函數。定義位於line 188
line 188 若使用gpu查看forward_network_gpu(net),line 762
line 762~769 是關於cuda的操作,具體意義暫未深究,下面一個for循環沒太明白,fill_gpu()定義為啥沒找到。。
line 786 調用函數pull_network_output(netp),line 1123
line 1123 調用函數get_network_output_layer(network *net),line 699,返回值是第net->layers[i].type!=COST的那一層,這個返回值也上一個函數的輸入值
line 787 調用函數calc_network_cost(netp),計算損失函數。
~/darknet/src/parse.c
line 730 parse_network_cfg(char *filename)
line 739 section這一塊兒沒太明白,section應該是表示cfg文件中的每一小節,那為什么這個不是在循環里的,在line 836行
line 757 這個循環是輸出了運行網絡時輸出的每一層網絡的參數,細節看得有些模棱兩可,里面那一串if語句中的各種parse函數是根據layer的不同類型分別調用不同的函數進行處
理,這里的各種parse函數的細節還沒看
line 836 將處理完的layer,賦值給net->layers[count]
~/darknet/src/image.c
line 239 draw_detections()函數
line 255 打印類別及概率
line 295 定義了一個label,查看get_label()函數,line 132
line 132 image get_label(image **characters, char *string, int size),這里傳入的size為im.h*0.03,可是size不是必須是整型嗎?傳入的characters就是前面的alphabet,查看函數
load_alphabet(),傳入的string是什么呢,回頭看調用此函數的地方,傳入的是laberstr,是在函數draw_detections中定義的,結合后面的幾點確定,最后修改line 243里那個循
環,把概率加進去就可以了。添加的內容,將dets[i].prob[j]由浮點轉化為字符串,然后連接到labelstr后面,這引出一個問題,后面在draw時laberstr是如何分段的,如何修改才能
不對此有影響,先試一下吧。。試了一下發現成功了。
效果如圖
line 223 image **load_alphabet(),這個里面的buff由sprintf函數以sprintf(buff, "data/labels/%d_%d.png", i, j)的格式寫入buff中,查看data/labels中的文件,全是各種size的小的圖片,
找到可以用來表示概率的圖片,與ASCII碼是對應的,37為百分號,46為小數點,48~57為數字0~9,看完此函數,繼續看get_label(),line 138,
line 296 draw_label(),查看其定義
line 149 通過像素的操作把label畫出來,關鍵還是在前面的get_label()