【问题标题】:color depth reduction with opencv and LUT使用 opencv 和 LUT 减少颜色深度
【发布时间】:2013-01-26 13:40:33
【问题描述】:

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

像这个例子:

第一张是CGA分辨率,第二张是EGA,第三张是HAM。 我想用 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);

原文:

颜色减少:

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

使用此代码:

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

【问题讨论】:

    标签: c++ opencv colors depth


    【解决方案1】:

    您现在可能已经继续前进,但问题的根源在于您正在执行 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;
    }
    

    【讨论】:

    • 从哪里可以全面了解和使用LUT?我看到了 opencv 文档,但它对语法很严格。如果您想保存此 LUT image 的值并将其应用于其他相同的值,您该怎么做
    • LUT 的目的是根据查找表更改图像的颜色。这可以有多种目的,例如降低颜色分辨率作为图像分割中的预处理步骤。有关更多信息,请参阅此 Wikipedia 文章:en.wikipedia.org/wiki/Colour_look-up_table
    • 至于对不同图像应用相同的 LUT 变换,您可以修改上面的 colorReduce() 函数以接受对查找表的引用作为参数,然后在单独调用 @987654331 中计算表@ 或您认为合适的任何其他方法。
    【解决方案2】:

    in 都是整数,因此 i/n 是整数。也许您希望在发言并乘以 n 之前将其转换为双倍 ((double)i/n)?

    【讨论】:

    • 你的回答如何解释所有的蓝色?
    • uchar 有多少字节?您假设至少 3 个字节;即使是宽字符,也应该是 2 个字节,而不是 3 个或更多。
    猜你喜欢
    • 2017-03-02
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    • 2020-07-18
    • 2011-08-19
    • 2011-02-27
    • 2016-08-21
    相关资源
    最近更新 更多