Конвертиране на OpenCV BGR 8-битово изображение в CIE L*a*b*

Опитвам се да преобразувам даден Mat, представляващ RGB изображение с 8-битова дълбочина в Lab, като използвам функцията, предоставена в документацията:

cvtColor(source, destination, <conversion code>);

Опитах следните кодове за преобразуване:

CV_RGB2Lab
CV_BGR2Lab
CV_LBGR2Lab

Всеки път съм получавал странни резултати със стойност на "L" над 100 за някои проби, буквално ‹107, 125, 130>.

Използвам и Photoshop, за да проверя резултатите - но като се има предвид, че 107 е извън приетия диапазон от 0 ≤ L ≤ 100, не мога да разбера каква е моята грешка.

Актуализация: Ще публикувам общите си резултати тук: Като се има предвид изображение (Mat), представено от 8-битов BGR, изображението може да бъде преобразувано чрез следното:

cvtColor(source, destination, CV_BGR2Lab);

Тогава стойностите на пикселите могат да бъдат достъпни по следния начин:

int step = destination.step;
int channels = destination.channels();
for (int i = 0; i < destination.rows(); i++) {
    for (int j = 0; j < destination.cols(); j++) {
        Point3_<uchar> pixelData;
        //L*: 0-255 (elsewhere is represented by 0 to 100)
        pixelData.x = destination.data[step*i + channels*j + 0];
        //a*: 0-255 (elsewhere is represented by -127 to 127)
        pixelData.y = destination.data[step*i + channels*j + 1];
        //b*: 0-255 (elsewhere is represented by -127 to 127)
        pixelData.z = destination.data[step*i + channels*j + 2];
    }
}

person JT Cho    schedule 08.07.2012    source източник
comment
Освен това не можете да направите преобразуване от RGB към Lab с надежден резултат, без да знаете цветовия профил. RGB не е независимо цветово пространство, Lab е.   -  person TimZaman    schedule 04.02.2015


Отговори (4)


Това е така, защото стойността на L е в диапазон [0..255] в OpenCV. Можете просто да мащабирате тази стойност до необходимия интервал ([0..100] във вашия случай).

person ArtemStorozhuk    schedule 08.07.2012

Ако някой се интересува от обхвата на другите променливи a и b направих малка програма за тестване на обхвата им. Ако конвертирате всички цветове, които са представени с RGB, в CieLab, използван в OpenCV, диапазоните са:

0  <=L<= 255
42 <=a<= 226
20 <=b<= 223

И ако използвате RGB стойности в плаващ режим вместо uint8, диапазоните ще бъдат:

0.0      <=L<= 100.0
-86.1813 <=a<= 98.2352
-107.862 <=b<= 94.4758

P.S. Ако искате да видите колко различима (по отношение на човешкото възприятие) е LAB стойност от друга LAB стойност, трябва да използвате плаваща запетая. Скалата, използвана за поддържане на лабораторните стойности в диапазоните uint8, обърква тяхното евклидово разстояние.

Това е кодът, който използвах (python):

L=[0]*256**3
a=[0]*256**3
b=[0]*256**3
i=0
for r in xrange(256):
    for g in xrange(256):
        for bb in xrange(256):
            im = np.array((bb,g,r),np.uint8).reshape(1,1,3)
            cv2.cvtColor(im,cv2.COLOR_BGR2LAB,im) #tranform it to LAB 
            L[i] = im[0,0,0]
            a[i] = im[0,0,1]
            b[i] = im[0,0,2]
            i+=1

print min(L), '<=L<=', max(L)
print min(a), '<=a<=', max(a)
print min(b), '<=b<=', max(b)
person João Abrantes    schedule 09.02.2015
comment
Защо казвате, че скалата за LAB стойности в тип uint8 се бърка с тяхното евклидово разстояние? - person simplename; 05.10.2017
comment
@simplename идеята на LAB е, че евклидовото разстояние на два цвята е свързано с това колко лесно човешкото око може да различи тези два цвята. Използвайки uint8, L амплитудата вече е 255 вместо 100, докато a и b все още имат подобни диапазони - два различни цвята имат различни евклидови разстояния, когато се използва uint8 или когато се използва float. - person João Abrantes; 05.10.2017
comment
Изглежда не мога да преобразувам в оригинално изображение -› float32 -› bgr2lab -› правя промени -› lab2bgr -› uint8 -› ново изображение без проблеми. имате ли код за конвертиране напред и назад? - person 2c2c; 21.10.2017

Не съм сигурен за гамата на Жоао Абрантес за A и B.

В документацията за opencv ясно се споменава CIE L*a*b*range.

Обща гама

  • 8 битови изображения

    Обхват от 8_битови изображения

Това води до набор от

0 <= L <= 255
0 <= a <= 255
0 <= b <= 255
person Shan    schedule 24.02.2016

В случай, че някой се сблъска със същия проблем:

Моля, обърнете внимание, че в OpenCV (2.4.13) можете не да конвертирате CV_32FC3 BGR изображения в цветовото пространство на Lab. Тоест:

//this->xImage is CV_8UC3
this->xImage.convertTo(FloatPrecisionImage, CV_32FC3);
Mat result;
cvtColor(FloatPrecisionImage, result, COLOR_BGR2Lab);
this->xImage = result;

няма да сработи докато

Mat result;
cvtColor(this->xImage, result, COLOR_BGR2Lab);
result.convertTo(this->xImage, CV_32FC3);

работи като чар. Не открих причината за това поведение; въпреки това ми изглежда неправилно, защото това на практика поставя ограничения върху качеството на изображението.

person zeroByte    schedule 27.09.2017