Ответ 1
Это потому, что значение L находится в диапазоне [0..255] в OpenCV. Вы можете просто масштабировать это значение до необходимого интервала ( [0..100] в вашем случае).
Я пытаюсь преобразовать заданный 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, я не могу понять, что такое моя ошибка.
Update: Я опубликую здесь свои общие результаты: Учитывая изображение (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];
}
}
Это потому, что значение L находится в диапазоне [0..255] в OpenCV. Вы можете просто масштабировать это значение до необходимого интервала ( [0..100] в вашем случае).
Если кто-то интересуется диапазоном других переменных a
и b
, я сделал небольшую программу для проверки их диапазона.
Если вы преобразуете все цвета, представленные в RGB, в CieLab, используемые в OpenCV, диапазоны:
0 <=L<= 255
42 <=a<= 226
20 <=b<= 223
И если вы используете значения RGB в режиме float вместо 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)
Я не уверен относительно диапазона Жоао Абрантеса на A и B.
документация opencv четко обозначила диапазон CIE L*a*b*
.
Таким образом, приводя к диапазону
0 <= L <= 255
0 <= a <= 255
0 <= b <= 255
В случае, если кто-то сталкивается с той же проблемой:
Обратите внимание, что в OpenCV (2.4.13) вы можете не преобразовывать изображения BGR CV_32FC3 в цветовое пространство 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);
работает как шарм. Я не объяснил причину такого поведения; однако мне кажется, что это, по сути, ограничивает качество изображения.