C# OpenCV机器视觉:颜色量化法提取主色

news/2025/2/13 4:47:21/

在热闹繁华的广告设计圈里,阿强是个怀揣无限创意,却总被颜色搭配折腾得焦头烂额的设计师。每次接到项目,面对那些色彩斑斓的素材图片,他就像迷失在彩色迷宫里的小可怜。

“哎呀呀,这么多颜色,到底哪个才是主色啊?我这眼睛都快要看花了!” 阿强对着电脑屏幕上的图片唉声叹气,头发被他抓得像个鸟窝。他尝试凭感觉挑主色,可结果要么平淡无奇,要么色彩冲突严重,客户的反馈总是不太理想。

直到有一天,阿强在一个技术交流论坛上,偶然发现了 OpenCvSharp 这个神奇的存在,还得知能用颜色量化的方法提取主色。“这不是我的救星来了嘛!” 阿强瞬间来了精神,眼睛瞪得像铜铃,仿佛看到了自己设计事业的转折点。

第一章:神秘 “魔法书” 登场 ——OpenCvSharp 降临

阿强迫不及待一头扎进 OpenCvSharp 的世界,这一探索可不得了,他发现这简直就是一本色彩魔法书,里面藏着无数让色彩乖乖听话的神奇咒语。

“哈哈,OpenCvSharp,你就是我苦寻已久的色彩魔法助手啊!” 阿强兴奋地自言自语,脑海里已经开始幻想自己成为色彩大师,在设计界呼风唤雨的场景。

阿强深入研究后得知,颜色量化就像给图像里的色彩小精灵们重新 “编排队列”。一幅图像往往有海量的颜色,就像一群吵吵闹闹、各自为政的小精灵,颜色量化就是把它们按相似程度分成几个大组,每个组里最具代表性的那个小精灵,就是我们要找的主色啦!这就好比把一群性格各异的小朋友,按兴趣爱好分成几个社团,每个社团的 “小团长” 就是主色。

第二章:准备施展 “魔法”—— 开启奇妙之旅

阿强决定拿一张棘手的广告图片 “开刀”,这张图片色彩复杂得像一团乱麻。他像个即将上战场的战士,在电脑上小心翼翼地安装 OpenCvSharp 库。

“小宝贝,你可要顺顺利利地安装好呀,可别给我捣乱。” 阿强一边点着鼠标,一边小声念叨。但安装过程就像一场惊险刺激的冒险,各种报错和依赖问题像小怪兽一样不断冒出来。阿强一会儿眉头紧皱,一会儿又对着屏幕嘟嘟囔囔,好在他凭借着顽强的毅力和在网上疯狂搜索资料,终于把这些小怪兽一一打败,成功安装好了 OpenCvSharp

“呼,总算是搞定了!” 阿强长舒一口气,擦了擦额头上的汗珠,脸上露出了胜利的笑容。他迫不及待地打开编程软件,准备大显身手。

第三章:代码冲锋 —— 念起主色提取的 “魔法咒语”

阿强深吸一口气,手指在键盘上飞舞起来,仿佛在编织一张神奇的魔法网。

