通过分析HSL/HSB获取图片主色调
这两天稍微研究了一下颜色的HSL/HSB值,主要因为写程序想要实现通过一张图片拿到图片中的最突出的颜色值(类似Groove Music中播放栏背景就是从专辑封面中取出主色调,还有Windows 10任务栏也可以从桌面背景获取主色调作为主题颜色)。
网上搜索了一下并没有满意的解决办法,于是自己小小的研究了一下,最后效果还算可以啦。



开始的时候想通过分析ARGB来获取,可以说是一头雾水,因为ARGB的组合实在是多,而且我也不清楚组合以后出来的颜色到底有什么规律,所以没过多久就放弃了。
之后决定用HSL/HSB的方式来获取主色调,之前只是了解有这个模式,并没有具体研究过H、S、B分别表示什么,然后小小的学习了一下,收获很大,RGB的模式对于计算机来说很简单,但是对于人类来说就很不友好了,毕竟我们是感性的动物,而HSL/HSB模式就很好理解了,Hue代表色调,范围0-360°,代表了各种颜色(没有白色和黑色,大家应该都知道白色和黑色并不是颜色~),Saturation代表饱和度,范围0-1,饱和度为0那么颜色就是真了,所有的颜色都将变为灰色,Brightness/Lightness代表亮度,范围0-1,这两个之间是有区别的,Brightness为0的话就是黑色(没有光当然是漆黑一片了),为1的话是某种颜色最亮的状态。而Lightness为0的时候也是黑色,但是为1的时候就是白色了(我觉得可以这样认为,光强超过了物体吸收光波的极限,所有的光都反射了回来,所以你看到的就是一片白色啦,对眼睛伤害很大,所以阳光很足的时候不要老在外面待着哦),Lightness为0.5对应了Brightness为1的状态,所以我认为Lightness是Brightness在数值上的延伸而已。总只Wiki上Copy来两张图就解释一切啦!

至于HSB/HSL与ARGB之间具体的转换关系就没有深入研究了,公式都有,深入研究就算了,毕竟头发宝贵……
看到网上都是再拿Hue来做文章,毕竟Hue代表了色调,开始我也这样认为,觉得拿到图片的所有像素,统计一下Hue在哪个颜色范围最多,然后就取这个色调颜色的均值好了,结果发现如果图片的颜色不多还好,如果颜色复杂的话,并不是很容易就能拿到想要的颜色,而且很容易把图片的背景色错认为图片的主色调,想了很多的方法,都觉得不能满足所有的情况,比如有的时候背景色占的面积很大,有时候很小,或者图片就一种颜色,或者颜色很多,这样的话可能需要分类讨论的情况很多,很复杂,最重要的是自己的数学真的不足以支持那么复杂的运算,高数线代什么的早都还给老师了,还是那句话,头发宝贵啊....
然后又经历了一个晚上的不眠之夜,早上起来班车上突然灵感来了,哈哈,觉得真的是想复杂了,入手点不应该从Hue出发,而是从另外两个值来搞事情,Saturation和Brightness,很简单,怎么样定义主色调?很简单,就是看一张图片我们第一眼就关注到的颜色,这样的颜色只需要满足两个条件,饱和度最大并且亮度最大,也就是最鲜艳的颜色,注意这里其实也是有个小问题的,有一个颜色喜好的问题,就想看红绿灯,虽然红绿黄三种颜色都是纯色,他们的饱和度和亮度都是1,但是最能引起我们注意的还是红色,而对于不同的颜色,我觉得每个人最先分辨的颜色可能也是不一样的……那么这个问题,我就不解决了,大神可以自己研究一下,我的做法相当的简单,拿到一组饱和度+亮度的值最大的颜色(可能还涉及到权重,我也不管这个,直接相加),这组颜色可能是很多色调的组合,那就说明这张图上我们第一眼可能看到的颜色有多种,那么拿到这些颜色,可以随机取一种或者进行某种运算,我的话就直接取均色好了,我觉得这样也不错。然后最终效果就是最上面的两张图,我自己是满意了,而且这样处理直接会去掉白色和黑色,除非图上只有这两种颜色。
以上完全是个人想法,请轻喷……
最后要吐槽一下微软,C#里面获取亮度的方法是GetBrightness,看名字觉得应该是采用HSB的颜色模式,结果写完代码一看傻眼了,所有图片拿到的都是白花花的一片,才意识到可能微软用的是HSL的模式,写了个小程序测试了一下,果然,纯色的Brightness都是0.5,而白色的Brightness为1,NM真的是坑啊,要不你就换成GetLightness好不好???


