通过分析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导入 ...
随机推荐
- js 前端图片压缩+ios图片角度旋转
step1:读取选择的图片,并转为base64: function ImgToBase64 (e, fn) { // 图片方向角 //fn为传入的方法函数,在图片操作完成之后执行 var Orient ...
- 针对Eclipse的maven Missing artifact com.microsoft.sqlserver:slqjdbc4:jar:4.0
maven 中添加sqlserver 出错,报错内容 maven Missing artifact com.microsoft.sqlserver 解决方法这里先下载好jar包 ,然后maven命令执 ...
- CentOS7 修改网卡名称为eth0
前言 无论是RHEL 7.还是CentOS 7都使用了NetworkManager.service来进行网络管理,当然network服务还是可以继续使用的,但也将会是过渡期的残留品了. 除此之外7版本 ...
- 通过实例介绍持续集成的应用--基于Jenkins
1.测试工程师为什么要掌握持续集成 一个程序员如果想发布一个产品,他需要编码.编译.测试,发布的过程.对于一个企业来说,如果也想发布一个产品的话,同样的也是需要上述的过程,区别在于企业要发布的产品的需 ...
- Java经典编程题50道之二十三
给一个不多于5位的正整数,要求:①求它是几位数:②逆序打印出各位数字. public class Example23 { public static void main(String[] arg ...
- MysqL主主复制_模式之日志点复制
主主复制即在两台MySQL主机内都可以变更数据,而且另外一台主机也会做出相应的变更,可以起到一定的压力分担等作用. 测试两台虚拟机IP分别为: 192.168.136.131.192.168.136. ...
- dfs练习
不给提示,练习. 题意: 蒜头的数学实在是太差了,于是老师把他关到小黑屋让他闭门修炼.老师跟他一张纸,上面一排写着1, 2, 3...N这N个数,中间用空白分隔.老师让他在空白处填上加号或者减号.他让 ...
- Enable multi-tenancy on ironic
Multi-tenancy 是openstack ironic从Ocata版本开始支持的新特性,通过network-generic-switch插件控制交换机,Ironic可以实现在不同租户间机网络隔 ...
- nginx笔记2-负载均衡
负载均衡实现方式分为两类:1硬件类,2软件类. 硬件类:F5(这是一种硬件,并不是刷新啊,不要误解) 优点:非常快,可靠性高,并发量大.缺点:太贵,成本高,不方便,最致命的是不能将动态请求和静态请求 ...
- WireShark过滤解析HTTP/TCP
过滤器的使用: 可利用“&&”(表示“与”)和“||”(表示“或”)来组合使用多个限制规则, 比如“(http && ip.dst == 64.233.189.104) ...