C# 或 WPF 中如何判断两个颜色是否近似

C# 或 WPF 中如何判断两个颜色是否近似

独立观察员 2023 年 5 月 13 日

0b967e64d24cbf062a981e195f594845.png

一、算法

对于这种算法问题,直接询问 ChatGPT 是最快的:

6fb4c1944de0619a1f7a673143624bdb.png

也就是说有两种方法,一是计算两个颜色的 RGB 分量差之和,二是计算两个颜色的欧几里得距离,然后两者都是与给定的阈值进行比较,小于阈值即可认为是近似的。

本次主要用于 WPF,同时为了便于测试 Demo 的使用,我把 ChatGPT 给的方法整理了一下:

https://gitee.com/dlgcy/WPFTemplateLib/blob/master/WpfHelpers/MediaColorHelper.cs

using System;
using System.Windows.Media;
/*
 * 源码己托管: https://gitee.com/dlgcy/WPFTemplateLib
 * 版本:2023年5月13日
 */
namespace WPFTemplateLib.WpfHelpers
{
    /// <summary>
    /// 媒体颜色帮助类
    /// </summary>
    public class MediaColorHelper
    {
        #region 相似比较


        /// <summary>
        /// [ChatGPT] 计算两个颜色之间的欧几里得距离(即两个颜色在 RGB 空间中的距离)
        /// </summary>
        public static double ColorDistance(Color color1, Color color2)
        {
            int rDiff = color1.R - color2.R;
            int gDiff = color1.G - color2.G;
            int bDiff = color1.B - color2.B;


            return Math.Sqrt(rDiff * rDiff + gDiff * gDiff + bDiff * bDiff);
        }


        /// <summary>
        /// [ChatGPT] 判断两个颜色是否近似(使用 两个颜色之间的欧几里得距离 与 给定阈值 进行比较,如果距离小于指定的阈值,则认为这两个颜色近似)
        /// </summary>
        public static bool AreColorsSimilar1(Color color1, Color color2, double threshold = 26)
        {
            double distance = ColorDistance(color1, color2);
            return distance <= threshold;
        }


        /// <summary>
        /// 获取两个颜色的 RGB 分量差之和
        /// </summary>
        public static int ColorSumOfComponentDifferences(Color color1, Color color2)
        {
            int rDiff = Math.Abs(color1.R - color2.R);
            int gDiff = Math.Abs(color1.G - color2.G);
            int bDiff = Math.Abs(color1.B - color2.B);
            return rDiff + gDiff + bDiff;
        }


        /// <summary>
        /// [ChatGPT] 判断两个颜色是否近似(判断两个颜色的 RGB 分量差之和是否小于指定的阈值,如果小于则认为这两个颜色近似)
        /// </summary>
        /// <param name="color1"></param>
        /// <param name="color2"></param>
        /// <param name="threshold"></param>
        /// <returns></returns>
        public static bool AreColorsSimilar2(Color color1, Color color2, int threshold = 45)
        {
            int sum = ColorSumOfComponentDifferences(color1, color2);
            return sum <= threshold;
        }


        #endregion


        #region 媒体颜色转换


        /// <summary>
        /// System.Drawing.Color 转 System.Windows.Media.Color
        /// </summary>
        /// <returns><see cref="Color"/> 对象,转换失败返回透明色</returns>
        public static Color DrawingColorToMediaColor(System.Drawing.Color drawingColor)
        {
            try
            {
                return (Color)ColorConverter.ConvertFromString(drawingColor.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return Colors.Transparent;
            }
        }


        /// <summary>
        /// 从颜色字符串(支持RGB和ARGB)转换为媒体颜色
        /// </summary>
        /// <param name="colorStr">ARGB颜色字符串(如#FF000000、#000000)</param>
        /// <returns><see cref="Color"/> 对象,转换失败返回透明色</returns>
        public static Color ColorStrToMediaColor(string colorStr)
        {
            try
            {
                return (Color)ColorConverter.ConvertFromString(colorStr);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return Colors.Transparent;
            }
        }


        #endregion
    }
}

至于 C# 版,是一模一样的,只不过颜色对象的命名空间不同而已。WPF 是 System.Windows.Media.Color 媒体颜色,而 C# 是 System.Drawing.Color 绘图颜色。

C# 的绘图颜色帮助类可在如下地址获取:

https://gitee.com/dlgcy/dotnetcodes/blob/dlgcy/DotNet.Utilities/%E9%A2%9C%E8%89%B2/DrawingColorHelper.cs

二、测试程序

在本人的 DLGCY_WPFPractice 项目中添加了一个测试窗口:

6659784dcb6ef96cb79e599652cafb54.png

窗口上放了两个 HandyControl 的 ColorPicker 颜色选择器控件,选择后(不需要点击确定)会在下方 “方法一” 和 “方法二” 标签前面分别显示 颜色 1 和 颜色 2,方便肉眼近距离比较。方法一比较阈值和两个颜色的欧几里得距离,方法二比较阈值和两个颜色的 RGB 分量差之和,两者的阈值都可以在界面上设置,结果显示在最后面。

推荐使用连续模式,拖动任何一个颜色,底下的所有数据包括比较结果都能实时变动。

三、阈值说明

算法是确定的,但是阈值是不确定的,ChatGPT 也是这样说的:

4b1aca61318e05fe6b0ae664c6450bb2.png

本次制作这个测试程序的初衷也是为了方便找到一个合适的阈值,当然,这个 “合适” 是针对具体需求来说的,换一个需求场景,阈值也需要跟着变换,这时这个测试程序就能派上用场了。

在帮助类中,我给方法一设置了默认阈值为 26,给方法二设置了默认阈值为 45:

f05a53d683493a51abadcb2fbd110071.png

如果你只是粗略判断,或者不知道什么阈值合适,可以直接使用默认阈值,调用时就不用传具体阈值数值了:

c5530c31aceb2103c71db5942526a1b4.png

另外,无论怎么调整阈值,几乎总能找到一对颜色,让两个方法一个判定为相似,另一个判定为不相似。而且两个方法到底哪个好,目前没有结论。所以在实际使用时,不用纠结用哪个方法,挑一个你觉得顺眼的,然后选好一个阈值,一直用下去就行了。

以下是一些示例:

512ca04d995184ff6bad54afb433f230.png

8b196a2930a5b31804ab6d20fc1c619c.png

3bd7efc34c6fbe165673b0f43356339b.png

四、资源

1、颜色比较帮助类:(见第一节)

2、包含此帮助类的 NuGet 包:[WPFTemplateLib](https://www.nuget.org/packages/WPFTemplateLib/)

3、示例程序代码:https://gitee.com/dlgcy/DLGCY_WPFPractice/tree/Blog20230513

4、示例程序 获取方法:

在微信公众号 “独立观察员博客(DLGCY_BLOG)” 消息框回复 “WPFPractice” 获取。

原创文章,转载请注明: 转载自 独立观察员 (dlgcy.com)

本文链接地址:[C# 或 WPF 中如何判断两个颜色是否近似](http://dlgcy.com/how-to-determine-two-color-is-similar-in-csharp-or-wpf/)

-

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值