Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image processing 如何将位图还原为一组已知的RGB颜色_Image Processing_Bitmap_Rgb - Fatal编程技术网

Image processing 如何将位图还原为一组已知的RGB颜色

Image processing 如何将位图还原为一组已知的RGB颜色,image-processing,bitmap,rgb,Image Processing,Bitmap,Rgb,对于一个爱好项目,我将构建一个程序,当给定一个图像位图时,它将创建一个PDF格式的十字绣图案。我将在Mac上使用Cocoa/Objective C 源位图通常为24bpp图像,但在数百万种可用颜色中,只有少数颜色是十字绣线。线程有多种类型。DMC是最广泛可用的,几乎其整个范围可从各种网站获得RGB值,比如说 DMC# Name R G B ----- ------------------ --- --- --- blanc White

对于一个爱好项目,我将构建一个程序,当给定一个图像位图时,它将创建一个PDF格式的十字绣图案。我将在Mac上使用Cocoa/Objective C

源位图通常为24bpp图像,但在数百万种可用颜色中,只有少数颜色是十字绣线。线程有多种类型。DMC是最广泛可用的,几乎其整个范围可从各种网站获得RGB值,比如说

DMC#  Name               R   G   B
----- ------------------ --- --- ---
blanc White              255 255 255
208   Lavender - vy dk   148  91 128
209   Lavender - dk      206 148 186
210   Lavender - md      236 207 225
211   Lavender - lt      243 218 228
      ...etc...
在我看来,我的第一个问题是从图像中像素的RGB起点选择DMC集合中最接近的颜色。从数学上找到最接近的DMC颜色,并确保其与颜色紧密匹配的最佳方法是什么

尽管我将使用Cocoa,但在您发布的任何代码中都可以随意使用伪代码(甚至Java!)。

这就是所谓的伪代码,并且有许多可用的算法

一个非常基本的方法是将RGB颜色视为空间中的点,并使用颜色之间的普通欧几里得距离来计算它们的“接近程度”。这有缺点,因为人眼在这个空间的不同位置有不同的敏感度,所以这样的距离与人类感知颜色的方式不太相符。您可以使用各种权重方案来改善这种情况。

使用颜色空间并找到最接近的颜色。在RGB颜色空间中执行此操作将产生违反直觉的结果。(或使用颜色空间。)

因此,只需在每个像素上迭代,并在您选择的颜色空间中找到距离最近的颜色。请注意,对于某些颜色空间(例如使用色调的颜色空间),必须循环计算距离

(大多数颜色量化都是围绕着选择调色板展开的,但在您的案例中已经考虑到了这一点,因此您不能使用更流行的量化技术。)

还有,看看

要找到可可中的HSB色调,您可以使用


但是,如果您只是使用此技术将图像转换为十字绣设计,实际缝合将非常困难。它将充满单像素颜色字段,哪种类型会破坏交叉缝合的目的。

从实用程序集中获取
ppmquant
应用程序的源代码

根据颜色操作正确性的相关性,记住要考虑。虽然我对此有所研究,但由于我的摄影爱好,我仍然对一切都有点困惑

但是,如前所述,尽可能多地使用LAB,因为(afaik)它的颜色空间不可知,而所有其他方法(RGB/HSL/CMYK)在没有定义的颜色空间的情况下(理论上)毫无意义

例如,RGB仅为三个百分比值(0-255=>0-100%,具有8位颜色深度)。因此,如果您有一个RGB三元组(0255,0),它将转换为“只有绿色,并且尽可能多”。所以,问题是“红色是多少?”。这是颜色空间回答的问题-100%绿色并不像100%绿色那样绿色。甚至都不一样


对不起,如果这是离题的话

其他人已经指出了各种颜色量化技术。可以使用马尔可夫随机场等技术来惩罚在相邻像素位置切换线程颜色的系统。有一些通用的多标签MRF库,包括

要使用其中一种,数据元素将是输入颜色,标签将是线程颜色集,数据项可能类似于bzlm建议的实验室空间中的欧几里德距离,邻域项将惩罚线程颜色的切换。

Interresting…:)

您不仅要识别最近的颜色,还需要减少使用的颜色数量。你不想以使用数百种不同颜色的缝合图案结束

