2015-04-15 5 views
2

Что касается моего предыдущего вопроса для проверки границы - Border check in image processing? Я пишу код с неоновой для пограничных check.I Возникают ниже вопросов при написании кода:Проверка границы с неонами

Вход:

-------------------------------- 
|221 220 228 223 230 233 234 235 .. 
|71 73 70 78 92 130 141 143 .. 
| 

Требование:

-1 * v_m1_m1 + 0 * v_m1_0 + 1 * v_m1_p1 
    -1 * v_0_m1 + 0 * v_0_0 + 1 * v_0_p1 --> v_out 
    -1 * v_p1_m1 + 0 * v_p1_0 + 1 * v_p1_p1 

Псевдо Код:

for i = 0 to nrows - 1 
     // init row pointers 
     p_row_m1 = src + src_width * MAX(i-1, 0);   // pointing to minus1 row 
     p_row_0 = src + src_width * i;      // pointing to current row 
     p_row_p1 = src + src_width * MIN(i+1, src_width-1); // pointing to plus1 row 

     v_m1_m1 = vdupq_n_u32(p_row_m1[0]); // fill left vector from src[i-1][0] 
     v_0_m1 = vdupq_n_u32(p_row_0[0]); // fill left vector from src[i][0] 
     v_p1_m1 = vdupq_n_u32(p_row_p1[0]); // fill left vector from src[i+1][0] 

     v_m1_0 = vld1q_u32(&p_row_m1[0]); // load center vector from src[i-1][0..7] 
     v_0_0 = vld1q_u32(&p_row_0[0]); // load center vector from src[i][0..7] 
     v_p1_0 = vld1q_u32(&p_row_p1[0]); // load center vector from src[i+1][0..7] 

     for j = 0 to (ncols - 4) step 4   // assuming 4 elements per SIMD vector 

      v_m1_p1 = vld1q_u32(&p_row_m1[j+4]); // load right vector from src[i-1][0..7] 
      v_0_p1 = vld1q_u32(&p_row_0[j+4]); // load right vector from src[i][0..7] 
      v_p1_p1 = vld1q_u32(&p_row_p1[j+4]); // load right vector from src[i+1][0..7] 
    // 
    // you now have a 3x3 arrangement of vectors on which 
    // you can perform a neighbourhood operation and generate 
    // 16 output pixels for the current iteration: 
    // 
    // v_m1_m1 v_m1_0 v_m1_p1 
    // v_0_m1 v_0_0 v_0_p1 
    // v_p1_m1 v_p1_0 v_p1_p1 
    // 
    //    | 
    //    V 
    // 
    //    v_out 
    vst1q_s32(v_out, &image_out[i][j])  // store output vector at image_out[i][j..j+15] 
    // shuffle vectors so that we can use them on next iteration 
    v_m1_m1 = v_m1_0 
    v_m1_0 = v_m1_p1 

    v_0_m1 = v_0_0 
    v_0_0 = v_0_p1 

    v_p1_m1 = v_p1_0 
    v_p1_0 = v_p1_p1 

     end_for 
     // for final iteration we need to handle right edge pixels... 
     v_m1_p1 = vdupq_n_u32(p_row_m1[ncols-1])  // fill right vector from image[i-1][ncols-1] 
     v_0_p1 = vdupq_n_u32(p_row_0[ncols-1])  // fill right vector from image[i][ncols-1] 
     v_p1_p1 = vdupq_n_u32(p_row_p1[ncols-1])  // fill right vector from image[i+1][ncols-1] 
     // calculate v_out as above 
     vst1q_s32(v_out, &image_out[i][j])  // store output vector at image_out[i][ncols_16..ncols-1] 
    end_for 

В коде C, если я хочу рассчитать для 221 (@ i, j = 0,0), с границей l ooks как:

221 221 220 
     ----------- 
221 |221 220 
    | 
71 |71 73 

