android studio bitmap转jpg_如何用OpenCV在Android中制作铅笔素描图像效果

6c3d633345744327ac14394d22ac918b.png

今天我们将制作一个Android应用程序,在OpenCV的帮助下将图像转换为铅笔素描。在我们开始之前:我假设您的android项目中已经安装了Open CV。

步骤1:打开activity_main。添加一个ImageView和3个按钮(第一个按钮用于从手机图库中选择图像,另两个按钮用于将图像转换为素描和彩色素描。

   
acd5c3269bd97bedf78279a5a214879f.png

步骤2:打开MainActivity.java,再onCreate中添加如下java代码。

private ImageView image;private Button select, sketch, colored@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); OpenCVLoader.initDebug(); image = findViewById(R.id.image); select = findViewById(R.id.select_img); sketch = findViewById(R.id.sketch); colored = findViewById(R.id.colored_sketch);}
932bbcda53cc6a637b2765b299da4f31.png

步骤3:创建一个ImageChooser函数,从图库中选择图像并显示在ImageView中。

为图像选择器声明几个变量。

private final int SELECT_PHOTO = 1;private Bitmap originBitmap = null;private File tempFile = new File("/sdcard/a.jpg");private Bitmap processImg;
1816c832cd70eb10983d297d0b348fd6.png

显示图像选择器的函数

private void showImageChooser() { Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); startActivityForResult(photoPickerIntent, SELECT_PHOTO);}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == SELECT_PHOTO && resultCode == RESULT_OK && null != data) { Uri selectedImage = data.getData(); InputStream imageStream; try { imageStream = getContentResolver().openInputStream(selectedImage); originBitmap = BitmapFactory.decodeStream(imageStream); } catch (FileNotFoundException e) { e.printStackTrace(); } if (originBitmap != null) { tempFile.delete(); this.image.setImageBitmap(originBitmap); } }}
f2a16ace787508c0bfd82aa70bb5024e.png

将OnClickListener设置为图像选择按钮

select.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showImageChooser(); }});
cfb6885fdb68a819ec0158f6ff3dae6e.png
05c6dcb36cb787172b1dcd13ebabc78d.png

步骤4:让我们将效果应用到选定的图像。

为了将图像转换为素描,我们需要制作3个不同的图像层

  1. 灰度(第1层)
  2. 反转灰度图像(第2层)
  3. 将高斯模糊应用于inverted image(第3层)
  4. 用于铅笔素描的颜色减淡和混合(第3层,第1层),用于彩色素描的颜色减淡(原始图像,第1层)。

素描函数的java代码如下:

public void Sketch(Bitmap bitmap, String type){ bitmap=bitmap.copy(Bitmap.Config.ARGB_8888, true); Mat src = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4); Mat dest = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4); Mat grey = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4); Mat invert = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4); Bitmap inv, gray; Utils.bitmapToMat(bitmap, src); Imgproc.cvtColor(src, grey, Imgproc.COLOR_BGR2GRAY); Imgproc.cvtColor(grey, grey, Imgproc.COLOR_GRAY2RGBA, 4); Core.bitwise_not( grey, invert); Imgproc.GaussianBlur(invert,invert, new Size(11,11),0); inv = Bitmap.createBitmap(invert.cols(),invert.rows(),Bitmap.Config.ARGB_8888); gray = Bitmap.createBitmap(invert.cols(),invert.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(invert, inv); Utils.matToBitmap(grey, gray); Bitmap b = null; if (type.equals("normal")) { b = ColorDodgeBlend(inv, gray); }else if(type.equals("colored")){ b = ColorDodgeBlend(inv, bitmap); } processImg = Bitmap.createBitmap(dest.cols(),dest.rows(),Bitmap.Config.ARGB_8888); Utils.matToBitmap(dest, processImg); image.setImageBitmap(b);}
0657ed8b3e2ad8240482230cac4f5ff6.png

颜色减淡和混合的java代码:

private static 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)))));}public static 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;}
59411656bdab85276179297ef51ad75d.png

将OnClickListener添加到按钮

sketch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) {  if (originBitmap != null) { Sketch(originBitmap, "normal"); } }});colored.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (originBitmap != null) { Sketch(originBitmap, "colored"); } }});
4c142bcf7d55489e3c855264444ba0b9.png
13170ecd296c609404d320b7576b4c1b.png

步骤5:在模拟器中构建和测试应用程序。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值