Более быстрое (оптимизированное) решение для уничтожения изображений (C )

#c #algorithm #image-processing #optimization #image-optimization

#c #алгоритм #обработка изображений #оптимизация #оптимизация изображений

Вопрос:

Я ищу более быстрый способ работы со следующим кодом C. У меня есть изображение размером 640×480, и я хочу уменьшить его в 2 раза, удалив все остальные строки и столбцы в изображении. Я приложил код ниже. Есть ли лучший способ оптимизировать код.

 #define INPUT_NUM_ROW 480
#define INPUT_NUM_COL 640
#define OUTPUT_NUM_ROW 240
#define OUTPUT_NUM_COL 320

unsigned char inputBuf[INPUT_NUM_ROW* INPUT_NUM_COL];
unsigned char outputBuf[OUTPUT_NUM_ROW* OUTPUT_NUM_COL];

void imageDecimate(unsigned char *outputImage , unsigned char *inputImage)
{
/* Fill in your code here */
for (int p = 0; p< OUTPUT_NUM_ROW; p  ) {
    for (int q = 0; q < OUTPUT_NUM_COL; q  ) {
        outputImage[p*OUTPUT_NUM_COL   q] = inputImage[(p*INPUT_NUM_COL q)*2];
        // cout << "The pixel at " << p*OUTPUT_NUM_COL q << " is " << outputImage[p*OUTPUT_NUM_COL q] << endl;
    }
  }
}
  

Комментарии:

1. большинство изображений имеют много полей заголовка, которые необходимо будет обновить. Опубликованный код обрабатывает только фактические поля данных / пикселей. Длина большинства полей пикселей (в зависимости от информации заголовка) составляет 3 или 4 байта. при сжатии изображения не удаляйте произвольно 1/2 строк и 1/2 столбцов. Гораздо лучшим подходом является усреднение пар строк, затем (в отдельном цикле) усреднение пар столбцов, помня, что каждый столбец (пиксель) состоит из 3 или 4 байт. Также помните, что (в большинстве изображений) количество байтов в строке будет кратно 4,

2. Вы правы в отношении включения полей заголовка в изображения, а также усреднения пикселей, что, в свою очередь, делает сглаживание менее заметным. Однако я искал более эффективную оптимизацию кода.

Ответ №1:

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

 int outputIndex;
int inputIndex;
for (int p = 0; p< OUTPUT_NUM_ROW; p  ) {
    inputIndex = p * INPUT_NUM_COL * 2;
    outputIndex = p * OUTPUT_NUM_COL;
    for (int q = 0; q < OUTPUT_NUM_COL; q  ) {
        outputImage[outputIndex] = inputImage[inputIndex];
        inputIndex  = 2;
        outputIndex  ;
        // cout << "The pixel at " << p*OUTPUT_NUM_COL q << " is " << outputImage[p*OUTPUT_NUM_COL q] << endl;
    }
  }
}
  

Вы могли бы выполнить инкрементирование встроенным с копированием присваивания тоже, и вы также могли бы назначить только inputIndex и outputIndex в первый раз, но это не дало бы вам такого значительного повышения производительности, как перемещение вычисления из внутреннего цикла. Я предполагаю, что функции массового копирования не обладают такой увеличивающейся гибкостью, но если они это делают и используют аппаратное ускорение, доступное на всех ваших целевых платформах, то это было бы лучшим выбором.

Я также предполагаю, что подобный доступ к массиву компилируется до наиболее оптимизированной арифметики указателей, которую вы могли бы использовать.

Комментарии:

1. Следовало подумать об этом! Спасибо. 1

2. это не учитывает фактический размер каждого пикселя и не уменьшает изображение по вертикали и не обрабатывает требование «кратно 4 байтам» для каждой строки.

3. @user3629249 — Разница в 2 между вычислениями inputIndex и outputIndex завершает прореживание по вертикали. Если вы имеете в виду, что общее количество байтов в строке должно быть кратно 4 байтам, то константы для 480 и 240 гарантируют, что так оно и будет. Если вместо этого вы говорите о разрядности на пиксель, то не было указано, что это изображение с 32 битами на пиксель и для него потребуется 4 байта на пиксель. Я мог только предположить из вопроса, что это было изображение с 8 битами на пиксель.

4. Допущения при написании программного обеспечения являются (или будут) проклятием для жизни любого программиста. Ваш ответ не учитывает тот факт, что длина каждого пикселя (в зависимости от информации в заголовке файла) может составлять 1,3 или 4 байта. Считывание количества байтов int размера ненадежно. Что происходит на 64-битной архитектуре? Что происходит на 16-битной архитектуре? Что происходит, когда каждый пиксель равен 3 байтам? Что происходит, когда каждый пиксель равен 1 байту?