В NEON коде, если я хочу, чтобы вычислить для 221 (@ I, J = 0,0), с бордюра выглядит следующим образом:

221 221 221 221  221 220 228 223 230 233 234 235 
        ------------------------------- 
221 221 221 221 |221 220 228 223 230 233 234 235 
        | 
71 71 71 71  |71 73 70 78 92 130 141 143 

Для расчета 221: В неон код соседи показали ниже, и в соответствии с требования, что происходит не так:

v_m1_m1.0 v_m1_0.0 v_m1_p1.0 
v_0_m1.0 v_0_0.0 v_0_p1.0 
v_p1_m1.0 v_p1_0.0 v_p1_p1.0 

221 221 230 
    --- 
221 |221| 230 
    --- 
71 71 92 

Как я могу заботиться о границе с общей логикой коды ??

+0

Неясно, в чем ваша проблема: девять векторов v_xxx содержат все данные, необходимые для операции 3x3 соседей - может быть, вы запутались из-за избыточных элементов в смежных векторах? Если это так, вы можете просто игнорировать их, вы будете использовать только один элемент при смещении пар векторов влево/вправо. –

+0

@ PaulR, я ожидаю, что сосед по соседству для 221 должен быть 220, а не 230. С тем же неоновым кодом для 228, соседи - 221 (слева), 234 (справа). И согласно C-коду для 228, соседи должны быть 220 (слева), 223 (справа) .am объясняю достаточно, чтобы очистить мой вопрос // v_m1_m1 v_m1_0 v_m1_p1 // v_0_m1 v_0_0 v_0_p1 // v_p1_m1 v_p1_0 v_p1_p1 – user3476225

+0

@ PaulR, он будет работать нормально для первой итерации: v_0_m1: 221 221 221 221 ||| v_0_0: 221 220 228 223 ||| v_0_p1: 220 228 223 230 для второй итерации я должен увеличивать ширину (или j) на 1 вместо 4, что разрушит значение векторизации. – user3476225

ответ

2

Похоже, вам нужно понять, как реализовать SIMD-ядро с соседними операциями. Это важная часть:

// 
// you now have a 3x3 arrangement of vectors on which 
// you can perform a neighbourhood operation and generate 
// 4 output pixels for the current iteration: 
// 
// v_m1_m1 v_m1_0 v_m1_p1 
// v_0_m1 v_0_0 v_0_p1 
// v_p1_m1 v_p1_0 v_p1_p1 
// 
//    | 
//    V 
// 
//    v_out 

Предположим, что вы хотите реализовать сумму по крестообразной ядра, то есть:

y[i][j] = x[i][j] + x[i-1][j] + x[i+1][j] + x[i][j-1] + x[i][j+1]; 

Псевдокод для этого в SIMD будет:

// sum vertically: x[i][j] + x[i-1][j] + x[i+1][j] 
v_out = v_m1_0; 
v_out = v_out + v_0_0;  // vaddq 
v_out = v_out + v_p1_0;  // vaddq 

// add the x[i][j-1] components 
v_temp = v_0_m1:v_0_0 >> 1; // vextq - use this to get a right-shifted vector 
v_out = v_out + v_temp;  // vaddq 

// add the x[i][j+1] components 
v_temp = v_0_0:v_0_p1 << 1; // vextq - use this to get a left-shifted vector 
v_out = v_out + v_temp;  // vaddq 

На данный момент v_out теперь содержит четыре суммы для выходных элементов y[i][j] .. y[i][j+3]. Другими словами, мы оценили четыре точки вывода в одном ядре. Теперь мы перетасовываем все наши векторы, оставленные одним, и загружаем 3 новых вектора для правого столбца и делаем это снова с j += 4. Если вы посмотрите на исходный псевдокод из предыдущего вопроса, вы увидите, что все пограничные случаи позаботятся, заполнив вектор значением края.

 Смежные вопросы

  • Нет связанных вопросов^_^