OpenCV / оттенки серого / цветная адресация

Я написал алгоритм сопоставления блоков в C++, используя OpenCV для моей диссертации. Он работает над изображениями в градациях серого и обращается к IPLImage по своему абсолютному пикселадрессу.

Я должен разделить IPLImage на блоки одинакового размера (8x8 пикселей). Чтобы получить доступ к значениям пикселей в блоках, я вычисляю адрес пикселя и получаю доступ к значению пикселя следующим образом:

 for (int yBlock = 0; yBlock < maxYBlocks; yBlock++){
    for (int xBlock = 0; yxlock < maxXBlocks; xBlock++){
       for (int yPixel = 0; yPixel < 8; yPixel++){
          for (int xPixel = 0; xPixel < 8; xPixel++){

                pixelAdress = yBlock*imageWidth*8 + xBlock*8 + yPixel*imageWidth + xPixel;

                unsigned char* imagePointer = (unsigned char*)(img->imageData);
                pixelValue = imagePointer[pixelAdress];
    }
   }
  }
 }

Я на самом деле не перебиваю строки и столбцы, и это прекрасно работает!

Теперь у меня есть цветной IPLImage (без оттенков серого) и я не знаю, как получить доступ к значениям пикселей r, g, b.

Я нашел это на этом форуме

for( row = 0; row < img->height; row++ ){
    for ( col = 0; col < img->width; col++ ){
      b = (int)img->imageData[img->widthStep * row + col * 3];
      g = (int)img->imageData[img->widthStep * row + col * 3 + 1];
      r = (int)img->imageData[img->widthStep * row + col * 3 + 2];
}
}

но я не уверен, как использовать его на моем вычисленном pixelAdress. Правильно ли просто умножить это на 3 (потому что я не перебираю строки и добавляю 0, 1 или 2? Например:

pixelValueR = imagePointer[pixelAdress*3 + 2]; 
pixelValueG = imagePointer[pixelAdress*3 + 1]; 
pixelValueB = imagePointer[pixelAdress*3 + 0]; 

или я должен использовать widthStep, где я использовал imageWidth прежде, как это:

pixelAdressR = pixelAdress = yBlock*img->widthStep*8 + xBlock*8*3 + yPixel*img->widthStep + xPixel*3 + 2;
pixelAdressG = pixelAdress = yBlock*img->widthStep*8 + xBlock*8*3 + yPixel*img->widthStep + xPixel*3 + 1;
pixelAdressB = pixelAdress = yBlock*img->widthStep*8 + xBlock*8*3 + yPixel*img->widthStep + xPixel*3;

и так доступ

pixelValueR = imagePointer[pixelAdressR];
pixelValueG = imagePointer[pixelAdressG];
pixelValueB = imagePointer[pixelAdressB];

3 ответа

Решение

Я не уверен в вашем алгоритме и не могу проверить его в данный момент, но для IplImages память выровнена так:

1. row
baseadress + 0 = b of [0]
baseadress + 1 = g of [0]
baseadress + 2 = r of [0]
baseadress + 3 = b of [1]
etc

2. row
baseadress + widthStep + 0 = b
baseadress + widthStep + 1 = g
baseadress + widthStep + 2 = r

так что если у вас есть n*m блоки размера 8x8 данные без знака char bgr, и вы хотите перебрать переменные [x,y] в блоке [bx,by] Вы можете сделать это так:

baseadress + (by*8+ y_in_block)*widthStep + (bx*8+x)*3 +0 = b
baseadress + (by*8+ y_in_block)*widthStep + (bx*8+x)*3 +1 = g
baseadress + (by*8+ y_in_block)*widthStep + (bx*8+x)*3 +2 = r

с ряда by*8+y is adressbaseadress + (by*8+ y_in_block)*widthStep`

и колонка bx*8+x смещение адреса (bx*8+x)*3

В случае многоканального Mat (BGR в этом примере) вы можете получить доступ к одному пикселю, используя, как описано здесь

Vec3b intensity = img.at<Vec3b>(y, x);
uchar blue = intensity.val[0];
uchar green = intensity.val[1];
uchar red = intensity.val[2];
  1. За Mat (например Mat img)

    • Оттенки серого (8UC1):

      uchar intensity = img.at<uchar>(y, x);
      
    • Цветное изображение (порядок цветов BGR, формат по умолчанию, возвращаемый imread):

      Vec3b intensity = img.at<Vec3b>(y, x);
      uchar blue = intensity.val[0];
      uchar green = intensity.val[1];
      uchar red = intensity.val[2];
      
  2. За IplImage (например IplImage* img)

    • Оттенки серого:

      uchar intensity = CV_IMAGE_ELEM(img, uchar, h, w);
      
    • Цветное изображение:

      uchar blue = CV_IMAGE_ELEM(img, uchar, y, x*3);
      uchar green = CV_IMAGE_ELEM(img, uchar, y, x*3+1);
      uchar red = CV_IMAGE_ELEM(img, uchar, y, x*3+2);
      
Другие вопросы по тегам