Преобразование 8-битного изображения OpenCV BGR в 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