2015-03-11 2 views
3

с учетом серого cv :: Mat (CV_8UC1) Я хочу вернуть еще один cv :: Mat, содержащий квадратный корень из элементов (CV_32FC1), и я хочу сделать это с помощью встроенных SSE2 , У меня возникают некоторые проблемы с преобразованием из 8-битных значений в 32 значения float для выполнения квадратного корня. Я бы очень признателен за любую помощь. Это мой код сейчас (это не дает правильные значения):Квадратный корень серого изображения OpenCV с использованием SSE

uchar *source = (uchar *)cv::alignPtr(image.data, 16); 
float *sqDataPtr = cv::alignPtr((float *)Squared.data, 16); 
for (x = 0; x < (pixels - 16); x += 16) { 
    __m128i a0 = _mm_load_si128((__m128i *)(source + x)); 

    __m128i first8 = _mm_unpacklo_epi8(a0, _mm_set1_epi8(0)); 
    __m128i last8 = _mm_unpackhi_epi8(a0, _mm_set1_epi8(0)); 

    __m128i first4i = _mm_unpacklo_epi16(first8, _mm_set1_epi16(0)); 
    __m128i second4i = _mm_unpackhi_epi16(first8, _mm_set1_epi16(0)); 
    __m128 first4 = _mm_cvtepi32_ps(first4i); 
    __m128 second4 = _mm_cvtepi32_ps(second4i); 

    __m128i third4i = _mm_unpacklo_epi16(last8, _mm_set1_epi16(0)); 
    __m128i fourth4i = _mm_unpackhi_epi16(last8, _mm_set1_epi16(0)); 
    __m128 third4 = _mm_cvtepi32_ps(third4i); 
    __m128 fourth4 = _mm_cvtepi32_ps(fourth4i); 

    // Store 
    _mm_store_ps(sqDataPtr + x, _mm_sqrt_ps(first4)); 
    _mm_store_ps(sqDataPtr + x + 4, _mm_sqrt_ps(second4)); 
    _mm_store_ps(sqDataPtr + x + 8, _mm_sqrt_ps(third4)); 
    _mm_store_ps(sqDataPtr + x + 12, _mm_sqrt_ps(fourth4)); 
} 

ответ

1

Код SSE выглядит нормально, за исключением того, что вы не обрабатываете последние 16 пикселей:

for (x = 0; x < (pixels - 16); x += 16) 

должен быть:

for (x = 0; x <= (pixels - 16); x += 16) 

Обратите внимание, что если ваша ширина изображения не кратна 16, то вам нужно будет заботиться о всех оставшихся пикселей после последнего полного вектора.

Также обратите внимание, что вы принимаете значения sqrt в диапазоне 0..255. Возможно, вы хотите нормализованное значение в диапазоне 0..1.0, и в этом случае вы захотите масштабировать значения соответствующим образом.

+0

Большое спасибо за ваш ответ, но я не копировал оставшиеся вычисления последних пикселей здесь для простоты. Этот код, я не знаю, почему не приводит к правильным значениям. Да, мне нужен квадратный корень из значений между 0 ... 255. Я не знаю, если это полностью эффективно. – user3696558

+0

OK - петля все еще нуждается в исправлении, хотя, ради производительности, поскольку вам не хватает возможности обработать один последний полный вектор. Что касается функциональности, я подозреваю, что проблема может быть где-то иначе, чем в коде SSE - возможно, попробуйте заменить код SSE на простой скалярный цикл, чтобы увидеть, работает ли это, или проверить цикл SSE в отдельной тестовой проводке, чтобы проверить это? –

+0

Еще одна вещь - я помещаю ваш SSE-код в тестовую жгуту, и она проходит (как только верхняя граница цикла цикла исправлена). –

1

У меня нет опыта работы с SSE2, но я думаю, что если производительность является проблемой, вы должны использовать справочную таблицу. Создание справочной таблицы выполняется быстро, так как у вас есть только 256 возможных значений. Копирование 4 байтов из таблицы поиска в матрицу назначения должно быть очень эффективной.

+1

С помощью таблицы поиска вы можете обрабатывать только одну точку на итерацию, и для обработки 1 входного значения требуется 2 загрузки и 1 хранилище. Версия SSE обрабатывает 16 точек на каждую итерацию цикла, только 1 загрузка и 4 магазина для 16 входных значений. –

+0

Большое спасибо за ответ, но, да, это медленнее. – user3696558

+0

, даже если вы используете функцию OpenCV LUT? – Micka

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