2013-02-11 1 views
6

색상 심도 조정을 통해 색상 감소를 수행하고 싶습니다. 이 예와 같이opencv 및 LUT의 색상 심도 감소

: enter image description here

제 CGA 이미지 해상도는 세번째 HAM이고, 두 번째는 EGA된다. 나는 cv :: LUT로하고 싶다. 왜냐하면 나는 그것을하는 것이 더 좋은 방법이라고 생각하기 때문이다. 이 코드와 그레이 스케일로 수행 할 수 있습니다

Mat img = imread("test1.jpg", 0); 
uchar* p; 
Mat lookUpTable(1, 256, CV_8U); 
p = lookUpTable.data; 
for(int i = 0; i < 256; ++i) 
    p[i] = 16 * (i/16) 
LUT(img, lookUpTable, reduced); 

원래 : enter image description here

색상 감소 : enter image description here

을하지만 난 색상으로 그것을하려고하면 내가 이상한 결과를 얻을 ..

enter image description here

:

imgColor = imread("test1.jpg"); 
Mat reducedColor; 
int n = 16; 
for (int i=0; i<256; i++) { 
    uchar value = floor(i/n) * n; 
    cout << (int)value << endl; 
    lut.at<Vec3b>(i)[2]= (value >> 16) & 0xff; 
    lut.at<Vec3b>(i)[1]= (value >> 8) & 0xff; 
    lut.at<Vec3b>(i)[0]= value & 0xff; 
} 
LUT(imgColor, lut, reducedColor); 

답변

3

아마도 지금까지 살펴 보았지만 문제의 근본 원인은 바로 8 비트 길이 인 uchar value으로 16 비트 이동을하는 것입니다. 이 경우의 8 비트 시프트조차도 너무 많아서 uchar에있는 모든 비트를 지울 것입니다. 그렇다면 cv::LUT documentation에는 src이 분명히 코드에없는 "8 비트 요소의 입력 배열"이어야한다는 내용이 명시되어 있습니다. 결과적으로 컬러 이미지의 첫 번째 채널 (파란색 채널) 만 cv::LUT으로 변환됩니다.

이러한 제한 사항을 해결하는 가장 좋은 방법은 채널간에 컬러 이미지를 분리하고 각 채널을 개별적으로 변환 한 다음 변환 된 채널을 새로운 색상 이미지로 병합하는 것입니다. 아래 코드를 참조하십시오.

/* 
Calculates a table of 256 assignments with the given number of distinct values. 

Values are taken at equal intervals from the ranges [0, 128) and [128, 256), 
such that both 0 and 255 are always included in the range. 
*/ 
cv::Mat lookupTable(int levels) { 
    int factor = 256/levels; 
    cv::Mat table(1, 256, CV_8U); 
    uchar *p = table.data; 

    for(int i = 0; i < 128; ++i) { 
     p[i] = factor * (i/factor); 
    } 

    for(int i = 128; i < 256; ++i) { 
     p[i] = factor * (1 + (i/factor)) - 1; 
    } 

    return table; 
} 

/* 
Truncates channel levels in the given image to the given number of 
equally-spaced values. 

Arguments: 

image 
    Input multi-channel image. The specific color space is not 
    important, as long as all channels are encoded from 0 to 255. 

levels 
    The number of distinct values for the channels of the output 
    image. Output values are drawn from the range [0, 255] from 
    the extremes inwards, resulting in a nearly equally-spaced scale 
    where the smallest and largest values are always 0 and 255. 

Returns: 

Multi-channel images with values truncated to the specified number of 
distinct levels. 
*/ 
cv::Mat colorReduce(const cv::Mat &image, int levels) { 
    cv::Mat table = lookupTable(levels); 

    std::vector<cv::Mat> c; 
    cv::split(image, c); 
    for (std::vector<cv::Mat>::iterator i = c.begin(), n = c.end(); i != n; ++i) { 
     cv::Mat &channel = *i; 
     cv::LUT(channel.clone(), table, channel); 
    } 

    cv::Mat reduced; 
    cv::merge(c, reduced); 
    return reduced; 
} 
+1

어디에서 LUT를 완전히 이해하고 사용할 수 있습니까? 나는 opencv 문서를 보았지만 그 문법은 엄격했다. 이 'LUT 이미지'의 값을 저장하고 다른 동일한 값에 적용하려는 경우 수행 할 작업 – AHF

+1

LUT의 목적은 찾아보기 테이블에 따라 이미지의 색상을 변경하는 것입니다. 이미지 분할에서 전처리 단계로 색상 해상도를 낮추는 등 다양한 목적을 가질 수 있습니다. http://en.wikipedia.org/wiki/Colour_look-up_table – xperroni

+0

동일한 LUT 변환을 다른 이미지에 적용하는 경우 위의 'colorReduce()'함수를 수정하여 lookup table에 대한 참조를 인자로 사용한다면'lookupTable()'또는 적절한 것으로 생각되는 다른 메소드를 별도로 호출하여 테이블을 계산하면된다. – xperroni

0

in은 모두 정수이므로 i/n은 정수입니다. 아마도 바닥을 차지하기 전에 n을 곱하기 전에 그것을 double ((double)i/n)으로 변환하고 싶습니까?

+0

어떻게 답변이 모두 파란색으로 설명되어 있습니까? – nkint

+0

uchar은 몇 바이트입니까? 최소한 3 바이트를 가정합니다. 넓은 문자 인 경우에도 3 바이트가 아닌 2 바이트 여야합니다. –