OpenCV 使用 k 均值对图像进行色调分离

2024-04-02

我想在 C++ 接口(cv 命名空间)中使用 k-means 和 OpenCV 对图像进行色调分离,但得到了奇怪的结果。我需要它来减少一些噪音。这是我的代码:

#include "cv.h"
#include "highgui.h"

using namespace cv;

int main() {
    Mat imageBGR, imageHSV, planeH, planeS, planeV;

    imageBGR = imread("fruits.jpg");
    imshow("original", imageBGR);
    
    cv::Mat labels, data;
    cv::Mat centers(8, 1, CV_32FC1);
    imageBGR.convertTo(data, CV_32F);

    cv::kmeans(data, 8, labels,
            cv::TermCriteria(CV_TERMCRIT_ITER, 10, 1.0),
            3, cv::KMEANS_PP_CENTERS, &centers);
    imshow("posterized hue", data);
    data.convertTo(data, CV_32FC3);

    waitKey();
    return 0;
}

但我得到了一个奇怪的结果

第一张图片:原图

第二张图片:k 均值之后。

有什么建议吗?


更新:正确的解决方案。也许有人可以帮助我优化代码?

#include "cv.h"
#include "highgui.h"

#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat src;

    src = imread("fruits.jpg");
    imshow("original", src);

    blur(src, src, Size(15,15));
    imshow("blurred", src);

    Mat p = Mat::zeros(src.cols*src.rows, 5, CV_32F);
    Mat bestLabels, centers, clustered;
    vector<Mat> bgr;
    cv::split(src, bgr);
    // i think there is a better way to split pixel bgr color
    for(int i=0; i<src.cols*src.rows; i++) {
        p.at<float>(i,0) = (i/src.cols) / src.rows;
        p.at<float>(i,1) = (i%src.cols) / src.cols;
        p.at<float>(i,2) = bgr[0].data[i] / 255.0;
        p.at<float>(i,3) = bgr[1].data[i] / 255.0;
        p.at<float>(i,4) = bgr[2].data[i] / 255.0;
    }

    int K = 8;
    cv::kmeans(p, K, bestLabels,
            TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),
            3, KMEANS_PP_CENTERS, centers);

    int colors[K];
    for(int i=0; i<K; i++) {
        colors[i] = 255/(i+1);
    }
    // i think there is a better way to do this mayebe some Mat::reshape?
    clustered = Mat(src.rows, src.cols, CV_32F);
    for(int i=0; i<src.cols*src.rows; i++) {
        clustered.at<float>(i/src.cols, i%src.cols) = (float)(colors[bestLabels.at<int>(0,i)]);
//      cout << bestLabels.at<int>(0,i) << " " << 
//              colors[bestLabels.at<int>(0,i)] << " " << 
//              clustered.at<float>(i/src.cols, i%src.cols) << " " <<
//              endl;
    }

    clustered.convertTo(clustered, CV_8U);
    imshow("clustered", clustered);

    waitKey();
    return 0;
}

Result:


我不是 OpenCV 方面的专家,所以我会给出与你的问题相关的一般建议 K-means 需要向量列表,它本质上是一个矩阵:

[x0, y0, r0, g0, b0]
[x1, y1, r1, g1, b1]
[x2, y2, r2, g2, b2]
.
.
.

你给它的图像是行不通的。您首先必须将图像转换为这种 k 均值矩阵格式。对于源图像的每个像素,结果矩阵中都有一行。另请注意,您应该缩放这些值,以便它们都具有相似的值。如果不这样做,x 和 y 坐标通常会比颜色具有更高的“重力”,从而导致不令人满意的结果。 C++伪代码:

int pixel_index = 0;
for (int y = 0; y < image height; y++)  {
  for (int x = 0; x < image width; x++)  {
     matrix[pixel_index][0] = (float)x / image width;
     matrix[pixel_index][1] = (float)y / image height;
     matrix[pixel_index][2] = (float)pixel(x, y).r / 255.0f;
     matrix[pixel_index][3] = (float)pixel(x, y).g / 255.0f;
     matrix[pixel_index][4] = (float)pixel(x, y).b / 255.0f;
  }
}
// Pass the matrix to kmeans...

因此,您可以获得每个像素的标签,这些标签对应于它所分配到的簇。然后,您需要确定簇的颜色 - 这可能会有所不同,从获取中心像素颜色值到计算簇的平均/中值颜色。确定颜色后,只需遍历图像并将像素设置为其簇颜色:

for (int y = 0; y < image height; y++)  {
  for (int x = 0; x < image width; x++)  {
     int index = y * image width + x;  // This corresponds to pixel_index above
     int cluster_index = labels[index]; // 0 to 7 in your case
     Color color = colors[cluster_index];  // Colors is an array of 8 colors of the clusters
     image.setpixel(x, y, color)
  }
}

如果您更喜欢使用 HSV 而不是 RGB,只需使用 HSV 值而不是 RGB 值即可。

