图片处理--羽化特效

在PHOTOSHOP里,羽化就是使选定范围的图边缘达到朦胧的效果。

羽化值越大,朦胧范围越宽,羽化值越小,朦胧范围越窄. 可根据想留下图的大小来调节

算法分析:
1、通过对rgb值增加额外的 V 值实现朦胧效果
2、通过控制 V 值的大小实现范围控制
3、V = 255 当前点Point距中点距离的平方s1 / (顶点距中点的距离平方 mSize)s2;
4、s1 有根据 ratio 修正 dx dy值.

float mSize = 0.5f;
  public Bitmap render(Bitmap bitmap)
  {
    if(bitmap == null)return null;

    final int SIZE = 32768;
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int ratio = width >height ? height  SIZE /width : width  SIZE/height; //这里有额外*2^15 用于放大比率;之后的比率使用时需要右移15位,或者/2^15.

    int cx = width>>1;
    int cy = height>>1;
    int max = cxcx + cycy;
    int min = (int)(max *(1-mSize));
    int diff= max -min; // ===>>    int diff = (int)(max * mSize);


    int[] pixels = new int[width * height];
    bitmap.getPixels(pixels ,0 , width , 0 , 0 , width , height);
    for(int i=0 ; i<height ; i++)
    {
      for(int j=0 ; j<width ; j++)
      {
        int pixel = pixels[i*width +j];
        int r = (pixel & 0x00ff0000)>>16;
        int g = (pixel & 0x0000ff00)>>8;
        int b = (pixel & 0x000000ff);

        int dx = cx - j;
        int dy = cy - i;

        if(width > height)
        {
          dx= (dx*ratio)>>15;
        }
        else
        {
          dy = (dy * ratio)>>15;
        }

        int dstSq = dxdx + dydy;
        float v = ((float) dstSq / diff)*255;
        r = (int)(r +v);
        g = (int)(g +v);
        b = (int)(b +v);
        r = (r>255 ? 255 : (r<0? 0 : r));
        g = (g>255 ? 255 : (g<0? 0 : g));
        b = (b>255 ? 255 : (b<0? 0 : b));
        pixels[i*width +j] = (pixel & 0xff000000) + (r<<16)+ (g<<8) +b;
      }
    }

    return Bitmap.createBitmap(pixels ,width , height , Config.ARGB_8888);
  }
学习OpenCV:滤镜系列(15)——羽化(模糊边缘)

更加简单的方式:
分析PS的羽化结果可以知道,羽化达成了两个目的:1. 平滑轮廓线; 2. 扩宽过渡区域
1.平滑轮廓线:可以采用均值滤波cvSnakeImage() 两种方式,前者维护一个宽度为 H 的窗口,窗口内均值滤波;而后者是OpenCV的C语言版本函数C++没有包含,其原理是能量最小化. 经过测试前者的速度略高于后者,且当 H 较大时,可以采用窗口加权减一加一的方式来代替每次都求H次加权的方式;
2.扩宽过度区域:采用对 mask 采用全图均值滤波方法即可,卷积核的半径越大,过渡区域越宽.

Last modification:October 9th, 2018 at 09:31 am