背景

前段时间的一个周末,一个女生让我帮她换一下他的证件照背景,我又没带电脑。我又不好意思拒接,怎么办呢?应用商店下载一个证件照换背景的APP,瞬间换完,我正准备保存时,跳出来一个支付框,如果你要保存,支付2元钱,出于面子,我只好掏了2块钱,保存了。于是我就想,这种技术活,还给别人付钱,自己来撸吧.我是一个专职Android开发,那么就用Android来撸吧.

先来了解一下Android里原生API对图片操作,一般有两种方式,

  1. 一种是利用好Canvas绘制图片,
  2. 一种是利用Bitmap的原生API,获取像素进行操作

这两种操作我都写了对应的文章,可以快速查看

  • Android:让你的“女神”逆袭,代码撸彩妆(画妆)
  • Android:代码撸彩妆 2(大眼,瘦脸,大长腿)

今天的主题是在Android里使用OpenCv来操作图片,并实现两个不同的效果,换证件照背景和污点修复.

代码已经托管在Github上,和上两篇文章代码地址一样,分支with-photo-changecolor

Github ,如果你喜欢,欢迎star 谢谢

Android OpenCv 快速入门

环境搭建

原生的API对图片的操作有限,并且一些颜色空间转化麻烦,效率低,那我们使用一个专业的图片操作库来操作图片,会变得容易些.

OpenCv有很多语言版本,当然底层是c/c++,他支持Android/IOS,Windows,Mac等,我们直接选择Android版本. 那么来搭建一下环境,有两部

  • 下载OpenCv SDK 地址,将SDK 打包成aar,集成到项目中,快速获取aar,可以直接到我打好的包里获取 Github中获取. 打aar包很简单,用Android Studio打开下载好的SDK,然后到其目录下,执行./gradlew assembleRelease 或者用侧边的辅助工具
  • 集成到你要使用OpenCv的项目,如下

图像灰度测试

集成完成后,进行OpenCV SDK接入成功测试

private void initLoaderOpenCV() {boolean success = OpenCVLoader.initDebug();if (!success) {Log.d(TAG, "初始化失败");}
}public void gray(View view) {Mat src = new Mat();Mat dst = new Mat();Utils.bitmapToMat(bitmap, src);Imgproc.cvtColor(src, dst, Imgproc.COLOR_BGRA2GRAY);Bitmap resultBitmap = getResultBitmap();Utils.matToBitmap(dst, resultBitmap);src.release();dst.release();showCompare(resultBitmap);
}

如果接入没问题,就可以愉快的使用OpenCV了,是不是很简单.

换证件照背景 (从蓝色到红色)

换证件照算法,直接使用了一个c++ 版本算法的,翻译为Android的. c++文章地址

主要步骤:

  1. 把RGB图像转换到HSV空间
  2. 取背景的一小块20*20,计算蓝色背景的平均色调和饱和度
  3. 设置阈值,取出蓝色背景替换为红色背景
  4. 把HSV图像转换会RGB空间
  5. 滤波器去除边缘效应

