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 adress
baseadress + (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];
За
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];
За
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);