照片/图像到草图algorithm

有没有人有一个想法,链接,图书馆,源代码,…如何转换照片和图像(位图)粗略的图片? 如何做到这一点我找不到任何好消息。

我发现这个链接如何卡通 – 如果编程的图像? 关于如何以编程方式卡通图像,但是我更喜欢将图像制作成草图。

我想制作一个Android应用程序,可以通过编程将JPEG照片转换为粗略的图像。

Solutions Collecting From Web of "照片/图像到草图algorithm"

好吧,所以我发现我自己的答案使用像马克告诉我的不同的技术。 我使用下面的伪代码:

*s = Read-File-Into-Image("/path/to/image") *g = Convert-To-Gray-Scale(s) *i = Invert-Colors(g) *b = Apply-Gaussian-Blur(i) *result = Color-Dodge-Blend-Merge(b,g) 

前四种方法很容易在互联网上find,但最后一个我找不到很多信息,甚至没有源代码。 所以我search了PS如何做,并在c ++中find以下公式:

 ((uint8)((B == 255) ? B:min(255, ((A << 8 ) / (255 - B))))) 

然后我用下面的代码把它转换成Java:

 private int colordodge(int in1, int in2) { float image = (float)in2; float mask = (float)in1; return ((int) ((image == 255) ? image:Math.min(255, (((long)mask << 8 ) / (255 - image))))); } /** * Blends 2 bitmaps to one and adds the color dodge blend mode to it. */ public Bitmap ColorDodgeBlend(Bitmap source, Bitmap layer) { Bitmap base = source.copy(Config.ARGB_8888, true); Bitmap blend = layer.copy(Config.ARGB_8888, false); IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight()); base.copyPixelsToBuffer(buffBase); buffBase.rewind(); IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight()); blend.copyPixelsToBuffer(buffBlend); buffBlend.rewind(); IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight()); buffOut.rewind(); while (buffOut.position() < buffOut.limit()) { int filterInt = buffBlend.get(); int srcInt = buffBase.get(); int redValueFilter = Color.red(filterInt); int greenValueFilter = Color.green(filterInt); int blueValueFilter = Color.blue(filterInt); int redValueSrc = Color.red(srcInt); int greenValueSrc = Color.green(srcInt); int blueValueSrc = Color.blue(srcInt); int redValueFinal = colordodge(redValueFilter, redValueSrc); int greenValueFinal = colordodge(greenValueFilter, greenValueSrc); int blueValueFinal = colordodge(blueValueFilter, blueValueSrc); int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal); buffOut.put(pixel); } buffOut.rewind(); base.copyPixelsFromBuffer(buffOut); blend.recycle(); return base; } 

如果代码可以改进,请在下面发表新的答案或评论。 谢谢!

并添加颜色。

 *s = Read-File-Into-Image("/path/to/image") *g = Convert-To-Gray-Scale(s) *i = Invert-Colors(g) *b = Apply-Gaussian-Blur(i) *result = Color-Dodge-Blend-Merge(b,g) *s2 = Apply-Gaussian-Blur(s) //I use radius 3 *cartoon = Apply-Color(s2, result) 

我对ColorDodgeBlend稍作修改以消除所有的颜色。

 public Bitmap ColorDodgeBlend(Bitmap source, Bitmap layer) .... //before buffOut.put(pixel); float[] hsv = new float[3]; Color.colorToHSV(pixel, hsv); hsv[1] = 0.0f; float top = VALUE_TOP; //Between 0.0f .. 1.0f I use 0.87f if (hsv[2] <= top) { hsv[2] = 0.0f; } else { hsv[2] = 1.0f; } pixel = Color.HSVToColor(hsv); 

一个应用颜色的方法:

 //hue, saturarion, value intervals size are for reduce colors on Bitmap //saturation, value percents are for increment or decrement [0..100..) public Bitmap getCartoonizedBitmap(Bitmap realBitmap, Bitmap dodgeBlendBitmap, int hueIntervalSize, int saturationIntervalSize, int valueIntervalSize, int saturationPercent, int valuePercent) { // Bitmap bitmap = Bitmap.createBitmap(scaledBitmap); // //fastblur(scaledBitmap, 4); Bitmap base = fastblur(realBitmap, 3).copy(Config.ARGB_8888, true); Bitmap dodge = dodgeBlendBitmap.copy(Config.ARGB_8888, false); try { int realColor; int color; float top = VALUE_TOP; //Between 0.0f .. 1.0f I use 0.87f IntBuffer templatePixels = IntBuffer.allocate(dodge.getWidth() * dodge.getHeight()); IntBuffer scaledPixels = IntBuffer.allocate(base.getWidth() * base.getHeight()); IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight()); base.copyPixelsToBuffer(scaledPixels); dodge.copyPixelsToBuffer(templatePixels); templatePixels.rewind(); scaledPixels.rewind(); buffOut.rewind(); while (buffOut.position() < buffOut.limit()) { color = (templatePixels.get()); realColor = scaledPixels.get(); float[] realHSV = new float[3]; Color.colorToHSV(realColor, realHSV); realHSV[0] = getRoundedValue(realHSV[0], hueIntervalSize); realHSV[2] = (getRoundedValue(realHSV[2] * 100, valueIntervalSize) / 100) * (valuePercent / 100); realHSV[2] = realHSV[2]<1.0?realHSV[2]:1.0f; realHSV[1] = realHSV[1] * (saturationPercent / 100); realHSV[1] = realHSV[1]<1.0?realHSV[1]:1.0f; float[] HSV = new float[3]; Color.colorToHSV(color, HSV); boolean putBlackPixel = HSV[2] <= top; realColor = Color.HSVToColor(realHSV); if (putBlackPixel) { buffOut.put(color); } else { buffOut.put(realColor); } }// END WHILE dodge.recycle(); buffOut.rewind(); base.copyPixelsFromBuffer(buffOut); } catch (Exception e) { // TODO: handle exception } return base; } public static float getRoundedValue(float value, int intervalSize) { float result = Math.round(value); int mod = ((int) result) % intervalSize; result += mod < (intervalSize / 2) ? -mod : intervalSize - mod; return result; } 

这并没有改善。 它更好,如果Apply-ColorColor-Dodge-Blend-Merge合并。

感谢XverhelstX的问题答案

下面是一个如何在graphics编辑程序中创build这种效果的例子:

http://www.createblog.com/paintshop-pro-tutorials/14018-sketch-effect/

  1. 将图像转换为灰度。
  2. 做一个副本,并反转强度。
  3. 模糊副本。
  4. 使用颜色减淡公式组合两个图像。

这里是根据@XverhelstX的代码明确的答案我已经创build了一个代码,以清楚地从照片素描。 从源采取图像并将其转换为input位图。 现在调用下面的方法并将Bitmap传递给它。

  public Bitmap Changetosketch(Bitmap bmp){ Bitmap Copy,Invert,Result; Copy =bmp; Copy = toGrayscale(Copy); Invert = createInvertedBitmap(Copy); Invert = Blur.blur(MainActivity.this, Invert); Result = ColorDodgeBlend(Invert, Copy); return Result; } 

这里我们得到了3种方法GrayScale,Inverted和Color-DodgeBlend。

  public static Bitmap toGrayscale(Bitmap bmpOriginal) { int width, height; height = bmpOriginal.getHeight(); width = bmpOriginal.getWidth(); Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); Canvas c = new Canvas(bmpGrayscale); Paint paint = new Paint(); ColorMatrix cm = new ColorMatrix(); cm.setSaturation(0); ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm); paint.setColorFilter(f); c.drawBitmap(bmpOriginal, 0, 0, paint); return bmpGrayscale; } public static Bitmap createInvertedBitmap(Bitmap src) { ColorMatrix colorMatrix_Inverted = new ColorMatrix(new float[] { -1, 0, 0, 0, 255, 0, -1, 0, 0, 255, 0, 0, -1, 0, 255, 0, 0, 0, 1, 0}); ColorFilter ColorFilter_Sepia = new ColorMatrixColorFilter( colorMatrix_Inverted); Bitmap bitmap = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); paint.setColorFilter(ColorFilter_Sepia); canvas.drawBitmap(src, 0, 0, paint); return bitmap; } public Bitmap ColorDodgeBlend(Bitmap source, Bitmap layer) { Bitmap base = source.copy(Bitmap.Config.ARGB_8888, true); Bitmap blend = layer.copy(Bitmap.Config.ARGB_8888, false); IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight()); base.copyPixelsToBuffer(buffBase); buffBase.rewind(); IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight()); blend.copyPixelsToBuffer(buffBlend); buffBlend.rewind(); IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight()); buffOut.rewind(); while (buffOut.position() < buffOut.limit()) { int filterInt = buffBlend.get(); int srcInt = buffBase.get(); int redValueFilter = Color.red(filterInt); int greenValueFilter = Color.green(filterInt); int blueValueFilter = Color.blue(filterInt); int redValueSrc = Color.red(srcInt); int greenValueSrc = Color.green(srcInt); int blueValueSrc = Color.blue(srcInt); int redValueFinal = colordodge(redValueFilter, redValueSrc); int greenValueFinal = colordodge(greenValueFilter, greenValueSrc); int blueValueFinal = colordodge(blueValueFilter, blueValueSrc); int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal); buffOut.put(pixel); } buffOut.rewind(); base.copyPixelsFromBuffer(buffOut); blend.recycle(); return base; } private int colordodge(int in1, int in2) { float image = (float)in2; float mask = (float)in1; return ((int) ((image == 255) ? image:Math.min(255, (((long)mask << 8 ) / (255 - image))))); } 

有一件事要注意的是,在我的代码中,我使用Renderscript来模糊位图。

这里是模糊类。

 import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.support.v8.renderscript.Allocation; import android.support.v8.renderscript.Element; import android.support.v8.renderscript.RenderScript; import android.support.v8.renderscript.ScriptIntrinsicBlur; import android.view.View; public class Blur { private static final float BITMAP_SCALE = 0.4f; private static final float BLUR_RADIUS = 4.5f; public static Bitmap blur(View v) { return blur(v.getContext(), getScreenshot(v)); } public static Bitmap blur(Context ctx, Bitmap image) { Bitmap photo = image.copy(Bitmap.Config.ARGB_8888, true); try { final RenderScript rs = RenderScript.create( ctx ); final Allocation input = Allocation.createFromBitmap(rs, photo, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); final Allocation output = Allocation.createTyped(rs, input.getType()); final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); script.setRadius( BLUR_RADIUS ); /* eg 3.f */ script.setInput( input ); script.forEach( output ); output.copyTo( photo ); }catch (Exception e){ e.printStackTrace(); } return photo; } private static Bitmap getScreenshot(View v) { Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); v.draw(c); return b; } } 

设置好所有这些后,只需将您的input位图传递到onCreate方法的第一个方法即:

  Done.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ResultBitmap = ChangetoSketch(InputBitmap); ImageView.setImageBitmap(ResultBitmap); } }); 

如果有帮助请投票。

好的,如果你有一个那么你可以在这里发布的代码,看看是否有人可以帮助你把代码翻译成Java ..另一种select..你可能不得不使用ndk也许..但是,我find了一些链接,我在这里张贴他们..你在这里find有趣的东西在这些链接

如何以编程方式卡通图像? 你可以检查这个链接