如何使用 OpenCV 减少图像中的颜色数量?

发布于 2024-11-05 13:11:52 字数 133 浏览 3 评论 0原文

我有一组图像文件,我想将它们的颜色数量减少到 64 种。我如何使用 OpenCV 来做到这一点?

我需要这个,以便我可以使用 64 尺寸的图像直方图。 我正在实施 CBIR 技术,

我想要的是 4 位调色板的颜色量化。

I have a set of image files, and I want to reduce the number of colors of them to 64. How can I do this with OpenCV?

I need this so I can work with a 64-sized image histogram.
I'm implementing CBIR techniques

What I want is color quantization to a 4-bit palette.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

情栀口红 2024-11-12 13:11:52

OpenCV 2 计算机视觉 很好地介绍了这个主题应用程序编程手册

第 2 章 演出一些归约操作,其中一个在 C++ 中演示,稍后在 Python 中演示:

#include <iostream>
#include <vector>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


void colorReduce(cv::Mat& image, int div=64)
{    
    int nl = image.rows;                    // number of lines
    int nc = image.cols * image.channels(); // number of elements per line

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

int main(int argc, char* argv[])
{   
    // Load input image (colored, 3-channel, BGR)
    cv::Mat input = cv::imread(argv[1]);
    if (input.empty())
    {
        std::cout << "!!! Failed imread()" << std::endl;
        return -1;
    } 

    colorReduce(input);

    cv::imshow("Color Reduction", input);   
    cv::imwrite("output.jpg", input);   
    cv::waitKey(0);

    return 0;
}

下面您可以找到该操作的输入图像(左)和输出(右) :

Python 中的等效代码如下:
(归功于 @eliezer-bernart

import cv2
import numpy as np

input = cv2.imread('castle.jpg')

# colorReduce()
div = 64
quantized = input // div * div + div // 2

cv2.imwrite('output.jpg', quantized)

This subject was well covered on OpenCV 2 Computer Vision Application Programming Cookbook:

Chapter 2 shows a few reduction operations, one of them demonstrated here in C++ and later in Python:

#include <iostream>
#include <vector>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


void colorReduce(cv::Mat& image, int div=64)
{    
    int nl = image.rows;                    // number of lines
    int nc = image.cols * image.channels(); // number of elements per line

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

int main(int argc, char* argv[])
{   
    // Load input image (colored, 3-channel, BGR)
    cv::Mat input = cv::imread(argv[1]);
    if (input.empty())
    {
        std::cout << "!!! Failed imread()" << std::endl;
        return -1;
    } 

    colorReduce(input);

    cv::imshow("Color Reduction", input);   
    cv::imwrite("output.jpg", input);   
    cv::waitKey(0);

    return 0;
}

Below you can find the input image (left) and the output of this operation (right):

The equivalent code in Python would be the following:
(credits to @eliezer-bernart)

import cv2
import numpy as np

input = cv2.imread('castle.jpg')

# colorReduce()
div = 64
quantized = input // div * div + div // 2

cv2.imwrite('output.jpg', quantized)
一抹微笑 2024-11-12 13:11:52

您可能会考虑 K 均值,但在这种情况下它很可能会非常慢。更好的方法可能是您自己“手动”执行此操作。假设您有 CV_8UC3 类型的图像,即每个像素由 0 到 255 之间的 3 个 RGB 值表示的图像 (Vec3b)。您可以将这 256 个值“映射”为仅 4 个特定值,这将产生 4 x 4 x 4 = 64 可能的颜色。

我有一个数据集,我需要确保深色=黑色,浅色=白色,并减少其间所有颜色的数量。这就是我所做的(C++):

inline uchar reduceVal(const uchar val)
{
    if (val < 64) return 0;
    if (val < 128) return 64;
    return 255;
}

void processColors(Mat& img)
{
    uchar* pixelPtr = img.data;
    for (int i = 0; i < img.rows; i++)
    {
        for (int j = 0; j < img.cols; j++)
        {
            const int pi = i*img.cols*3 + j*3;
            pixelPtr[pi + 0] = reduceVal(pixelPtr[pi + 0]); // B
            pixelPtr[pi + 1] = reduceVal(pixelPtr[pi + 1]); // G
            pixelPtr[pi + 2] = reduceVal(pixelPtr[pi + 2]); // R
        }
    }
}

导致 [0,64) 变成 0, [64,128) -> 64[128,255) -> 255,产生 27 颜色:

在此处输入图像描述 在此处输入图像描述

对我来说,这似乎比其他答案中提到的任何其他内容都简洁、完全清晰且更快。

您还可以考虑将这些值减少为某个数字的倍数之一,比方说:

inline uchar reduceVal(const uchar val)
{
    if (val < 192) return uchar(val / 64.0 + 0.5) * 64;
    return 255;
}

这将产生一组 5 个可能的值:{0, 64, 128, 192, 255},即 125颜色。

You might consider K-means, yet in this case it will most likely be extremely slow. A better approach might be doing this "manually" on your own. Let's say you have image of type CV_8UC3, i.e. an image where each pixel is represented by 3 RGB values from 0 to 255 (Vec3b). You might "map" these 256 values to only 4 specific values, which would yield 4 x 4 x 4 = 64 possible colors.

I've had a dataset, where I needed to make sure that dark = black, light = white and reduce the amount of colors of everything between. This is what I did (C++):

inline uchar reduceVal(const uchar val)
{
    if (val < 64) return 0;
    if (val < 128) return 64;
    return 255;
}

void processColors(Mat& img)
{
    uchar* pixelPtr = img.data;
    for (int i = 0; i < img.rows; i++)
    {
        for (int j = 0; j < img.cols; j++)
        {
            const int pi = i*img.cols*3 + j*3;
            pixelPtr[pi + 0] = reduceVal(pixelPtr[pi + 0]); // B
            pixelPtr[pi + 1] = reduceVal(pixelPtr[pi + 1]); // G
            pixelPtr[pi + 2] = reduceVal(pixelPtr[pi + 2]); // R
        }
    }
}

causing [0,64) to become 0, [64,128) -> 64 and [128,255) -> 255, yielding 27 colors:

enter image description here enter image description here

To me this seems to be neat, perfectly clear and faster than anything else mentioned in other answers.

You might also consider reducing these values to one of the multiples of some number, let's say:

inline uchar reduceVal(const uchar val)
{
    if (val < 192) return uchar(val / 64.0 + 0.5) * 64;
    return 255;
}

which would yield a set of 5 possible values: {0, 64, 128, 192, 255}, i.e. 125 colors.

眼眸里的快感 2024-11-12 13:11:52

这是使用 K-Means 聚类的 Python 实现颜色量化 cv2.kmeans。其想法是减少图像中不同颜色的数量,同时尽可能保留图像的颜色外观。结果如下:

输入 -> 输出








代码

import cv2
import numpy as np

def kmeans_color_quantization(image, clusters=8, rounds=1):
    h, w = image.shape[:2]
    samples = np.zeros([h*w,3], dtype=np.float32)
    count = 0

    for x in range(h):
        for y in range(w):
            samples[count] = image[x][y]
            count += 1

    compactness, labels, centers = cv2.kmeans(samples,
            clusters, 
            None,
            (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001), 
            rounds, 
            cv2.KMEANS_RANDOM_CENTERS)

    centers = np.uint8(centers)
    res = centers[labels.flatten()]
    return res.reshape((image.shape))

image = cv2.imread('1.jpg')
result = kmeans_color_quantization(image, clusters=8)
cv2.imshow('result', result)
cv2.waitKey()     

Here's a Python implementation of color quantization using K-Means Clustering with cv2.kmeans. The idea is to reduce the number of distinct colors in an image while preserving the color appearance of the image as much as possible. Here's the result:

Input -> Output








Code

import cv2
import numpy as np

def kmeans_color_quantization(image, clusters=8, rounds=1):
    h, w = image.shape[:2]
    samples = np.zeros([h*w,3], dtype=np.float32)
    count = 0

    for x in range(h):
        for y in range(w):
            samples[count] = image[x][y]
            count += 1

    compactness, labels, centers = cv2.kmeans(samples,
            clusters, 
            None,
            (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001), 
            rounds, 
            cv2.KMEANS_RANDOM_CENTERS)

    centers = np.uint8(centers)
    res = centers[labels.flatten()]
    return res.reshape((image.shape))

image = cv2.imread('1.jpg')
result = kmeans_color_quantization(image, clusters=8)
cv2.imshow('result', result)
cv2.waitKey()     
少年亿悲伤 2024-11-12 13:11:52

有很多方法可以做到这一点。 jeff7建议的方法还可以,但有一些缺点:

  • 方法1有参数N和M,您必须选择它们,并且还必须将其转换为另一个颜色空间。
  • 方法 2 的回答可能非常慢,因为您应该计算 1670 万个 bin 直方图并按频率对其进行排序(以获得 64 个更高的频率值)

我喜欢使用基于最高有效位的算法使用 RGB 颜色并将其转换为 64 色图像。如果您使用的是 C/OpenCV,则可以使用类似下面的函数。

如果您正在处理灰度图像,我建议使用 OpenCV 2.3 的 LUT() 函数,因为它更快。有一个关于如何使用LUT来减少颜色数量的教程。请参阅:教程:如何扫描图像、查找表...但是我找到了它如果您使用 RGB 图像,情况会更复杂。

void reduceTo64Colors(IplImage *img, IplImage *img_quant) {
    int i,j;
    int height   = img->height;   
    int width    = img->width;    
    int step     = img->widthStep;

    uchar *data = (uchar *)img->imageData;
    int step2 = img_quant->widthStep;
    uchar *data2 = (uchar *)img_quant->imageData;

    for (i = 0; i < height ; i++)  {
        for (j = 0; j < width; j++)  {

          // operator XXXXXXXX & 11000000 equivalent to  XXXXXXXX AND 11000000 (=192)
          // operator 01000000 >> 2 is a 2-bit shift to the right = 00010000 
          uchar C1 = (data[i*step+j*3+0] & 192)>>2;
          uchar C2 = (data[i*step+j*3+1] & 192)>>4;
          uchar C3 = (data[i*step+j*3+2] & 192)>>6;

          data2[i*step2+j] = C1 | C2 | C3; // merges the 2 MSB of each channel
        }     
    }
}

There are many ways to do it. The methods suggested by jeff7 are OK, but some drawbacks are:

  • method 1 have parameters N and M, that you must choose, and you must also convert it to another colorspace.
  • method 2 answered can be very slow, since you should compute a 16.7 Milion bins histogram and sort it by frequency (to obtain the 64 higher frequency values)

I like to use an algorithm based on the Most Significant Bits to use in a RGB color and convert it to a 64 color image. If you're using C/OpenCV, you can use something like the function below.

If you're working with gray-level images I recommed to use the LUT() function of the OpenCV 2.3, since it is faster. There is a tutorial on how to use LUT to reduce the number of colors. See: Tutorial: How to scan images, lookup tables... However I find it more complicated if you're working with RGB images.

void reduceTo64Colors(IplImage *img, IplImage *img_quant) {
    int i,j;
    int height   = img->height;   
    int width    = img->width;    
    int step     = img->widthStep;

    uchar *data = (uchar *)img->imageData;
    int step2 = img_quant->widthStep;
    uchar *data2 = (uchar *)img_quant->imageData;

    for (i = 0; i < height ; i++)  {
        for (j = 0; j < width; j++)  {

          // operator XXXXXXXX & 11000000 equivalent to  XXXXXXXX AND 11000000 (=192)
          // operator 01000000 >> 2 is a 2-bit shift to the right = 00010000 
          uchar C1 = (data[i*step+j*3+0] & 192)>>2;
          uchar C2 = (data[i*step+j*3+1] & 192)>>4;
          uchar C3 = (data[i*step+j*3+2] & 192)>>6;

          data2[i*step2+j] = C1 | C2 | C3; // merges the 2 MSB of each channel
        }     
    }
}
素手挽清风 2024-11-12 13:11:52

这里建议的答案非常好。我想我也应该添加我的想法。我遵循这里许多评论的表述,其中据说 RGB 图像中每个通道的 2 位可以表示 64 种颜色。

下面代码中的函数将图像和量化所需的位数作为输入。它使用位操作来“丢弃”LSB 位并仅保留所需的位数。结果是一种灵活的方法,可以将图像量化为任意位数。

#include "include\opencv\cv.h"
#include "include\opencv\highgui.h"

// quantize the image to numBits 
cv::Mat quantizeImage(const cv::Mat& inImage, int numBits)
{
    cv::Mat retImage = inImage.clone();

    uchar maskBit = 0xFF;

    // keep numBits as 1 and (8 - numBits) would be all 0 towards the right
    maskBit = maskBit << (8 - numBits);

    for(int j = 0; j < retImage.rows; j++)
        for(int i = 0; i < retImage.cols; i++)
        {
            cv::Vec3b valVec = retImage.at<cv::Vec3b>(j, i);
            valVec[0] = valVec[0] & maskBit;
            valVec[1] = valVec[1] & maskBit;
            valVec[2] = valVec[2] & maskBit;
            retImage.at<cv::Vec3b>(j, i) = valVec;
        }

        return retImage;
}


int main ()
{
    cv::Mat inImage;
    inImage = cv::imread("testImage.jpg");
    char buffer[30];
    for(int i = 1; i <= 8; i++)
    {
        cv::Mat quantizedImage = quantizeImage(inImage, i);
        sprintf(buffer, "%d Bit Image", i);
        cv::imshow(buffer, quantizedImage);

        sprintf(buffer, "%d Bit Image.png", i);
        cv::imwrite(buffer, quantizedImage);
    }

    cv::waitKey(0);
    return 0;
}

以下是上述函数调用中使用的图像:

在此处输入图像描述

每个 RGB 通道量化为 2 位的图像(总共 64 种颜色):

在此处输入图像描述

每个通道 3 位:

在此处输入图像描述

4 位...

在此处输入图像描述

The answers suggested here are really good. I thought I would add my idea as well. I follow the formulation of many comments here, in which it is said that 64 colors can be represented by 2 bits of each channel in an RGB image.

The function in code below takes as input an image and the number of bits required for quantization. It uses bit manipulation to 'drop' the LSB bits and keep only the required number of bits. The result is a flexible method that can quantize the image to any number of bits.

#include "include\opencv\cv.h"
#include "include\opencv\highgui.h"

// quantize the image to numBits 
cv::Mat quantizeImage(const cv::Mat& inImage, int numBits)
{
    cv::Mat retImage = inImage.clone();

    uchar maskBit = 0xFF;

    // keep numBits as 1 and (8 - numBits) would be all 0 towards the right
    maskBit = maskBit << (8 - numBits);

    for(int j = 0; j < retImage.rows; j++)
        for(int i = 0; i < retImage.cols; i++)
        {
            cv::Vec3b valVec = retImage.at<cv::Vec3b>(j, i);
            valVec[0] = valVec[0] & maskBit;
            valVec[1] = valVec[1] & maskBit;
            valVec[2] = valVec[2] & maskBit;
            retImage.at<cv::Vec3b>(j, i) = valVec;
        }

        return retImage;
}


int main ()
{
    cv::Mat inImage;
    inImage = cv::imread("testImage.jpg");
    char buffer[30];
    for(int i = 1; i <= 8; i++)
    {
        cv::Mat quantizedImage = quantizeImage(inImage, i);
        sprintf(buffer, "%d Bit Image", i);
        cv::imshow(buffer, quantizedImage);

        sprintf(buffer, "%d Bit Image.png", i);
        cv::imwrite(buffer, quantizedImage);
    }

    cv::waitKey(0);
    return 0;
}

Here is an image that is used in the above function call:

enter image description here

Image quantized to 2 bits for each RGB channel (Total 64 Colors):

enter image description here

3 bits for each channel:

enter image description here

4 bits ...

enter image description here

日记撕了你也走了 2024-11-12 13:11:52

OpenCV 库中已经提供了 K 均值聚类算法。简而言之,它确定围绕用户定义的 k 值(= 簇数)对数据进行聚类的最佳质心。因此,在您的情况下,您可以找到围绕给定 k=64 值对像素值进行聚类的质心。如果你谷歌一下,详细信息就在那里。 这里是 k-means 的简短介绍。

SO 使用 k-means,希望有帮助。

另一种方法是使用金字塔均值偏移OpenCV 中的过滤器 函数。它产生的图像有些“扁平化”,即颜色数量较少,因此它可能会对您有所帮助。

There is the K-means clustering algorithm which is already available in the OpenCV library. In short it determines which are the best centroids around which to cluster your data for a user-defined value of k ( = no of clusters). So in your case you could find the centroids around which to cluster your pixel values for a given value of k=64. The details are there if you google around. Here's a short intro to k-means.

Something similar to what you are probably trying was asked here on SO using k-means, hope it helps.

Another approach would be to use the pyramid mean shift filter function in OpenCV. It yields somewhat "flattened" images, i.e. the number of colors are less so it might be able to help you.

唠甜嗑 2024-11-12 13:11:52

如果您想要 C++ 中的快速而肮脏的方法,请在 1 行中:

capImage &= cv::Scalar(0b11000000, 0b11000000, 0b11000000);

因此,它所做的就是保留每个 R、G、B 分量的高 2 位,并丢弃低 6 位,即 0b11000000。

由于 RGB 有 3 个通道,因此您最多可以获得 4 R x 4 B x 4 B = 最多 64 种颜色。这样做的优点是您可以在任意数量的图像上运行它,并且将映射相同的颜色。

请注意,这可能会使您的图像变得更暗,因为它会丢弃一些位。

对于灰度图像,您可以这样做:

capImage &= 0b11111100;

这将保留高 6 位,这意味着您将获得 256 个灰度中的 64 个灰度,并且图像也会变得更暗一些。

这是一个例子,原始图像 = 251424 种独特的颜色。
输入图片此处描述

生成的图像有 46 种颜色:
输入图片此处描述

If you want a quick and dirty method in C++, in 1 line:

capImage &= cv::Scalar(0b11000000, 0b11000000, 0b11000000);

So, what it does is keep the upper 2 bits of each R, G, B component, and discards the lower 6 bits, hence the 0b11000000.

Because of the 3 channels in RGB, you get maximum 4 R x 4 B x 4 B = max 64 colors. The advantage of doing this is that you can run this on any number of images and the same colors will be mapped.

Note that this can make your image a bit darker since it discards some bits.

For a greyscale image, you can do:

capImage &= 0b11111100;

This will keep the upper 6 bits, which means you get 64 grays out of 256, and again the image can become a bit darker.

Here's an example, original image = 251424 unique colors.
enter image description here

And the resulting image has 46 colors:
enter image description here

风铃鹿 2024-11-12 13:11:52

假设您想对所有图像使用相同的 64 种颜色(即调色板未针对每个图像进行优化),我至少可以想到几个选择:

1) 转换为 Lab 或 YCrCb 色彩空间并使用 N 位进行亮度量化每个颜色通道为 M 位,N 应大于 M。

2) 计算所有训练图像的颜色值的 3D 直方图,然后选择具有最大 bin 值的 64 种颜色。通过为每个像素分配训练集中最接近的 bin 的颜色来量化图像。

方法 1 是最通用且最容易实现的,而方法 2 可以更好地适合您的特定数据集。

更新:
例如,32 种颜色为 5 位,因此将 3 位分配给亮度通道,将 1 位分配给每个颜色通道。要进行此量化,请将亮度通道除以 2^8/2^3 = 32,将每个颜色通道除以 2^8/2^1 = 128。现在只有 8 个不同的亮度值和 2 个不同的颜色通道每个。通过位移或数学运算将这些值重新组合成单​​个整数(量化颜色值 = 亮度*4+颜色1*2+颜色2);

Assuming that you want to use the same 64 colors for all images (ie palette not optimized per image), there are a at least a couple choices I can think of:

1) Convert to Lab or YCrCb colorspace and quantize using N bits for luminance and M bits for each color channel, N should be greater than M.

