2013-02-11 14 views
6

के साथ रंग गहराई में कमी मैं रंग गहराई स्केलिंग के माध्यम से रंग में कमी करना चाहता हूं।ओपनसीवी और एलयूटी

इस उदाहरण की तरह

: enter image description here

पहली छवि सीजीए संकल्प दूसरा ईजीए है तीसरे हैम है,,। मैं इसे सीवी :: 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

आप शायद अब तक चले गए हैं, लेकिन समस्या की जड़ यह है कि आप 16-बिट शिफ्ट कर रहे हैं uchar value, जो केवल 8-बिट लंबा है। इस मामले में भी 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

जहां से मैं पूरी समझ और एलयूटी का उपयोग कर सकता हूं? मैंने opencv दस्तावेज देखा लेकिन यह सिंटैक्स के लिए सिर्फ सख्त है। यदि आप इस 'LUT छवि' के मानों को सहेजना चाहते हैं तो आप क्या करते हैं और इसे अन्य मानों पर लागू करना चाहते हैं – AHF

+1

LUT का उद्देश्य एक लुकअप तालिका के अनुसार छवि के रंगों को बदलना है। इसमें विभिन्न उद्देश्यों हो सकते हैं, जैसे रंग संकल्प को छवि विभाजन में प्रीप्रोकैसिंग चरण के रूप में कम करना। कुछ अतिरिक्त जानकारी के लिए यह विकिपीडिया आलेख देखें: http://en.wikipedia.org/wiki/Colour_look-up_table – xperroni

+0

एक ही LUT को विभिन्न छवियों में बदलने के लिए, आप उपरोक्त 'colorReduce()' फ़ंक्शन को संशोधित करने के लिए संशोधित कर सकते हैं लुकअप टेबल को तर्क के रूप में संदर्भित करें, फिर तालिका को 'लुकअपटेबल()' या किसी भी अन्य विधि को उचित कॉल में गणना करें। – xperroni

0

दोनों i और n पूर्णांक हैं, इसलिए i/n एक पूर्णांक है। शायद आप n द्वारा फर्श लेने और गुणा करने से पहले इसे डबल ((double)i/n) में परिवर्तित करना चाहते हैं?

+0

आपका उत्तर नीले रंग की व्याख्या कैसे करता है? – nkint

+0

कितने बाइट्स है uchar? आप कम से कम 3 बाइट मानते हैं; भले ही यह विस्तृत चार है, फिर भी यह 2 बाइट्स होना चाहिए, न कि 3 या अधिक। –