【问题标题】:Why is this "reduction factor" algo doing "+ div/2"为什么这个“减少因子”算法在做“+ div/2”
【发布时间】:2014-07-18 03:59:39
【问题描述】:

所以我正在阅读 Robert Laganiere 的“OpenCV 2 计算机视觉应用程序编程食谱”。在第 42 页左右,它正在讨论图像缩减算法。我理解算法(我认为),但我不明白为什么要放入一个部分。我想我知道为什么,但如果我错了,我想纠正。我将在这里复制并粘贴一点:

"彩色图像由 3 通道像素组成。每个通道 对应于三基色之一的强度值 (红色、绿色、蓝色)。由于这些值中的每一个都是 8 位无符号 char,颜色总数为256x256x256,大于16 万种颜色。因此,为了降低分析的复杂性, 有时减少图像中的颜色数量很有用。一 实现这个目标的简单方法是简单地细分 RGB 空间 成大小相等的立方体。例如,如果您减少 每个维度的颜色乘以 8,那么您将获得总共 32x32x32 颜色。然后为原始图像中的每种颜色分配一个 减色图像中对应的新颜色值 它所属的立方体中心的值。因此, 基本的颜色减少算法很简单。如果 N 是减少 因子,然后对于图像中的每个像素和每个通道 像素,将值除以 N(整数除法,因此提醒 丢失)。然后将结果乘以 N,这将为您提供 N 的倍数刚好低于输入像素值。只需添加 N/2 即可 获得两个相邻的区间的中心位置 N 的倍数。如果对每个 8 位通道重复此过程 值,那么您将获得总共 256/N x 256/N x 256/N 可能 颜色值。怎么做……我们减色的签名 函数如下: void colorReduce(cv::Mat &image, int div=64);用户提供图像和每个通道的缩减 因素。在这里,处理是就地完成的,即像素 输入图像的值由函数修改。见 还有更多...这个配方的部分用于更通用的功能 带有输入和输出参数的签名。处理很简单 通过创建一个遍历所有像素值的双循环来完成:“

void colorReduce(cv::Mat &image, int div=64) {
    int nl= image.rows; // number of lines
    // total number of elements per line
    int nc= image.cols * image.channels();
    for (int j=0; j<nl; j++) {
        // get the address of row j
        uchar* data= image.ptr<uchar>(j);
        for (int i=0; i<nc; i++) {
            // process each pixel ---------------------
            data[i]=
            data[i]/div*div + div/2;// <-HERE IS WHERE I NEED UNDERSTANDING!!!
// end of pixel processing ---------------
}}}

所以我知道我是如何通过 div 数量减少 0:255 像素值的。然后我失去了剩下的任何东西。然后通过再次将它乘以 div 数量,我们将其放大以使其保持在 0:255 的范围内。 为什么我们还要在答案中添加 (div/2)? 我能想到的唯一原因是这会导致一些值向下舍入和一些值向上舍入。如果您不使用它,那么您的所有值都会向下舍入。所以在某种程度上它给出了一个“更好”的平均值?

不知道,你们觉得怎么样?

【问题讨论】:

    标签: c++ algorithm opencv image-processing


    【解决方案1】:

    说明这一点的最简单方法是使用示例。

    为简单起见,假设我们正在处理图像的单个通道。有 256 种不同的颜色,范围从 0 到 255。我们还将在示例中使用 N=64。

    使用这些数字,我们将颜色数量从 256 减少到 256/64 = 4。让我们绘制一个颜色空间图:

    |......|......|......|......| 
    0      63    127    191    255
    

    虚线代表我们的色彩空间,从 0 到 255。我们将这个区间分成 4 部分,并用垂直线表示。

    为了将所有 256 种颜色减少到 4 种颜色,我们将每种颜色除以 64(丢掉余数),然后再乘以 64。让我们看看这是怎么回事:

    [0  , 63 ] / 64 * 64 = 0
    [64 , 127] / 64 * 64 = 64
    [128, 191] / 64 * 64 = 128
    [192, 255] / 64 * 64 = 192
    

    如您所见,第一部分的所有颜色都变为 0,第二部分的所有颜色变为 64,第三部分为 128,第四部分为 192。所以我们的颜色空间如下所示:

    |......|......|......|......| 
    0      63    127    191    255
    |______/|_____/|_____/|_____/ 
    |       |      |      |
    0       64     128    192
    

    但这不是很有用。您可以看到我们所有的颜色都向间隔的左侧倾斜。如果它们位于间隔的中间,会更有帮助。这就是我们将64/2 = 32 添加到值的原因。添加间隔长度的一半会将颜色移动到间隔的中心。书中也是这么说的:“只要加上N/2,就可以得到N的两个相邻倍数的区间的中心位置。”

    让我们将 32 添加到我们的值中,看看一切如何:

    [0  , 63 ] / 64 * 64 + 32 = 32
    [64 , 127] / 64 * 64 + 32 = 96
    [128, 191] / 64 * 64 + 32 = 160
    [192, 255] / 64 * 64 + 32 = 224
    

    而区间是这样的:

    |......|......|......|......| 
    0      63    127    191    255
    \______/\_____/\_____/\_____/ 
       |       |      |      |
       32      96    160    224
    

    这是一种更好的色彩还原。该算法将我们的颜色空间从 256 种颜色减少到 4 种颜色,而这些颜色位于它们减少的间隔的中间。

    【讨论】:

      【解决方案2】:

      这样做是为了给出量化边界的平均值,而不是它的下限。 例如对于 N = 32,从 0 到 31 的所有数据将给出 16 而不是 0。

      请查看以下图片或我的excel file

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-23
        • 1970-01-01
        • 1970-01-01
        • 2015-04-23
        相关资源
        最近更新 更多