Android 代码如下:

 private void startDetail() {Mat image = new Mat();Utils.bitmapToMat(bitmap, image);Mat hsvImg = new Mat();Imgproc.cvtColor(image, hsvImg, Imgproc.COLOR_BGR2HSV);List<Mat> list = new ArrayList<>();Core.split(hsvImg, list);Mat roiH = list.get(0).submat(new Rect(0, 0, 20, 20));Mat roiS = list.get(1).submat(new Rect(0, 0, 20, 20));Log.i(TAG,"start sum bg");int SumH = 0;int SumS = 0;byte[] h = new byte[1];byte[] s = new byte[1];//取一块蓝色背景,计算出它的平均色调和平均饱和度for (int i = 0; i < 20; i++) {for (int j = 0; j < 20; j++) {roiH.get(j, i, h);roiS.get(j, i, s);SumH = h[0] + SumH;SumS = s[0] + SumS;}}int avgH, avgS;//蓝底的平均色调和平均饱和度avgH = SumH / 400;avgS = SumS / 400;Log.i(TAG,"depth="+list.get(0).depth());Log.i(TAG,"start sum detail all photo");//遍历整个图像int nl = hsvImg.height();int nc = hsvImg.width();
//        byte[] changeColor = new byte[]{127};byte[] hArray = new byte[nl * nc];byte[] sArray = new byte[nl * nc];byte[] vArray = new byte[nl * nc];list.get(0).get(0,0,hArray);list.get(1).get(0,0,sArray);
//        list.get(2).get(0,0,vArray);int row,index;for (int j = 0; j < nl; j++) {row = j * nc;for (int i = 0; i < nc; i++) {index = row + i;if(hArray[index] <= (avgH + 20) && hArray[index] >= (avgH - 20)&& sArray[index] <= (avgS + 150)&& sArray[index] >= (avgS -150)){hArray[index] = 127;
//                    sArray[index] = 0;
//                    vArray[index] = (byte) 255;}}}list.get(0).put(0,0,hArray);list.get(1).put(0,0,sArray);
//        list.get(2).put(0,0,vArray);Log.i(TAG,"merge photo");Core.merge(list,hsvImg);Imgproc.cvtColor(hsvImg,image, Imgproc.COLOR_HSV2BGR);Bitmap resultBitmap = getResultBitmap();Utils.matToBitmap(image,resultBitmap);Message obtain = Message.obtain();obtain.obj = resultBitmap;handler.sendMessage(obtain);}

Mat 为OpenCV中图像的保存,很类似Android里的Bitmap,他和Bitmap转化需要借助OpenCv的Utils进行,OpenCV的核心API可以查看官网,此处主要使用了Imgproc

效果

污点修复

修复原理

先来说一下污点修复的算法,一篇论文提到的 《An ImageInpainting Technique Based On the Fast Marching Method》

可以简单理解为p点为待修复区域,ε为修复半径,把ε的值区域的值计算出来,用于修复P点,直到修复整个Ω区域.

详细可以查看论文:论文地址

实际修复

OpenCV 里面已经实现了此算法,具体方法如下:

//OpenCV Photo.java/*** Restores the selected region in an image using the region neighborhood.** @param src Input 8-bit, 16-bit unsigned or 32-bit float 1-channel or 8-bit 3-channel image.* @param inpaintMask Inpainting mask, 8-bit 1-channel image. Non-zero pixels indicate the area that* needs to be inpainted.* @param dst Output image with the same size and type as src .* @param inpaintRadius Radius of a circular neighborhood of each point inpainted that is considered* by the algorithm.* @param flags Inpainting method that could be cv::INPAINT_NS or cv::INPAINT_TELEA** The function reconstructs the selected image area from the pixel near the area boundary. The* function may be used to remove dust and scratches from a scanned photo, or to remove undesirable* objects from still images or video. See &lt;http://en.wikipedia.org/wiki/Inpainting&gt; for more details.** <b>Note:</b>* <ul>*   <li>*       An example using the inpainting technique can be found at*         opencv_source_code/samples/cpp/inpaint.cpp*   </li>*   <li>*       (Python) An example using the inpainting technique can be found at*         opencv_source_code/samples/python/inpaint.py*   </li>* </ul>*/public static void inpaint(Mat src, Mat inpaintMask, Mat dst, double inpaintRadius, int flags) {inpaint_0(src.nativeObj, inpaintMask.nativeObj, dst.nativeObj, inpaintRadius, flags);}

其中上面提到的原理算法为,INPAINT_TELEA.

来一张实际的图操作修复一下,如下:

      private void startInpaint() {bitmap = BitmapUtils.getBitmapByAssetsNameRGB(this,"test.png");Mat desc = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC3);//转化为mat对象Utils.bitmapToMat(bitmap, desc,true);//转化为3通道图像Mat src = new Mat();Imgproc.cvtColor(desc,src,Imgproc.COLOR_RGBA2RGB);//灰度图像Mat srcGray = new Mat();Imgproc.cvtColor(src, srcGray, Imgproc.COLOR_RGB2GRAY);//中值滤波去燥Imgproc.medianBlur(srcGray,srcGray,3);//获取污点的二值化图像Mat srcThresh = new Mat();Imgproc.threshold(srcGray,srcThresh,242,255,Imgproc.THRESH_BINARY);Log.i("test","srcThresh channels:"+srcThresh.channels() + ",type:"+ CvType.typeToString(CvType.depth(srcThresh.type())));Log.i("test","src channels:"+src.channels() + ",type:"+ CvType.typeToString(CvType.depth(src.type())));
//        Bitmap resultBitmap = getResultBitmap();
//        Utils.matToBitmap(srcThresh, resultBitmap);//修复图像Mat inpaintResult = new Mat();Photo.inpaint(src,srcThresh,inpaintResult,3,Photo.INPAINT_TELEA);//把结果转化为bitmap 用于显示Bitmap resultBitmap = getResultBitmap();Utils.matToBitmap(inpaintResult, resultBitmap);Message obtain = Message.obtain();obtain.obj = resultBitmap;handler.sendMessage(obtain);}

效果

图片来源:https://www.cnblogs.com/hellowooorld/p/7048614.html

总结

本篇文章,主要介绍了OpenCV怎么快速使用,并结合了两个实际的例子,来进一步说明借助OpenCV里的API,可以实现很多不错的效果.

文中图片来源网络,若又侵权,请联系作者,立刻删除!

本篇文章的两个例子代码地址:github ,如果你喜欢迎star,后续关于图片的操作,都会在此库里更新.

推荐阅读

Android:让你的“女神”逆袭,代码撸彩妆(画妆)
Flutter PIP(画中画)效果的实现
Android 绘制原理浅析【干货】

Android 修图(换证件照背景,污点修复)相关推荐

  1. android studio证件照代码,Android 修图(换证件照背景,污点修复)

    背景 前段时间的一个周末,一个女生让我帮她换一下他的证件照背景,我又没带电脑.我又不好意思拒接,怎么办呢?应用商店下载一个证件照换背景的APP,瞬间换完,我正准备保存时,跳出来一个支付框,如果你要保存 ...

  2. 如何用ps换证件照背景颜色

    参考链接:https://jingyan.baidu.com/article/9989c746c77209f648ecfea8.html

  3. android theme material,Android Studio 换主题(Material Theme..)

    1.去如下网址下载自己喜欢的主题文件xx.jar http://color-themes.com/?view=index 2. 导入方式 下载主题-xxx.jar 注意:如果我们下载下来的jar名字如 ...

  4. 深度学习项目实践——制作一个能一键更换证件照背景的软件

    背景 前段时间找工作,做简历的时候看中了一个红色为底色的模板,但是发现我的证件照只有蓝色底色的,这和简历不搭啊!有点强迫症的我怎么能忍!果断上网找方法换证件照底色(不要问我为什么不去重新拍一张,因为我 ...

  5. floatingactionbutton 更改背景颜色_经验分享!Word轻松换掉证件照背景颜色

    ​生活中,我们入职或者办证都需要用到证件照,还有各种要求,例如需要红底.白底等等,因为要换个背景颜色,就要去重拍一张吗?当然不用,现在我们可以用word换证件照颜色,PS都免了,一起来看看操作方法吧. ...

  6. 证件照背景颜色怎么用手机换

    证件照是日常生活中非常常用的照片之一,可以说是一种非常特殊的照片,因为很多场合证件照背景要求都不同,所以大家经常去照相馆重新拍摄,其实手机就可以给证件照换底色,方法非常简单. 现在手机像素都很高,拍照 ...

  7. 计算机等级图片背景蓝色怎么调,证件照背景颜色怎么换?白色蓝色背景都能换的方法...

    证件照背景颜色怎么换?有的人会选择使用某图秀秀,或者利用excel表格来操作,其实还有一种方法可以快速更换证件照背景颜色,比如使用智能证件照相机.这个工具除了可以更换证件照背景颜色以外,还能美颜.美白 ...

  8. 如何给照片换背景?怎么用手机更换证件照背景颜色

    有时候在使用电子版的证件照的时候,由于证件照的背景颜色与要求不符所以无法使用证件照的情况,那么应该如何给照片换背景(https://www.yasuotu.com/coloreplace)?首先我们要 ...

  9. Opencv -- 12图像色彩空间转换应用 -- 给证件照换颜色背景

    应用:给证件照换颜色背景 利用HSV中的常见色彩区分度比RGB中的色彩区分度更明显的优势,再结合inRange()函数可以将图片中不同的颜色给提取出来. openCV中的HSV颜色体系 使用 Open ...

最新文章

  1. 2天训练出15亿参数大模型,国产开源项目力克英伟达Megatron-LM,来自LAMB作者团队...
  2. 如何获取高精度CV模型?快来试试百度EasyDL超大规模视觉预训练模型
  3. 【Unity】6.1 Unity中的C#脚本基础知识
  4. 计算机二级offic考试题库2017,2017年9月计算机二级MSOffice考试题「带答案」
  5. 微软BI 之SSIS 系列 - 通过设置 CheckPoints 检查点来增强 SSIS Package 流程的重用性...
  6. Python学习笔记(六)——查询天气脚本
  7. 295.数据流的中位数
  8. java controller的生命周期_一张图搞懂Spring bean的完整生命周期
  9. AE 动效工作流技巧 —— 减少 Bodymovin 导出的 JSON 大小并提升性能(二)
  10. 【CentOS8.0开启防火墙放行8081端口】
  11. 盘点国外知名量化基金
  12. 分享个自己Python爬虫时的浏览器标识库
  13. 用余弦算法做相似度匹配
  14. yocto编译linux,好实用!用 Yocto 在 Ubuntu 上创建最小化 Linux 发行版
  15. TCP、UDP的区别
  16. 【06月19日】A股滚动市盈率PE最低排名
  17. 李永乐(七)向量组的秩、矩阵的秩——笔记
  18. Python学习之title()函数
  19. 未来的计算机事业作文600字,模块计算机考试的感想
  20. 修改3389远程端口的批处理文件.bat

热门文章

  1. xposed android4.4,EdXposed下载-edxposed框架 安卓版v4.4.8-PC6安卓网
  2. Mac解决鼠标滚轮反方向移动逻辑--Mos(又免费又好用哦~)
  3. 如何用Visio画venn(维恩)图
  4. 数据库表设计3:微信、QQ第三方多账号登陆
  5. 解决Linux服务器磁盘爆满导致的MySQ错误Can‘t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock
  6. Linux文件系统预读的情景分析
  7. c语言的局部变量,全局变量及静态局部变量和静态全局变量
  8. app复杂业务逻辑自动化验证案例分享
  9. UE4/UE5 虚幻引擎,快捷键
  10. 可分离卷积:空间可分离卷积和深度可分离卷积