为什么这个“缩减因子”算法做“+ div / 2”

时间:2014-05-28 19:07:47

标签: c++ algorithm opencv image-processing

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

  

“彩色图像由3通道像素组成。每个通道   对应于三原色之一的强度值   (红色,绿色,蓝色)。由于这些值中的每一个都是8位无符号   char,颜色总数为256x256x256,超过16   百万种颜色。因此,为了降低分析的复杂性,   减少图像中的颜色数量有时很有用。一   实现这一目标的简单方法是简单地细分RGB空间   到相同大小的立方体。例如,如果减少数量   每个维度的颜色为8,那么你将获得总数   32x32x32颜色。然后为原始图像中的每种颜色分配一个   与颜色相对应的减色图像中的新颜色值   值所在的多维数据集的中心。因此,   基本的色彩还原算法很简单。如果N是减少   因此,对于图像中的每个像素以及每个像素的每个像素   像素,将值除以N(整数除法,因此提醒   迷路了)然后将结果乘以N,这将给你   刚好在输入像素值之下的N的倍数。只需添加N / 2即可   获得两个相邻区间的中心位置   如果为每个8位通道重复此过程,则为N的倍数   值,那么你将获得总共256 / N×256 / N×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)添加回答案?我能想到的唯一原因是这会导致某些值向下舍入而某些值向上舍入。如果您不使用它,那么所有值都会向下舍入。所以在某种程度上它给出了“更好”的平均值?

不知道,那么你们/女孩们的想法是什么?

2 个答案:

答案 0 :(得分:7)

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

为简单起见,我们假设我们正在处理图像的单个通道。有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的原因。添加间隔长度的一半会将颜色移动到间隔的中心。这也是它在书中所说的:&#34;只需添加N / 2即可获得N的两个相邻倍数之间的间隔的中心位置。&#34; < / p>

因此,让我们为我们的值添加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色,这些色彩位于它们减少的间隔的中间。

答案 1 :(得分:3)

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

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