darknet源碼理解(二)---圖片的讀取
簡介:
這篇博客介紹darknet框架下,圖片是如何讀取的。
上一篇博客介紹的是darknet的主體框架。
正文:
首先,作者在darknet.h中定義了一個結構體image用於存放圖片數據及圖片相關信息。結構體image中包含以下成
員變量:
int w , int h , int c, float*data
顧名思義,它們分別存儲着圖片的寬、高、通道數以及數據。
回顧上一篇博客,可以知道在detector.c中,test_detector()函數中包含了我們熟悉的一個端到端的過程。即,
初始化模型、讀取模型權重、讀取圖片、圖片resize、將圖片餵給模型進行前向傳播、根據模型輸出得到目標位置
及類別、將目標位置及類別標註在圖片上。
其中的load_image_color(input,0,0)函數根據圖片路徑input,讀取圖片信息。該函數定義於src/image.c中,其通
過調用load_image()函數(定義於image.c中)讀取圖片。
下面給出load_image()函數的定義
image load_image(char*filename, int w, int h, int c)
{
#ifdef OPENCV
image out =load_image_cv(filename, c);
#else
image out =load_image_stb(filename, c);
#endif
if((h && w) &&(h != out.h || w != out.w)){
image resized =resize_image(out, w, h);
free_image(out);
out = resized;
}
return out;
}
從中我們可以看出,如果我們編譯darknet時使用了opencv,那麼這裏讀取圖片時會調用
load_image_cv(filename,c);如果未使用opencv,則讀取圖片時調用load_image_stb(filename,c)。
1、使用opencv
使用opencv時,load_image_cv(filename,c)調用ipl_to_image()。在ipl_to_image()中,函數會先初始化一個
image結構體,再調用ipl_into_image()將輸入圖片的信息賦值給結構體成員變量。
ipl_into_image()的作用是改變float*data中圖片像素數據的存儲順序,具體解釋如下:
在opencv中,圖片是按下圖所示的方式進行存儲的,即按順序先存儲圖片第1行第1列元素的3個通道的像素值,再
存儲第1行第2列元素的3個通道的像素值,以此類推。
而ipl_into_image()將上圖的存儲順序轉換成下圖所示的存儲順序,即先存儲圖片的第一個通道,再存儲第2個通
道,最後存儲第三個通道。
2、不使用opencv
不使用opencv時,darknet使用一個簡單的圖像庫stb_image.h進行圖像的讀取、存儲等簡單的操作,因此不能顯
示圖片。此時,使用load_image_stb(filename,c)讀取圖片信息,其功能依然是改變圖片像素數據的存儲順序。
下一篇博客,將介紹darknet中layer的初始化和layer的前向傳播。