在Java中用透明性着色灰度图像的合适方法是什么? - java

我正在制作一个化身生成器,其中化身组件来自具有透明性的PNG文件。这些文件是诸如body_1.png或legs_5.png之类的文件。透明性在零件周围,但不在零件内部,并且图像均为灰度。零件分层良好,我可以得到灰度头像。

我希望能够动态地为这些部分着色,但是到目前为止,我还没有好运。我曾尝试将像素数据从RGB转换为HSL,并使用原始像素的L值,同时提供新颜色的H值,但效果并不理想。

我看过Colorize grayscale image,但似乎无法使他所说的在Java中起作用。我最终得到的图像到处都有相当明亮的霓虹色。

我想要的是保留透明度,同时给灰度部分着色。黑色轮廓应仍为黑色,白色高光区域应仍为白色(我认为)。

有人有这样做的好方法吗?

编辑:

这是我可能要着色的图像:

再次,我想保持灰度图像的亮度水平(以便轮廓保持深色,可以看到渐变,白色斑块为白色)。

我已经能够使LookupOp在某种程度上基于Colorizing images in Java工作,但是颜色总是显得单调和暗淡。

这是我的输出示例:

使用的颜色是这种颜色(请注意亮度差异):http://www.color-hex.com/color/b124e7

这是我的查找

protected LookupOp createColorizeOp(short R1, short G1, short B1) {
    short[] alpha = new short[256];
short[] red = new short[256];
short[] green = new short[256];
short[] blue = new short[256];

//int Y = 0.3*R + 0.59*G + 0.11*B

    for (short i = 0; i < 30; i++) {
    alpha[i] = i;
        red[i] = i;
        green[i] = i;
        blue[i] = i;
}

for (short i = 30; i < 256; i++) {      
    alpha[i] = i;
    red[i] = (short)Math.round((R1 + i*.3)/2);
        green[i] = (short)Math.round((G1 + i*.59)/2);
        blue[i] = (short)Math.round((B1 + i*.11)/2);

    }


    short[][] data = new short[][] {
            red, green, blue, alpha
    };

    LookupTable lookupTable = new ShortLookupTable(0, data);
    return new LookupOp(lookupTable, null);
}

编辑2:我更改了LookupOp以使用以下内容,并获得了更好看的颜色:

red[i] = (short)((R1)*(float)i/255.0);
green[i] = (short)((G1)*(float)i/255.0);
blue[i] = (short)((B1)*(float)i/255.0);

参考方案

看来对您有用的是这样的:

for each pixel
    if pixel is white, black or transparent then leave it alone
    else
        apply desired H and S and make grayscale value the L
        convert new HSL back to RGB

编辑:看到您的图片后,我有几点评论:

似乎您要对较暗的色调进行特殊处理,因为您不会对30以下的任何颜色进行着色。按照相同的逻辑,您是否也应免于对较高的值进行着色?这样可以防止白人和近白人染上颜色。

您不应该同时设置alpha值和RGB。原始图像的Alpha值应始终保留。您的查询表算法应仅影响RGB。

当您说您尝试过HSL时,这不在您发布的代码中。您应该在HSL中进行着色,然后将查找表的结果颜色转换为RGB,因为这将保留原始的灰度亮度。您的查询表创建可能是这样的:

short H = ??; // your favorite hue
short S = ??; // your favorite saturation
for (short i = 0; i < 256; i++) {
    if (i < 30 || i > 226) {
        red[i] = green[i] = blue[i] = i; // don't do alpha here
    }
    else {
        HSL_to_RGB(H, S, i, red[i], green[i], blue[i])
    }
}

注意:您必须提供从HSL到RGB的转换功能。请参阅我对Colorize grayscale image的回答,以获取源代码的链接。

图像作为Int Array Java - java

我在用Java编写的网络摄像头应用程序中使用JMyron,该程序返回了网络摄像头视为int []的内容。由于每个int一个像素,它如何将像素的rgb值表示为一个int? 参考方案 一个int是32位。所以int的前8位是红色0-255,后8位是绿色0-255,后8位是蓝色0-255,后8位是alpha值0-255。这就是为什么它称为32位颜色。当我第一次连接…

Java:正则表达式模式匹配器是否有大小限制? - java

我的模式类似于OR:“word1 | word2 | word3”我大约有800个字。可能有问题吗? 参考方案 您仅受记忆和理智的限制。 :)

在Java中识别图像中的相似模式 - java

考虑到我有以下类型的图像,如何识别图像文件中的点。获得点的坐标后,我想连接几个点,例如制作一个正方形或三角形。什么方法是最好的呢?[编辑]:另外,我不知道点的数量,而且也不规则,就像在点之间存在线一样。 参考方案 您可以在图像的X * Y空间中运行卷积蒙版。蒙版将是图像上确切的7x7(或其他大小)点。您将通过否定像素来运行蒙版,无论蒙版的任何位置为您提供最暗…

Java-显式转换为char / short - java

谁能告诉我为什么即使short / char的大小均为16位,这种显式转换也会产生不同的结果?package jh; public class Main { public static void main(String[] args) { byte b = (byte)255; System.out.println("Size of short: …

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …