使用opencv和LUT进行颜色深度缩减

使用opencv和LUT进行颜色深度缩减

本文介绍了使用opencv和LUT进行颜色深度缩减的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过颜色深度缩放来执行缩减颜色。

I'd like to perform a color reduction via color depth scaling.

像这个例子:

Like this example:

第一张图片是CGA分辨率,第二张是EGA,火腿。
我想使用cv :: LUT,因为我认为这是更好的做。
我可以使用greyscale这个代码:

the first image is CGA resolution, the second is EGA, the third is HAM.I'd like to do it with cv::LUT because i think it is the betterway to do it.I can do with greyscale with this code:

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);

原始:

color reduced:

color reduced:

但是如果我尝试用颜色做它,我会得到奇怪的结果..

but if i try to do it with color I get strange result..

此代码:

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);


推荐答案

现在你可能已经走了,问题的根源是你正在做一个16位移位到 uchar值,这只是8位长。即使是这种情况下的8位移位也太多了,因为你会清除 uchar 中的所有位。然后有一个事实,即明确指出 src 必须是一个8位元素的输入数组,这很清楚isn'在你的代码中的情况。最终结果是只有 cv :: LUT 转换彩色图像(蓝色通道)的第一个通道。

You'll probably have moved on by now, but the root of the problem is that you are doing a 16-bit shift to uchar value, which is just 8-bits long. Even an 8-bit shift in this case is too much, as you'll erase all the bits in the uchar. Then there is the fact that the cv::LUT documentation explicitly states that src must be an "input array of 8-bit elements", which clearly isn't the case in your code. The net result is that only the first channel of the color image (the Blue channel) is transformed by cv::LUT.

解决这些限制的最佳方法是跨通道分割彩色图像,分别转换每个通道,然后将转换的通道合并为新的彩色图像。请参阅下面的代码:

The best way to work around these limitations is to split color images across channels, transform each channel separately, and then merge the transformed channels into a new color image. See the code below:

/*
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;
}

这篇关于使用opencv和LUT进行颜色深度缩减的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 12:42