最后附代码,直接来一发拓展方法(刚刚跟猛哥那学来没多久,当然要多用一用),其实代码不重要,重要的是思路,如果大家有更好的想法,欢迎分享给我啦
(WPF的话还简单点,UWP取图片的像素点还是有点小麻烦的)
static class ExtensionMethod
{
public static double GetHue(this Color color)
{
return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).GetHue();
} public static double GetSaturation(this Color color)
{
return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).GetSaturation();
} public static double GetBrightness(this Color color)
{
return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).GetBrightness();
} public async static Task<Color> GetMajorColorAsync(this BitmapImage bitmap)
{
var random = RandomAccessStreamReference.CreateFromUri(bitmap.UriSource);
var stream = await random.OpenReadAsync();
var decoder = await BitmapDecoder.CreateAsync(stream);
var data = await decoder.GetPixelDataAsync();
var bytes = data.DetachPixelData();
var colors = new List<Color>();
for (int i = ; i < bytes.Length; i += )
{
colors.Add(Color.FromArgb(bytes[i + ], bytes[i + ], bytes[i + ], bytes[i]));
}
colors = colors.GroupBy(c => - c.GetSaturation() + Math.Abs(0.5 - c.GetBrightness())).OrderBy(g => g.Key).FirstOrDefault().ToList();
var color = Color.FromArgb(Convert.ToByte(colors.Average(c => c.A)), Convert.ToByte(colors.Average(c => c.R)), Convert.ToByte(colors.Average(c => c.G)), Convert.ToByte(colors.Average(c => c.B)));
return color;
}
}
终于写完了,每天进步一点点,Get√
通过分析HSL/HSB获取图片主色调的更多相关文章
- iOS UIImage:获取图片主色调
本文转载至 http://www.wahenzan.com/a/mdev/ios/2015/0325/1677.html -(UIColor*)mostColor{ #if __IPHONE_OS_V ...
- UWP取出图片主色调
一切都要从风车动漫的新详情页说起... 当我最初拿到风车动漫新详情页的UI设计概念图时,新详情页中有两点: 1.图片的高斯模糊 2.取出图片的主色调(主要用于tag和相关动漫的标题背景) 大概就是要这 ...
- JS快速获取图片宽高的方法
快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器. 我们一步一 ...
- php 获取图片主要颜色的方法
本文章向码农们介绍php 获取图片主要颜色的方法,主要涉及php针对图片的相关操作技巧,需要的码农可以参考一下. $i = imagecreatefromjpeg("image.jpg&qu ...
- 转载:JS快速获取图片宽高的方法
快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器. 我们一步一 ...
- Android--从系统Camera和Gallery获取图片优化
前言 之前有两篇博客讲解了如何从系统内已有的Camera和Gallery应用中获取图片的例子,看到评论里有朋友说有时候会报错,导致程序崩溃的问题.本篇博客主要就这个问题分析讲解一下,最后将以一个简单的 ...
- 解决获取图片实际尺寸(宽高)的bug
需求:获取图片的宽高其实是为了预先做好排版样式布局做准备. 可以利用图片onload事件监听获取图片的宽高属性值.在IE9以下版本只能使用图片的width与height属性,HTMl5中新加入了nat ...
- js获取图片信息(一)-----获取图片的原始尺寸
如何获取图片的原始尺寸大小? 如下,当给 img 设置一个固定的大小时,要怎样获取图片的原始尺寸呢? #oImg{ width: 100px; height: 100px; } <img src ...
- 使用AI技术获取图片文字与识别图像内容
获取图片文字 如何使用python获取图片文字呢? 关注公众号[轻松学编程]了解更多- 1.通过python的第三方库pytesseract获取 通过pip install pytesseract导入 ...
随机推荐
- 通过WMI获取机器信息
PerformanceCounter的介绍就不多说了,MSDN上介绍的很详细: https://msdn.microsoft.com/zh-cn/library/system.diagnostics. ...
- WPF项目学习.二
WPF用MVVM的解决记录 版权声明:本文为博主初学经验,未经博主允许不得转载. 一.前言 记录在学习与制作WPF过程中遇到的解决方案. 焦点的控制,键盘事件触发,输入框的数字限制,异步处理,隐藏状 ...
- css的浮动与定位
显示与隐藏 标签 属性 值 效果 区别 css的style display none 元素不可见 不占页面空间 css的style visibility hidden 元素不可见 占页面空间 disp ...
- 关于对MVC和MVVM的思考
前言:最近公司交给我一个web项目,其采用的框架是java中的zkoss,它不用于以往我平时用的mvc,它采用的mvvm模式,因为以前只理解过mvc,经常使用譬如SpringMvc.Struts2等框 ...
- git使用步骤_2017
(部署项目) zbot deploy developer git对文件chmod 777后导致status发生变化,使用: git config core.fileMode false [当 ...
- Java GC分析记录
Java GC记录 近来.项目没有特别忙碌的时候,抽空看了下生产环境的项目运行状况,我们的项目一直运行速度不是很快,偶尔会出现卡顿的现象,这点给人的体验感觉也就不那么好了.先抛个测试环境截图(生产环境 ...
- HDU - 1584 IDA*
思路:裸的IDA*,估计当前状态至少需要多少距离才能达到目标状态,剪枝即可.每一墩牌只需记录其最上面和最下面的牌型即可完成移动. AC代码 #include <cstdio> #inclu ...
- HDU - 3001 Travelling 状压dp + 三进制 [kuangbin带你飞]专题二
终于刷完搜索专题了. 题意:给定n个城市,每个城市参观不能超过两次,两个城市之间有道路通过需要花费X,求通过能所有城市的最小花费. 思路:每个城市有三个状态0,1,2,可用三进制存储所有城市的访问状态 ...
- shell脚本中 杀死可能成为僵尸进程的方法
交互式 Bash Shell 获取进程 pid 在已知进程名(name)的前提下,交互式 Shell 获取进程 pid 有很多种方法,典型的通过 grep 获取 pid 的方法为(这里添加 -v gr ...
- Servlet Cookie取不到值原因
现象: 在测试带Cookie的HTTP请求时发现,服务端用request.getHeader("cookie")可以去到值; 但是用request.getCookies()却不行 ...