using System;
using OpenCvSharp;
using System.Collections.Generic;class MainColorExtractor
{static void Main(){// 1. 读取图像Mat image = Cv2.ImRead("tricky_ad_image.jpg");if (image.Empty()){Console.WriteLine("哎呀妈呀,图像读取失败啦!是不是你把图片藏得太深,我找不到啦?快检查检查!");return;}// 2. 将图像转换为HSV颜色空间,HSV对颜色的感知更符合人类直觉Mat hsvImage = new Mat();Cv2.CvtColor(image, hsvImage, ColorConversionCodes.BGR2HSV);// 3. 颜色量化,这里简单地将每个通道量化为4个等级int quantizationLevels = 4;Mat quantizedImage = new Mat();QuantizeImage(hsvImage, quantizationLevels, quantizedImage);// 4. 统计量化后每种颜色的出现频率Dictionary<Vec3b, int> colorFrequency = new Dictionary<Vec3b, int>();for (int i = 0; i < quantizedImage.Rows; i++){for (int j = 0; j < quantizedImage.Cols; j++){Vec3b color = quantizedImage.At<Vec3b>(i, j);if (colorFrequency.ContainsKey(color)){colorFrequency[color]++;}else{colorFrequency[color] = 1;}}}// 5. 找出频率最高的前几种颜色作为主色,这里取3种int numDominantColors = 3;List<Vec3b> dominantColors = GetDominantColors(colorFrequency, numDominantColors);// 6. 显示结果ShowDominantColors(dominantColors);}static void QuantizeImage(Mat inputImage, int levels, Mat outputImage){inputImage.ConvertTo(outputImage, MatType.CV_32F);for (int i = 0; i < outputImage.Rows; i++){for (int j = 0; j < outputImage.Cols; j++){Vec3f color = outputImage.At<Vec3f>(i, j);color[0] = (float)Math.Floor(color[0] * levels / 180) * 180 / levels;color[1] = (float)Math.Floor(color[1] * levels / 255) * 255 / levels;color[2] = (float)Math.Floor(color[2] * levels / 255) * 255 / levels;outputImage.Set<Vec3f>(i, j, color);}}outputImage.ConvertTo(outputImage, MatType.CV_8U);}static List<Vec3b> GetDominantColors(Dictionary<Vec3b, int> colorFrequency, int numColors){var sortedColors = new SortedDictionary<int, Vec3b>(Comparer<int>.Create((x, y) => y.CompareTo(x)));foreach (var entry in colorFrequency){sortedColors[entry.Value] = entry.Key;}List<Vec3b> result = new List<Vec3b>();int count = 0;foreach (var entry in sortedColors){result.Add(entry.Value);count++;if (count >= numColors){break;}}return result;}static void ShowDominantColors(List<Vec3b> colors){// 创建一个新的图像来显示主色Mat colorPalette = new Mat(100, colors.Count * 100, MatType.CV_8UC3);for (int i = 0; i < colors.Count; i++){Mat colorBlock = new Mat(100, 100, MatType.CV_8UC3, colors[i]);Mat roi = colorPalette.SubMat(0, 100, i * 100, (i + 1) * 100);colorBlock.CopyTo(roi);}Cv2.ImShow("Dominant Colors", colorPalette);Cv2.WaitKey(0);Cv2.DestroyAllWindows();}
}

代码解析

  1. 图像读取:阿强用Cv2.ImRead方法去 “召唤” 图片,要是图片没 “召唤” 成功,程序就会像个小喇叭一样提醒他。这就好比邀请朋友来参加派对,如果朋友没来,那派对可就没法好好开始啦。
  2. 颜色空间转换:将图像转换为 HSV 颜色空间。HSV 空间就像是一个更懂人类心思的色彩翻译官,它把颜色分成色调(Hue)、饱和度(Saturation)和明度(Value)三个维度,这样我们能更直观地理解和处理颜色,就像把复杂的颜色语言翻译成了通俗易懂的大白话。
  3. 颜色量化:通过QuantizeImage方法进行颜色量化。在 HSV 的每个通道上,把颜色范围划分成quantizationLevels个等级 。这里设定为 4 个等级,就像把一个长长的跑道分成 4 段,每个像素的颜色就会被 “安排” 到对应的段落里。比如,原本连续变化的色调值,会被近似到 4 个固定的色调值之一。这一步大大减少了颜色的种类,把纷繁复杂的颜色世界变得简单有序。
  4. 统计颜色频率:遍历量化后的图像,用一个字典colorFrequency记录每种颜色出现的次数。这就像在班级里统计每个同学的考试成绩,看看哪个分数段的同学最多。
  5. 找出主色:在GetDominantColors方法里,把记录颜色频率的字典按频率从高到低排序,然后取出频率最高的前几种颜色作为主色。这里取 3 种,就像在班级里找出成绩最好的 3 个同学,他们就是主色的代表。
  6. 结果显示:阿强用ShowDominantColors方法把找到的主色展示出来。他创建了一个新的图像,把每个主色都变成一个小方块,整齐地排列在一起,就像一个色彩拼盘,这样他就能一目了然地看到自己辛苦找到的主色啦。

第四章:成功时刻 —— 魔法生效,主色现形

阿强紧张地按下运行键,眼睛死死地盯着屏幕,大气都不敢出。当屏幕上清晰地出现一排鲜艳的主色色块时,阿强一下子从椅子上弹了起来。

“哇塞,成功啦!我就知道我能行!” 阿强兴奋地在办公室里手舞足蹈,像个中了彩票的孩子。

他迫不及待地把这个好消息分享给同事们,同事们都围过来,看着屏幕上的主色,纷纷竖起大拇指。

“阿强,你太牛了吧!这主色找得太准了!”
“是啊是啊,阿强,快教教我们怎么做到的!”

从那以后,阿强凭借这个神奇的主色提取方法,设计作品越来越出色。客户们看到他的设计方案,都赞不绝口,订单像雪花一样飞来。

阿强知道,这只是他在色彩魔法世界的第一步,他还要继续探索 OpenCvSharp 更多的神奇功能。他相信,只要不断学习,自己一定能成为真正的色彩魔法大师,在设计的舞台上大放异彩。


http://www.ppmy.cn/news/1571612.html

相关文章

【论文笔记】Are Self-Attentions Effective for Time Series Forecasting? (NeurIPS 2024)

官方代码https://github.com/dongbeank/CATS Abstract 时间序列预测在多领域极为关键&#xff0c;Transformer 虽推进了该领域发展&#xff0c;但有效性尚存争议&#xff0c;有研究表明简单线性模型有时表现更优。本文聚焦于自注意力机制在时间序列预测中的作用&#xff0c;提…

华硕笔记本怎么一键恢复出厂系统_华硕笔记本一键恢复出厂系统教程

华硕笔记本怎么一键恢复出厂系统&#xff1f; 华硕一键恢复出厂系统是一个安全、高效、方便的恢复方式&#xff0c;让您轻松还原出厂设置&#xff0c;以获得更好的系统性能。如果您的华硕电脑遇到问题&#xff0c;可以使用华硕一键恢复出厂系统功能。下面小编就教大家华硕笔记本…

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_show_version_info函数

声明 在 nginx.c 开头 static void ngx_show_version_info(void); 实现 static void ngx_show_version_info(void) {ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);if (ngx_show_help) {ngx_write_stderr("Usage: nginx [-?hvVtTq] [-s s…

Expo运行模拟器失败错误解决(xcrun simctl )

根据你的描述&#xff0c;问题主要涉及两个方面&#xff1a;xcrun simctl 错误和 Expo 依赖版本不兼容。以下是针对这两个问题的解决方案&#xff1a; 解决 xcrun simctl 错误 错误代码 72 通常表明 simctl 工具未正确配置或路径未正确设置。以下是解决步骤&#xff1a; 确保 …

Python进阶-在Ubuntu上部署Flask应用

随着云计算和容器化技术的普及&#xff0c;Linux 服务器已成为部署 Web 应用程序的主流平台之一。Python 作为一种简单易用的编程语言&#xff0c;适用于开发各种应用程序。本文将详细介绍如何在 Ubuntu 服务器上部署 Python 应用&#xff0c;包括环境准备、应用发布、配置反向…

机器学习周报-文献阅读

文章目录 摘要abstract 1 文献内容1.1 具有并行架构的混合深度学习模型1.2 时域卷积网络(TCN)1.3 长短期记忆神经网络(LSTM)1.4 Tensor concatenate module 2 实验2.1 数据处理2.2 评估指标2.3 实验结果 3 Savitzky-Golay滤波器(SG filter)4 代码总结 摘要 本周阅读了一篇基于…

ASP.NET Core WebSocket、SignalR

目录 WebSocket SignalR SignalR的基本使用 WebSocket WebSocket基于TCP协议&#xff0c;支持二进制通信&#xff0c;双工通信。性能和并发能力更强。WebSocket独立于HTTP协议&#xff0c;不过我们一般仍然把WebSocket服务器端部署到Web服务器上&#xff0c;因为可以借助HT…

SQLServer的创建,表创建,主键,约束,模糊查询

设置 注意: 设置完成之后 重新启动 创建数据库 注意: 这个目标路径必须要有该文件名的文件夹 -- 指向 master 数据库&#xff0c;告诉它我们要创建一个新的数据库操作了 use master go-- 创建数据库 create database StudentManageDB on primary (-- 以下四个组成部分缺一不可…