Darknet函數分析

Darknet中函數分析

隨機打亂數據

代碼在data.c源文件中

void randomize_data(data d)
{
    int i;
    for(i = d.X.rows-1; i > 0; --i){ // 從最後一個元素位置開始,當前位置爲i
        int index = rand()%i;// 從i(不包括)之前的所有位置隨機選擇一個位置index
        float *swap = d.X.vals[index]; // 交換index和i處的指針
        d.X.vals[index] = d.X.vals[i];
        d.X.vals[i] = swap;
    swap <span class="token operator">=</span> d<span class="token punctuation">.</span>y<span class="token punctuation">.</span>vals<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">;</span>
    d<span class="token punctuation">.</span>y<span class="token punctuation">.</span>vals<span class="token punctuation">[</span>index<span class="token punctuation">]</span> <span class="token operator">=</span> d<span class="token punctuation">.</span>y<span class="token punctuation">.</span>vals<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
    d<span class="token punctuation">.</span>y<span class="token punctuation">.</span>vals<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> swap<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

可以看到整個打亂過程只有指針指向在不斷髮生變化,數據在內存中的位置不變。


im2col實現

代碼在im2col.c源文件中

float im2col_get_pixel(float *im, int height, int width, int channels,
                        int row, int col, int channel, int pad)
{
    row -= pad;
    col -= pad;
<span class="token keyword">if</span> <span class="token punctuation">(</span>row <span class="token operator">&lt;</span> <span class="token number">0</span> <span class="token operator">||</span> col <span class="token operator">&lt;</span> <span class="token number">0</span> <span class="token operator">||</span>
    row <span class="token operator">&gt;=</span> height <span class="token operator">||</span> col <span class="token operator">&gt;=</span> width<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> im<span class="token punctuation">[</span>col <span class="token operator">+</span> width<span class="token operator">*</span><span class="token punctuation">(</span>row <span class="token operator">+</span> height<span class="token operator">*</span>channel<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

}

//From Berkeley Vision’s Caffe!
//https://github.com/BVLC/caffe/blob/master/LICENSE
void im2col_cpu(float data_im, // 輸入的圖像數據,內存中按行排列成一維
int channels, // 通道數
int height, int width, // 圖像的高和寬
int ksize, // 卷積核的高和寬,這裏默認卷積核高和寬大小一樣
int stride, // 卷積時的步長,這裏默認高和寬兩個方向上步長一樣
int pad, // 圖像的填充,這裏默認高和寬上填充一樣
float data_col // 最終輸出的數據
) {
int c,h,w;
int height_col = (height + 2pad - ksize) / stride + 1; // 卷積後的圖像尺寸,可以想象,其中每個點對應圖像的一個卷積區域,卷積區域大小是channels * ksize * ksize,即下面的channels_col。
int width_col = (width + 2pad - ksize) / stride + 1;

<span class="token keyword">int</span> channels_col <span class="token operator">=</span> channels <span class="token operator">*</span> ksize <span class="token operator">*</span> ksize<span class="token punctuation">;</span> <span class="token comment">// 圖像上每個卷積區域展成一列後的大小,比如                                                          // ksize=3,圖像通道數爲3,那麼channels_col爲27</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>c <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> c <span class="token operator">&lt;</span> channels_col<span class="token punctuation">;</span> <span class="token operator">++</span>c<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">int</span> w_offset <span class="token operator">=</span> c <span class="token operator">%</span> ksize<span class="token punctuation">;</span> <span class="token comment">// 0, 1, 2, 0, 1, 2, 0, 1, 2, ... 寬的相對偏移</span>
    <span class="token keyword">int</span> h_offset <span class="token operator">=</span> <span class="token punctuation">(</span>c <span class="token operator">/</span> ksize<span class="token punctuation">)</span> <span class="token operator">%</span> ksize<span class="token punctuation">;</span> <span class="token comment">// 0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, ...高的相對偏移</span>
    <span class="token keyword">int</span> c_im <span class="token operator">=</span> c <span class="token operator">/</span> ksize <span class="token operator">/</span> ksize<span class="token punctuation">;</span> <span class="token comment">// 9個0, 9個1, 9個2 通道序號,(c_im, h_offset, w_offset)是卷積區域的相對座標</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span>h <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> h <span class="token operator">&lt;</span> height_col<span class="token punctuation">;</span> <span class="token operator">++</span>h<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 有height_col * width_col個卷積區域,遍歷每一個卷積區域,對於每個區域,計算它的c位置處的圖像像素值</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span>w <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> w <span class="token operator">&lt;</span> width_col<span class="token punctuation">;</span> <span class="token operator">++</span>w<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">int</span> im_row <span class="token operator">=</span> h_offset <span class="token operator">+</span> h <span class="token operator">*</span> stride<span class="token punctuation">;</span> <span class="token comment">// 相對於圖像的行座標</span>
            <span class="token keyword">int</span> im_col <span class="token operator">=</span> w_offset <span class="token operator">+</span> w <span class="token operator">*</span> stride<span class="token punctuation">;</span> <span class="token comment">// 相對於圖像的列座標</span>
            <span class="token keyword">int</span> col_index <span class="token operator">=</span> <span class="token punctuation">(</span>c <span class="token operator">*</span> height_col <span class="token operator">+</span> h<span class="token punctuation">)</span> <span class="token operator">*</span> width_col <span class="token operator">+</span> w<span class="token punctuation">;</span> <span class="token comment">// </span>
            data_col<span class="token punctuation">[</span>col_index<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">im2col_get_pixel</span><span class="token punctuation">(</span>data_im<span class="token punctuation">,</span> height<span class="token punctuation">,</span> width<span class="token punctuation">,</span> channels<span class="token punctuation">,</span>
                    im_row<span class="token punctuation">,</span> im_col<span class="token punctuation">,</span> c_im<span class="token punctuation">,</span> pad<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

這是caffe中卷積操作之前的關鍵步驟,對三維圖像進行變形,將傳統卷積操作變成矩陣形式的卷積操作。

簡便起見,設channels = 1,即圖像是個單通道圖。data_im爲
051015201611162127121722381318234914192401234567891011121314151617181920212223240amp;1amp;2amp;3amp;45amp;6amp;7amp;8amp;910amp;11amp;12amp;13amp;1415amp;16amp;17amp;18amp;1920amp;21amp;22amp;23amp;2405101520161116212712172238131823491419240123456789101112131415161718192021222324 \begin{matrix}0 &amp; 1 &amp; 2 &amp; 3 &amp; 4 \\5 &amp; 6 &amp; 7 &amp; 8 &amp; 9 \\10 &amp; 11 &amp; 12 &amp; 13 &amp; 14 \\15 &amp; 16 &amp; 17 &amp; 18 &amp; 19 \\20 &amp; 21 &amp; 22 &amp; 23 &amp; 24 \\\end{matrix}3×3×3=27列。此時,再將kernel拉伸成一列,卷積過程變成了矩陣乘法:
0125671011121236781112132347891213145671011121516176781112131617187891213141718191011121516172021221112131617182122231213141718⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢0125671011121236781112132347891213145671011121516176781112131617187891213141718191011121516172021221112131617182122231213141718

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章