Быстрый доступ к значениям пикселей JPEG изображений - PullRequest
1 голос
/ 24 октября 2010

CompVision еще раз, я работаю с изображениями JPEG в моем приложении.Просто потому, что я немного знаком с MFC и ATL, я использовал CImage для доступа к значениям пикселей.

Для своих нужд я рассчитываю матрицу яркости изображения во время инициализации.Функция выглядит следующим образом (Image - это имя моего собственного класса, неважно, bright is float [] []):

 void Image::fillBrightnessMatrix(){
    COLORREF val;
    for(int i=0;i<width;i++){
        for(int j=0; j<height;j++){
          val=src.GetPixel(i,j);
              bright[i][j]=rgb_to_L(val);
        }
    }
}

Где src - это экземпляр класса CImage, rgb_to_L - некотороефункция, которая вычисляет яркость цвета.

Изучив производительность моего приложения, я обнаружил, что GetPixel является самой дорогой операцией, и она значительно (действительно, в ~ 700 раз медленнее, чем любая другая операция) замедляетсявся инициализация изображения. Вопрос в том, какую библиотеку вы можете предложить для быстрого доступа к однопиксельным значениям ?Мне не нужны никакие другие операции, кроме загрузки изображения в формате JPEG и доступа к отдельным пикселям.Производительность важна, потому что мое приложение работает с набором из ~ 3000 изображений, и я не могу ждать часами, чтобы получить результаты.

Ответы [ 3 ]

2 голосов
/ 24 октября 2010

Используйте CBitmap :: GetBits (), чтобы получить необработанный указатель на данные пикселей. Теперь вы можете напрямую обрабатывать пиксели, не используя дорогой метод GetPixel (). Есть ряд вещей, с которыми нужно быть осторожным, когда вы делаете это:

  • Вы должны использовать CBitmap :: GetPitch (), чтобы вычислить смещение к началу строки. Высота тона не равна ширине.
  • Линии в растровом изображении хранятся в обратном порядке
  • Вы должны разобраться с форматом пикселей самостоятельно. Изображение 24bpp хранит 3 байта на пиксель. Индексированный формат, такой как 8bpp, требует поиска цвета в таблице цветов. 32bpp - это просто, 4 байта на пиксель, а высота тона всегда равна ширине.
1 голос
/ 24 октября 2010

Я всегда рекомендую OpenCV .

Это скромный фрагмент кода, с которого можно начать:

IplImage* pRGBImg = cvLoadImage("c:\\test.jpg", CV_LOAD_IMAGE_UNCHANGED); 
if (!pRGBImg)
{
  std::cout << "!!! cvLoadImage failed !!!" << std::endl;
  exit(1);
}

int width = pRGBImg->width; 
int height = pRGBImg->height;
int bpp = pRGBImg->nChannels; 
for (int i=0; i < width*height*bpp; i+=bpp) 
{
  if (!(i % (width*bpp))) // print empty line for better readability
      std::cout << std::endl;

  std::cout << std::dec << "R:" << (int) pRGBImg->imageData[i] <<  
                          " G:" << (int) pRGBImg->imageData[i+1] <<  
                          " B:" << (int) pRGBImg->imageData[i+2] << " "; 
}
0 голосов
/ 24 октября 2010

Вам, вероятно, следует извлечь jpeg в необработанные данные, а затем получить доступ к необработанным данным вместо GetPixel.

...