【问题标题】:OpenCV: Grayscale color reductionOpenCV:灰度颜色减少
【发布时间】:2017-03-02 21:05:00
【问题描述】:

我正在尝试使用此公式将灰度图像颜色从 256 降低到 4 来自http://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html

我假设 n 是减少因子,对于这种情况,它将是公式中的 10 种颜色。 我的代码如下。

void Reduction(Mat image1)
{
for (int r = 0;r < image1.rows;r++) {

    for (int c = 0;c < image1.cols;c++) {
        // get pixel

        int tmp = (image1.at<Vec3b>(r, c)[0] + image1.at<Vec3b>(r, c)[1] + image1.at<Vec3b>(r, c)[2])/3 ;
        tmp =  (tmp/4)* 4;
        image1.at<Vec3b>(r, c)[0] = tmp;
        image1.at<Vec3b>(r, c)[1] = tmp;
        image1.at<Vec3b>(r, c)[2] = tmp;
    }

    }
}

我的预期结果是

但是从 tmp = (tmp/4)*4;或 tmp = (tmp/8)*8;

我的图片看起来和原图一样;

然后我尝试将其更改为 tmp = (tmp/40)*40;

我得到的结果与我想要的结果相似。

公式是如何工作的,我应该从我的代码中编辑什么来准确地得到我想要的结果? (就像上面的预期结果)

【问题讨论】:

  • (tmp / 4) * 4) 从 256 种颜色减少到 64 种颜色。 (tmp / 8) * 8) 从 256 种颜色减少到 32 种颜色。等等。您的原始公式(tmp / 10) * 10) 正在从 256 种颜色减少到 25 种颜色。这是如何运作的?在第一种情况下,颜色4 5 6 7 变为1 1 1 1,然后变为4 4 4 4,因为整数除法。
  • 不要垃圾标签! C 和 C++ 是不同的语言。
  • 更好的方法是使用舍入。颜色减少算法有据可查。应该有大量信息可以找到它们如何运行以及哪些算法最适合。
  • @WeatherVane 谢谢你的解释。现在对整数除法有了更好的理解
  • 如果您不想要类似卡通的输出,我会使用带有常量预定义调色板的simple Dithering in C++。只是 r,g,b 只计算 intensity 所以几乎 2/3 的代码将消失。

标签: c++ algorithm opencv colors


【解决方案1】:

这是一种颜色量化。这是一个简单的技术reduce the number of colors 在依赖于整数除法

的图像中

由于起始范围有256 值,如果你想以N 的颜色结束,你需要整数除法,然后乘以K = 256 / N

所以在你的情况下,对于N=8,你需要一个K = 256 / 8 = 32,对于N = 4,你需要K = 256 / 4 = 64

【讨论】:

    【解决方案2】:

    使用您给出的公式的变体,您将无法在“预期结果”图像中获得 4 色图像,因为整数除法总是向下舍入。它产生这个结果:

    input       output
    0-63        0
    64-127      64
    128-191     128
    192-255     192
    

    因此图像中的任何像素都不会超过全亮度的 3/4(浅灰色),并且目标图像包含纯白色。

    简单的四舍五入到范围的中点也不起作用,因为目标图像包含纯黑色和纯白色,所以对于黑色,您需要始终向下舍入,而对于白色,您需要始终四舍五入起来。

    您可能还希望将 256 色范围平均分成 4 个相等的部分,如果您进行简单的舍入,这将不起作用,因为黑色和白色最终会被较小的范围覆盖。

    它有助于准确排除您希望范围划分的方式。例如,假设您想将其分成 4 份,然后创建一个包含白色和黑色的等距范围:

    input       output
    0-63        0
    64-127      85
    128-191     170
    192-255     255
    

    您可以在绘图应用中打开您预期的结果图像,并使用吸管工具来验证这些是正确的输出值。

    这个公式是:

    int new_value = (value / 64) * 85;
    

    或更笼统地说:

    int num_colors = 4;
    int divisor = 256 / num_colors;
    int max_quantized_value = 255 / divisor;
    int new_value = ((value / divisor) * 255) / max_quantized_value;
    

    这样,您可以保证获得最小 new_value 为 0 和最大 new_value 为 255。

    【讨论】:

      【解决方案3】:

      查看颜色量化的另一种方法是考虑位/像素。通常,灰度图像的每个像素使用 8 位存储,因此结果值范围为 0 到 255。

      我们可以通过量化或换句话说dropping the Least Significant Bits (LSB) 来减少图像中的颜色数量。 8 位表示通常如下所示:

      V V V V V V V V

      当减少时,我们可以删除 LSB,例如:

      V V V V V V x x

      V V V V x x x x

      其中 V 表示二进制值,x 表示丢弃的位。在您的情况下,您希望减少到 4 种颜色,这意味着您只需要两位来表示您的图像。在这种情况下,每个字节将如下所示:

      V V x x x x x x

      这可以通过在灰度图像中的uchar 值上使用左移运算符&gt;&gt; 来完成(如所附答案所示)。

      【讨论】:

      • 仅当您想要“二的幂”颜色时;D
      猜你喜欢
      • 2013-01-26
      • 1970-01-01
      • 2020-07-18
      • 2012-11-06
      • 1970-01-01
      • 2018-11-18
      • 2013-01-12
      • 2012-07-11
      • 1970-01-01
      相关资源
      最近更新 更多