2) Compute a 3D histogram of color values over all your training images, then choose the 64 colors with the largest bin values. Quantize your images by assigning each pixel the color of the closest bin from the training set.

Method 1 is the most generic and easiest to implement, while method 2 can be better tailored to your specific dataset.

Update:
For example, 32 colors is 5 bits so assign 3 bits to the luminance channel and 1 bits to each color channel. To do this quantization, do integer division of the luminance channel by 2^8/2^3 = 32 and each color channel by 2^8/2^1 = 128. Now there are only 8 different luminance values and 2 different color channels each. Recombine these values into a single integer doing bit shifting or math (quantized color value = luminance*4+color1*2+color2);

半岛未凉 2024-11-12 13:11:52

一个简单的按位和适当的位掩码就可以解决问题。

python,对于 64 种颜色,

img = img & int("11000000", 2)

RGB 图像的颜色数量应该是一个完美的立方体(3 个通道相同)。

对于此方法,通道的可能值的数量应为 2 的幂。(代码忽略此检查,并采用下一个较低的 2 幂)

import numpy as np
import cv2 as cv


def is_cube(n):
    cbrt = np.cbrt(n)
    return cbrt ** 3 == n, int(cbrt)


def reduce_color_space(img, n_colors=64):
    n_valid, cbrt = is_cube(n_colors)

    if not n_valid:
        print("n_colors should be a perfect cube")
        return

    n_bits = int(np.log2(cbrt))

    if n_bits > 8:
        print("Can't generate more colors")
        return

    bitmask = int(f"{'1' * n_bits}{'0' * (8 - n_bits)}", 2)

    return img & bitmask