我编写了一些代码,可以在基本级别上实现这一点。(很抱歉,它是用C#写的,我希望它还是有用的。)

当然,在该方法正常工作之前,还需要做一些进一步的调整。GetDistance方法将色调、饱和度和亮度的重要性相互加权,找到它们之间的最佳平衡对于找到最接近的颜色当然很重要

使用减少调色板的方法也可以做很多事情。在本例中,我只选择了最常用的颜色,但您可能希望根据调色板中颜色的相似程度来确定权重。这可以通过拾取最常用的颜色,根据与拾取颜色的距离减少列表中剩余颜色的计数,然后使用列表来完成

保存DMC颜色的Hsl类可以计算到另一种颜色的距离,并在颜色列表中找到最近的颜色:

public class Hsl {

    public string DmcNumber { get; private set; }
    public Color Color { get; private set; }
    public float Hue { get; private set; }
    public float Saturation { get; private set; }
    public float Brightness { get; private set; }
    public int Count { get; set; }

    public Hsl(Color c) {
        DmcNumber = "unknown";
        Color = c;
        Hue = c.GetHue();
        Saturation = c.GetSaturation();
        Brightness = c.GetBrightness();
        Count = 0;
    }

    public Hsl(string dmc, int r, int g, int b)
        : this(Color.FromArgb(r, g, b))
    {
        DmcNumber = dmc;
    }

    private static float AngleDifference(float a1, float a2) {
        float a = Math.Abs(a1 - a2);
        if (a > 180f) {
            a = 360f - a;
        }
        return a / 180f;
    }

    public float GetDistance(Hsl other) {
        return
            AngleDifference(Hue, other.Hue) * 3.0f +
            Math.Abs(Saturation - other.Saturation) +
            Math.Abs(Brightness - other.Brightness) * 4.0f;
    }

    public Hsl GetNearest(IEnumerable<Hsl> dmcColors) {
        Hsl nearest = null;
        float nearestDistance = float.MaxValue;
        foreach (Hsl dmc in dmcColors) {
            float distance = GetDistance(dmc);
            if (distance < nearestDistance) {
                nearestDistance = distance;
                nearest = dmc;
            }
        }
        return nearest;
    }

}
公共级Hsl{
公共字符串DmcNumber{get;private set;}
公共颜色{get;private set;}
公共浮点色调{get;private set;}
公共浮点饱和{get;private set;}
公共浮点亮度{get;private set;}
公共整数计数{get;set;}
公共Hsl(c色){
DmcNumber=“未知”;
颜色=c;
色调=c.GetHue();
饱和度=c.GetSaturation();
亮度=c.GetBrightness();
计数=0;
}
公共Hsl(字符串dmc、整数r、整数g、整数b)
:此(颜色来源于argb(r,g,b))
{
DmcNumber=dmc;
}
专用静态浮动角度差(浮动a1、浮动a2){
浮点数a=数学绝对值(a1-a2);
如果(a>180f){
a=360f-a;
}
返回a/180f;
}
公共浮动距离(Hsl其他){
返回
角度差(色调、其他色调)*3.0f+
数学Abs(星期六)
Hsl[] dmcColors = {
    new Hsl("blanc", 255, 255, 255),
    new Hsl("310", 0, 0, 0),
    new Hsl("317", 167, 139, 136),
    new Hsl("318", 197, 198, 190),
    new Hsl("322", 81, 109, 135),
    new Hsl("336", 36, 73, 103),
    new Hsl("413", 109, 95, 95),
    new Hsl("414", 167, 139, 136),
    new Hsl("415", 221, 221, 218),
    new Hsl("451", 179, 151, 143),
    new Hsl("452", 210, 185, 175),
    new Hsl("453", 235, 207, 185),
    new Hsl("503", 195, 206, 183),
    new Hsl("504", 206, 221, 193),
    new Hsl("535", 85, 85, 89)
};

Bitmap image = (Bitmap)Image.FromFile(@"d:\temp\pattern.jpg");

// count colors used
List<Hsl> usage = new List<Hsl>();
for (int y = 0; y < image.Height; y++) {
    for (int x = 0; x < image.Width; x++) {
        Hsl color = new Hsl(image.GetPixel(x, y));
        Hsl nearest = color.GetNearest(dmcColors);
        int index = usage.FindIndex(h => h.Color.Equals(nearest.Color));
        if (index != -1) {
            usage[index].Count++;
        } else {
            nearest.Count = 1;
            usage.Add(nearest);
        }
    }
}

// reduce number of colors by picking the most used
Hsl[] reduced = usage.OrderBy(c => -c.Count).Take(5).ToArray();

// convert image
for (int y = 0; y < image.Height; y++) {
    for (int x = 0; x < image.Width; x++) {
        Hsl color = new Hsl(image.GetPixel(x, y));
        Hsl nearest = color.GetNearest(reduced);
        image.SetPixel(x, y, nearest.Color);
    }
}

image.Save(@"d:\temp\pattern.png", System.Drawing.Imaging.ImageFormat.Png);