OpenCV 可能具有完全执行我上面描述的转换的函数,但我无法使用 Google 快速找到它们。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV 使用 k 均值对图像进行色调分离 的相关文章

  • boost::multi_index_container 复合键中的 equal_range 与比较运算符

    我正在尝试从多索引容器查询结果 其中值类型是三个元素的结构 第一个值已给出 但第二个和第三个值必须大于或小于查询参数 经过搜索后 我发现必须实现自定义密钥提取器 并且这里的一些链接建议相同 但我无法实现它 boost multi index
  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐

  • 如何绘制每个元素在列表中的次数[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在尝试做一些我认为并不困难的事情 但我不知道如何让 python matplotlib pylab 去做 给定一个输入 我想要一个直方
  • 如何在MessageBox中显示textBox控件?

    知道如何在 MessageBox 中显示 textBox 控件 我正在开发 winforms 项目 c 先感谢您 你不能 MessageBox 是一个特殊的容器 旨在仅显示消息和按钮 相反 您可以使用您想要的任何控件创建自己的表单 并使用
  • 这段代码中的 StringBuilder 变量线程安全吗?

    考虑下面的支柱Action类中 我正在使用StringBuilder执行方法中的变量 我的问题 变量是sb线程安全与否 public DemoAction extends Action public ActionForward execut
  • Chrome 23 中的 Vibration API 隐藏在哪里?

    根据一个post http peter sh 2012 08 key bindings for extensions and media streams for the web audio api 在 Peter Beverloo 的博客上
  • 使用 Swift 和 Cocoa 创建 nswindow 的正确方法

    通常我会使用此方法通过窗口控制器打开一个新窗口 class WindowTestController interface AppDelegate NSObject
  • 替换

    以前有人问过这个问题 但我从未见过足够的答案 是否有有效的替代品
  • 如何将数据库与微服务(以及新的)同步?

    我正在开发一个采用微服务架构的网站 每个服务都拥有一个数据库 数据库存储微服务所需的数据 Post Video服务需要用户信息 因此订阅的两个服务NEW USER EVENT The NEW USER EVENT当有新用户注册时将被触发 一
  • vi 退出后如何恢复终端内容?

    像 vi 或 man 或任何其他程序这样的程序如何用程序自己的内容替换终端内容 然后在退出这些程序后它们会带回旧的终端内容 Vi 翻转到终端支持的备用屏幕缓冲区 这是通过使用转义序列来实现的 看这个链接 http invisible isl
  • 从链表中删除最小值[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我需要从链表中删除最小的元素值 喜欢
  • 在地图周围绘制各州省份,并用德国邮政编码着色

    我正在尝试创建一张地图 在其中按德国邮政编码进行着色 并且我想添加德国各州作为边界 for loading our data library raster library readr library readxl library sf li
  • 如何从 GAC 加载程序集?

    我正在尝试使用 Assembly Load 加载 GAC 中的程序集 例如 假设我想列出存在于的所有类型演示核心 dll 我该如何加载演示核心 dll 当我尝试这个时 Assembly a Assembly Load Presentatio
  • MUI:如何以编程方式删除 DataGrid 中选定的行?

    我正在使用 MUI 创建文件列表DataGrid 用户可以选中复选框DataGrid做出他们的选择 我希望在用户执行某些操作 例如删除所选文件 后重置该复选框 我面临的问题是在执行删除操作后 该复选框仍然在同一位置被选中 例如 在我按下删除
  • 更改搜索栏拇指的大小

    我正在使用可绘制的搜索栏拇指 android thumb drawable thumb 我怎样才能设置这个拇指的大小dip单元 因为我使用类似搜索栏的样式 我想要拇指12dip高度和宽度 对我来说设置拇指大小的最灵
  • org.springframework.beans.factory.BeanCreationException:创建类路径资源中定义的名称为“scriptDataSourceInitializer”的bean时出错?

    我是学习 Spring Boot Web 的新手 我已经开始学习 spring jpa 数据 我使用 h2 数据库 我想使用插入测试数据 org springframework beans factory BeanCreationExcep
  • 仅显示 SQL 查询的前 N ​​行输出

    有没有办法只显示前 N 行输出SQL query 如果查询停止运行一次 则奖励积分N输出行 我最感兴趣的是找到适用于的东西Oracle 如果您指定您的目标数据库将会很有帮助 不同的数据库有不同的语法和技术来实现这一点 例如 在 Oracle
  • Git:如何排除存储库中的子文件夹?

    我已经在我的项目的文件夹中创建了一个存储库 你知道 git init 我有Webstorm文件夹 idea另一个与此无关的文件夹 我对保留在存储库中不感兴趣 并且我不希望此文件夹显示为要添加的新文件 我想忘记这些子文件夹 如何在提交整个存储
  • vertx 内的多线程

    我是 vert x 的新手 我正在尝试 vert x NetServer 功能 http vertx io core manual java html writing tcp servers and clients http vertx i
  • 下载 Fuchsia 源代码 - Jiri 钩子由于更新项目或包时出现致命错误而未运行

    Per 获取紫红色源代码 https fuchsia dev fuchsia src development source code echo PATH media cwh 32GB swdev fuchsia jiri root bin
  • 如何在 SQLite 中拥有自动时间戳?

    我有一个 SQLite 数据库版本 3 我正在使用 C 创建一个使用该数据库的应用程序 我想在表中使用时间戳字段来实现并发 但我注意到当我插入新记录时 该字段未设置 并且为空 例如 在 MS SQL Server 中 如果我使用时间戳字段
  • OpenCV 使用 k 均值对图像进行色调分离

    我想在 C 接口 cv 命名空间 中使用 k means 和 OpenCV 对图像进行色调分离 但得到了奇怪的结果 我需要它来减少一些噪音 这是我的代码 include cv h include highgui h using namesp