img = cv.imread("image.png")

cv.imshow("orig", img)
cv.imshow("reduced", reduce_color_space(img))

cv.waitKey(0)

A simple bitwise and with a proper bitmask would do the trick.

python, for 64 colors,

img = img & int("11000000", 2)

The number of colors for an RGB image should be a perfect cube (same across 3 channels).

For this method, the number of possible values for a channel should be a power of 2. (This check is ignored by the code and the next lower power of 2 is taken by it)

import numpy as np
import cv2 as cv


def is_cube(n):
    cbrt = np.cbrt(n)
    return cbrt ** 3 == n, int(cbrt)


def reduce_color_space(img, n_colors=64):
    n_valid, cbrt = is_cube(n_colors)

    if not n_valid:
        print("n_colors should be a perfect cube")
        return

    n_bits = int(np.log2(cbrt))

    if n_bits > 8:
        print("Can't generate more colors")
        return

    bitmask = int(f"{'1' * n_bits}{'0' * (8 - n_bits)}", 2)

    return img & bitmask


img = cv.imread("image.png")

cv.imshow("orig", img)
cv.imshow("reduced", reduce_color_space(img))

cv.waitKey(0)
瞄了个咪的 2024-11-12 13:11:52

img = numpy.multiply(img//32, 32)

img = numpy.multiply(img//32, 32)

长梦不多时 2024-11-12 13:11:52

nQuantGpp 包括用于 g++ 生成高质量优化图像的前 10 种颜色量化算法。它从 nQuantCpp 移植到 OpenCV,以利用此类流行库的深度学习功能。

Mat source = imread(sourceFile, IMREAD_UNCHANGED);
PnnQuant::PnnQuantizer pnnQuantizer;
int nMaxColors = 64;
vector<uchar> pngBytes;
Mat dest = pnnQuantizer.QuantizeImage(source, pngBytes, nMaxColors, true);
if(nMaxColors > 256)
    imwrite(destPath, dest);
else {
    ofstream outfile(destPath, ios::binary);
    outfile.write(reinterpret_cast<const char*>(pngBytes.data()), pngBytes.size());
    outfile.close();
}

通过基于 Fast PNN 的算法减少到 64 色
简化为通过基于快速成对最近邻的算法实现 64 种颜色

通过使用 CIELAB 色彩空间的基于快速 PNN 的算法将 64 种颜色减少到 64 种颜色
简化为通过使用 CIELAB 色彩空间的快速成对最近邻算法实现 64 种颜色

通过 NeuQuant 神经网络量化算法将 64 种颜色减少到 64 种颜色
简化为通过 NeuQuant 神经网络量化算法实现 64 种颜色

通过高效、边缘感知、组合颜色量化和抖动减少至 64 种颜色CIELAB 色彩空间
简化为通过高效、边缘感知、结合 CIELAB 色彩空间的色彩量化和抖动实现 64 种颜色

通过 Xialoin Wu 的快速最佳色彩减少到 64 种颜色量化算法
简化为64种颜色由Xialoin Wu的快速最优颜色量化算法

最后,CBIR技术最本质的方法应该是OTSU方法(OTSU),它是一种全局自适应二值化阈值图像分割算法。然后,通过从图像数据集中有效提取特征向量来将图像分类为有意义的类别一直依赖于特征选择技术。

nQuantGpp includes top 10 color quantization algorithms for g++ producing high quality optimized images. It is ported from nQuantCpp which migrates to OpenCV to leverage the deep learning features of such popular library.

Mat source = imread(sourceFile, IMREAD_UNCHANGED);
PnnQuant::PnnQuantizer pnnQuantizer;
int nMaxColors = 64;
vector<uchar> pngBytes;
Mat dest = pnnQuantizer.QuantizeImage(source, pngBytes, nMaxColors, true);
if(nMaxColors > 256)
    imwrite(destPath, dest);
else {
    ofstream outfile(destPath, ios::binary);
    outfile.write(reinterpret_cast<const char*>(pngBytes.data()), pngBytes.size());
    outfile.close();
}

Reduced to 64 colors by Fast PNN based algorithm
Reduced to 64 colors by Fast pairwise nearest neighbor based algorithm

Reduced to 64 colors by Fast PNN based algorithm with CIELAB color space
Reduced to 64 colors by Fast pairwise nearest neighbor based algorithm with CIELAB color space

Reduced to 64 colors by NeuQuant Neural-Net Quantization Algorithm
Reduced to 64 colors by NeuQuant Neural-Net Quantization Algorithm

Reduced to 64 colors by Efficient, Edge-Aware, Combined Color Quantization and Dithering with CIELAB color space
Reduced to 64 colors by Efficient, Edge-Aware, Combined Color Quantization and Dithering with CIELAB color space

Reduced to 64 colors by Xialoin Wu's fast optimal color Quantization Algorithm
Reduced to 64 colors by Xialoin Wu's fast optimal color Quantization Algorithm

Finally, the most essential method for CBIR techniques should be the OTSU method (OTSU) which is a global adaptive binarization threshold image segmentation algorithm. Then categorization of images into meaningful classes by efficient extraction of feature vectors from image datasets has been dependent on feature selection techniques.

沫尐诺 2024-11-12 13:11:52

为什么不直接进行矩阵乘法/除法呢?值将自动四舍五入。

伪代码:

将您的频道转换为无符号字符 (CV_8UC3),
除以
总颜色/所需颜色。垫子 = 垫子 / (256/64)。小数点
将被截断。
乘以相同的数字。垫子=垫子*4

完成。每个通道现在仅包含 64 种颜色。

Why don't you just do Matrix multiplication/division? Values will be automatically rounded.

Pseudocode:

convert your channels to unsigned characters (CV_8UC3),
Divide by
total colors / desired colors. Mat = Mat / (256/64). Decimal points
will be truncated.
Multiply by the same number. Mat = mat * 4

Done. Each channel now only contains 64 colors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文