gpt4 book ai didi

java - 需要有关调色板颜色量化 : java - Android 的帮助

转载 作者:搜寻专家 更新时间:2023-10-31 20:10:14 24 4
gpt4 key购买 nike

我正在 Android 上开发一个项目,这要求我最多过滤 5 种不同的颜色 - 包括背景颜色(近似白色)。我不能使用高级数学算法,因为我不知道太多的数学(我会完全迷失),但是通过一些简单的逻辑算法,我部分通过反复试验推导出来,部分逻辑,我已经能够结果可以达到 70%。但我需要有关如何使其 100% 工作的建议。

为了测试该算法,我用 4 支不同颜色的笔在纯白色(第 5 种颜色)纸上随意乱写了单词/字母,并编写了一些代码来解码颜色。所以在代码中算法......

  • 如果红色笔墨水像素被解码,像素被设置为数字红色
  • 如果解码蓝色钢笔墨水像素,则像素设置为数字蓝色
  • 如果绿色钢笔墨水像素被解码,像素被设置为数字绿色
  • 如果黑色笔墨像素被解码,像素被设置为数字黄色

  • 黑色墨水像素设置为数字黄色(不是黑色,因为在视觉上很难将黑色与墨水黑色区分开来)。

    我的代码在下面,但首先这里是我得到的最好的结果之一。如您所见,黑色(由数字黄色表示)和红色(由数字红色表示)之间的边缘有重叠。就像我说的,我的代码部分是逻辑部分,部分是反复试验。

    我的第一个问题是如何改进这个算法以完美地解码/过滤颜色(我选择这个方法是因为我很快就会迷失在非常复杂的数学中)?

    其次,我怎样才能使它适用于不同色调的光(白光、
    黄灯……)?

    编辑:经过进一步的评论和讨论,我意识到我需要的帮助是调色板颜色量化 Adroid java 代码示例,谢谢

    Undecoded Original image

    Decoded image, almost but not good enough
    if(  (Blue > Green) &&(Red > Blue) && (Red - Green) > 25 )
    copyOfBM.setPixel(x, y, Color.RED); //red
    else if( (Blue > Red) && ( (Blue > Green)) )
    copyOfBM.setPixel(x, y, Color.BLUE);
    else if( (Green >= 82) && ((Green - Blue) >= 12) &&
    ((DecodeLuminaceColor( x, y, copyOfBM )>= 82 ) &&
    (DecodeLuminaceColor( x, y, copyOfBM )< 124)) )
    copyOfBM.setPixel(x, y, Color.GREEN);
    else if( ((Red - Green) > 6) &&((Red - Green) < 17) &&((Green - Blue) < 8)
    && (DecodeLuminaceColor( x, y, copyOfBM )< 118 ) )
    copyOfBM.setPixel(x, y, Color.YELLOW);



    void DecodeLuminaceColor( int _x, int _y, Bitmap cBM ){
    float avrLum = 0;
    Red = 0; Green = 0; Blue = 0; //Color.green(green_encoded_color);

    red_encoded_color = cBM.getPixel(_x, _y);
    green_encoded_color = cBM.getPixel(_x, _y);
    blue_encoded_color = cBM.getPixel(_x, _y);

    Red = ( (red_encoded_color >> 16) & 0xff );
    Green = ( (green_encoded_color >> 8) & 0xff);
    Blue = ( (blue_encoded_color >> 0) & 0xff );
    }

    最佳答案

    我会用 HSV色彩空间

    最好检测应该有很大帮助的颜色(更像人类感知)。您也可以使用 HSV Histogram检测你有多少不同的颜色。

    HSV histogram

    如果您仍然想要 RGB,而不是进行不同的比较

    你有笔 color0=(r0,g0,b0)和像素 color=(r,g,b)所以计算它们之间的距离:

    d=((r-r0)*(r-r0))+((g-g0)*(g-g0))+((b-b0)*(b-b0))

    不需要 sqrt .现在你只需计算 d对于您拥有的每种颜色(钢笔)并选择最小的 d ...您也可以使用不太精确的:
    d=abs(r-r0)+abs(g-g0)+abs(b-b0)

    如果您不知道此之前的颜色并且不想使用直方图
  • 形成一个(重新)颜色表(一组不同的可见颜色,您将为每支找到的新笔设置)
  • 创建已找到颜色的空列表
  • 处理输入图像的所有像素
  • 计算距离 d到列表中所有找到的颜色
  • 如果 d小于某个阈值常数,像素在找到的颜色列表中属于该颜色。否则将其添加为新发现的颜色。
  • 使用重新着色表中的颜色重新着色像素。

  • 这将消除阴影和抗锯齿颜色失真。您还可以忽略重新着色表并使用找到的颜色列表中的颜色。这个过程是 的形式颜色量化 .

    [Edit1] 在使用 HSV 颜色并重新着色以找到颜色列表(无直方图)后,我得到了这个结果:

    HSV simple recolor

    这表明您的图像具有不同的照明条件(不是渲染,而是真实照片)。所以 Ilumination normalization应该进一步改善这一点。此外,我使用 2 个阈值,一个用于灰度,一个用于颜色......来区分两者......你也可以通过以下方式检测背景颜色:
  • 像素数(应该比文本颜色大得多)
  • 沿图像分散(应覆盖大面积,密度相对较高,均匀分散...文本局部化)

  • 这里的 C++/VCL 源代码:
    backbuffer bmp; // source and target image
    struct _color { DWORD rgb; int h,s,v; }; // color entry in (re)color table
    _color ld_rgb(DWORD rgb) // just RGB -> HSV conversion
    {
    const int _b=0;
    const int _g=1;
    const int _r=2;
    const int _a=3;
    union { DWORD dd; BYTE db[4]; } c;
    double r,g,b,min,max,del,h,s,v,dr,dg,db;
    c.dd=rgb;
    r=c.db[_r]; r/=255.0;
    g=c.db[_g]; g/=255.0;
    b=c.db[_b]; b/=255.0;
    min=r; if (min>g) min=g; if(min>b) min=b;
    max=r; if (max<g) max=g; if(max<b) max=b;
    del=max-min;
    v=max;
    if (del<=0.1) { h=0; s=0; } // grayscale
    else{
    s=del/max;
    dr=(((max-r)/6.0)+(del/2.0))/del;
    dg=(((max-g)/6.0)+(del/2.0))/del;
    db=(((max-b)/6.0)+(del/2.0))/del;
    if (fabs(r-max)<1e-10) h=db-dg;
    else if (fabs(g-max)<1e-10) h=(1.0/3.0)+dr-db;
    else if (fabs(b-max)<1e-10) h=(2.0/3.0)+dg-dr;
    if (h<0.0) h+=1.0;
    if (h>1.0) h-=1.0;
    }
    _color ccc;
    ccc.rgb=rgb;
    ccc.h=255.0*h;
    ccc.s=255.0*s;
    ccc.v=255.0*v;
    return ccc;
    }
    void recolor() // this is the recolor you want
    {
    // load input jpg file to bmp image
    TJPEGImage *jpg=new TJPEGImage();
    jpg->LoadFromFile("in.jpg");
    bmp.bmp->Assign(jpg);
    bmp.resize(bmp.bmp->Width,bmp.bmp->Height);
    delete jpg;

    // recolor bmp
    int i,x,y,d;
    _color c0,c1;
    List<_color> col; // color list
    col.num=0; // clear colro list
    for (y=0;y<bmp.ys;y++) // process all pixels
    for (x=0;x<bmp.xs;x++)
    {
    c0=ld_rgb(bmp.pyx[y][x]); // pixel color -> hsv

    if ((c0.h==0)&&(c0.s==0)) // compare it to found colors (grayscales)
    for (i=0;i<col.num;i++)
    {
    // i=-1; c1.rgb=0x00202020; break;
    c1=col[i];
    if ((c1.h!=0)||(c1.s!=0)) continue;
    d=abs(c1.v-c0.v);
    if (d<32) { i=-1; break; } // match found ?
    }
    else // compare it to found colors
    for (i=0;i<col.num;i++)
    {
    // i=-1; c1.rgb=0x0000FF00; break;
    c1=col[i];
    if ((c1.h==0)&&(c1.s==0)) continue;
    d=(abs(c1.h-c0.h))+(abs(c1.s-c0.s));
    if (d<50) { i=-1; break; } // match found ?
    }
    if (i>=0) { c1=c0; col.add(c1); } // if not add new color
    bmp.pyx[y][x]=c1.rgb; // recolor;
    }
    bmp.bmp->Canvas->Brush->Style=bsClear;
    bmp.bmp->Canvas->Font->Color=0x00802040;
    bmp.bmp->Canvas->TextOutA(5,0,"Found colors: "+AnsiString(col.num));
    bmp.bmp->Canvas->Brush->Style=bsSolid;
    for (d=16,i=0;i<col.num;i++)
    for (y=d;y<=d+d;y++)
    for (x=d*i+1;(x<d*i+d)&&(x<bmp.xs);x++)
    bmp.pyx[y][x]=col[i].rgb;
    }
  • List<T> l;是动态数组,如 std::vector<T> ... 代表 T l[l.num];
  • backbuffer bmp;是我的图像类... bmp.bmp持有 GDI 位图和 bmp.xs,bmp.ys是分辨率
  • col保存找到的颜色...

  • [Edit1] 双三次照明归一化

    我最近正在重写我的 拨码 lib 升级我的照明标准化,因此我对您的输入图像(作为许多测试图像之一)进行了拍摄,这里的结果(强制(检测到)空白空间重新着色):

    normalized image

    如您所见,中间的红色光点消失了。您可以尝试使用您的算法,以便在对其进行编码之前了解应用照明归一化是否有帮助(如果操作得当,它会有点复杂)。这是这样做的:
  • 为您的图像创建网格(表格)

    每个电池包含 平均颜色和累积三角洲 (噪声)的单元格区域。还有一个标志告诉单元格是否是 墨水 .单元格大小应该在 <0.5 - 1.5> 左右最小细节尺寸(如字母或钢笔宽度...)
  • 将所有具有高增量的单元格设置为墨水,其余设置为纸张
  • 计算所有纸单元组合的平均颜色
  • 每个纸格相邻墨格

    如果其平均颜色与全局平均纸张颜色相差太远,则设置为墨水。注意不要将那些新墨组单元作为这一步的相邻条件。 (使用临时标志或不同的标志位并在完成后恢复...
  • 找到沿图像均匀分布的 16 个控制点(仅使用纸单元格)

    它们应该在坐标附近 0%,33%,66%,100%图像分辨率所以双三次插值是有效的。
  • 对于每个像素

    双三次计算单元格颜色并将其命名为 c0然后对像素应用归一化(RGB 空间中的 !!! ):
  • pixel+=global_avg_color-c0 ;

  • 这将使整个图像的纸张颜色均衡,与 global_avg_color 非常接近。 .保持非纸质细节不失真。
  • 可选择使用 global_avg_color 重新着色所有纸单元格区域

    这不是必需的,但它会消除背景中的大部分噪音。喜欢纸质...
  • 关于java - 需要有关调色板颜色量化 : java - Android 的帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33461711/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com