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

背景

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

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

一种是利用好Canvas绘制图片,

一种是利用Bitmap的原生API,获取像素进行操作

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

97632c586aca

image

97632c586aca

image

今天的主题是在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 或者用侧边的辅助工具

97632c586aca

image

集成到你要使用OpenCv的项目,如下

97632c586aca

image

图像灰度测试

集成完成后,进行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了,是不是很简单.

97632c586aca

image

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

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

主要步骤:

把RGB图像转换到HSV空间

取背景的一小块20*20,计算蓝色背景的平均色调和饱和度

设置阈值,取出蓝色背景替换为红色背景

把HSV图像转换会RGB空间

滤波器去除边缘效应

Android 代码如下:

private void startDetail() {

Mat image = new Mat();

Utils.bitmapToMat(bitmap, image);

Mat hsvImg = new Mat();

Imgproc.cvtColor(image, hsvImg, Imgproc.COLOR_BGR2HSV);

List 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

97632c586aca

image

效果

97632c586aca

image

污点修复

修复原理

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

97632c586aca

image

可以简单理解为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 <http://en.wikipedia.org/wiki/Inpainting> for more details.

*

* Note:

*

*

* An example using the inpainting technique can be found at

* opencv_source_code/samples/cpp/inpaint.cpp

*

*

* (Python) An example using the inpainting technique can be found at

* opencv_source_code/samples/python/inpaint.py

*

*

*/

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);

}

效果

97632c586aca

image

总结

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

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

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

推荐阅读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/514430.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

闲鱼是怎么让二手属性抽取准确率达到95%+的?

闲鱼是怎么让二手属性抽取准确率达到95%的&#xff1f; 先上效果 图1 - 二手属性抽取算法效果Demo(1) 背景 闲鱼作为一款C2X的app&#xff0c;站在商品发布的角度&#xff0c;闲鱼商品相对于淘宝商品的特点有&#xff1a; 轻发布导致商品信息不足 闲鱼采用图文描述的轻发布模…

代号红狗:那些站在微软云起点的中国创业者

作者&#xff1a;亲爱的数据 来源&#xff1a;亲爱的数据011996年的北京。上高中二年级的左玥&#xff0c;代表崇文区参加市一级"四通杯"青少年计算机程序设计竞赛&#xff0c;得了一等奖。据左玥回忆&#xff0c;在去参赛的路上&#xff0c;辅导老师还在吐槽&#x…

如何迁移 Flink 任务到实时计算

简介&#xff1a; 本文由阿里巴巴技术专家景丽宁&#xff08;砚田&#xff09;分享&#xff0c;主要介绍如何迁移Flink任务到实时计算 Flink 中来。 通常用户在线下主要使用 Flink run&#xff0c;这会造成一些问题&#xff0c;比如&#xff1a;同一个配置因版本而变化&#xf…

如何落地云原生DevOps?

简介&#xff1a; 什么是云原生DevOps&#xff1f;在阿里内部有怎样的实践&#xff1f;企业又该如何落地&#xff1f;阿里云云效专家团队提出了下一代精益产品开发方法体系——ALPD&#xff0c;提供了系统的云原生DevOps落地的方法支撑&#xff0c;帮助企业渐进式地迈入云原生D…

亚马逊独霸美国安云计算未来十年订单;英伟达推出首个元宇宙平台;华为云、天翼云会合并吗?...

NEWS本周新闻回顾亚马逊独霸美国安云计算未来十年订单&#xff0c;微软表示不服亚马逊AWS获得美国国家安全局100亿美元云计算合同。得知亚马逊拿下订单后&#xff0c;微软已向政府问责提交文件&#xff0c;提出抗议。最终……还是亚马逊笑到了最后英伟达推出全球首个元宇宙平台…

如何做好技术 Team Leader?

简介&#xff1a; 作为一个技术TL&#xff08;Team Leader&#xff09;&#xff0c;除了自身技能&#xff0c;还会面临诸多团队管理上的困难和挑战。如何定义和明确团队的目标&#xff1f;怎样建立优秀的工程文化&#xff1f;让团队长期发挥战斗力和创新能力的核心是什么&#…

android应用控制百度地图,Android中应用百度地图API开发地图APP实例-显示百度地图...

场景效果在使用百度地图API之前需要先在百度地图开放平台中申请API_KEY申请API_KEY登录百度开放平台后找到控制台下的应用管理-创建应用依次输入应用名&#xff0c;应用类型选择Android SDK然后下面需要输入发布版SHA1和包名获取应用SHA1首先来到.Android文件所在的位置&#x…

数禾云上数据湖最佳实践

简介&#xff1a; 数禾科技从成立伊始就组建了大数据团队并搭建了大数据平台。并在ECS上搭建了自己的Cloudera Hadoop集群。但随着公司互联网金融业务的快速扩张发展&#xff0c;大数据团队承担的责任也越来越重&#xff0c;实时数仓需求&#xff0c;日志分析需求&#xff0c;即…

程序员只能吃“青春饭”?IT行业年龄焦虑如何破局?

2019 年搜狐科技《中国互联网简史》报告显示&#xff0c;国内近一半的程序员年龄在 25-29 岁之间&#xff0c;其次为 30-34岁&#xff0c;占比 24.6%&#xff0c;35 岁 -39 岁的程序员占比 6.1%&#xff0c;而 40岁 的程序员仅占 1.2%。由于程序员需要长时间面对电脑工作&#…

对容器镜像的思考和讨论

简介&#xff1a; 常言道&#xff0c;startup 有 startup 的好&#xff0c;大厂有大厂的好&#xff0c;那么大厂究竟好在哪呢&#xff1f;拿硅谷老牌大厂们 FLG 来说&#xff0c;如果要问最令人怀念的是什么&#xff1f;Free food 和基础设施(Infrastructure)一定是会上榜的&am…

android 高度上分权重,Android LinearLayout weight权重使用

在日常的开发过程中&#xff0c;我们通常或多或少会使用到LinearLayout的weight属性来进行权重设置&#xff0c;进而达到按比例显示布局的意图通常我们在使用时&#xff0c;会这样使用android:layout_width"match_parent"android:layout_height"match_parent&qu…

实时计算pv/uv Demo

简介&#xff1a; 本文由阿里巴巴高级技术专家邓小勇&#xff08;静行&#xff09;分享&#xff0c;主要用 Demo 演示如何通过实时计算 Flink 实时计算pv/uv的场景。 本文由阿里巴巴高级技术专家邓小勇&#xff08;静行&#xff09;分享&#xff0c;主要用 Demo 演示如何通过实…

《天际友盟DRP数字风险防护报告(2021年上半年)》重磅发布

今天&#xff0c;数字化正在发生&#xff0c;整个社会正在步入数字化革新。根据市场研究公司IDC的预测&#xff0c;到2023年超过50%的全球经济将由数字经济所驱动。在中国&#xff0c;2021-2024数字化转型总支出将达到1.5万亿美元&#xff0c;年均增长率超过17%。由此可见&…

Android Native crash 处理案例分享

简介&#xff1a; Android Native crash 处理案例分享 1. 背景 目前 mPaas[1] Android使用Crash SDK对闪退进行的处理&#xff0c;CrashSDK 是 Android 平台上一款功能强大的崩溃日志收集 SDK&#xff0c;有着极高的崩溃收集率和完整、全面的崩溃日志信息&#xff0c;生成的日…

Mendix:低代码与无代码的异同点与用例

投稿 | Mendix 编辑 | 宋 慧 头图 | 付费下载于 IC photo 低代码和无代码应用开发都遵循着代码抽象化原则来实现建模的可视化。但基于这两种方法构建的应用在规模和类型却有着根本性的区别。 低代码与无代码的相同之处 低代码和无代码开发平台都无需编写代码就能构建软件应用…

解读:云原生下的可观察性发展方向

简介&#xff1a; 非常有幸参加了云原生社区Meetup北京站&#xff0c;有机会和众多业内的大牛一起讨论云原生相关的技术和应用&#xff0c;本次Meetup上我和大家分享了关于云原生下的可观察性相关的议题&#xff0c;本篇文章主要是视频的文字性总结&#xff0c;欢迎大家留言讨论…

一文读懂 Serverless,将配置化思想复用到平台系统中

简介&#xff1a; 搭建一个 aPaaS 平台是需要很长时间的&#xff0c;当然也可以基于一些公有云产品的 Serverless 方案实现现有系统的灵活性与扩展性&#xff0c;从而实现针对于不同客户的定制。 写在前面 在 SaaS 领域 Salesforce 是佼佼者&#xff0c;其 CRM 的概念已经扩展…

9.9 元福利价,解锁校园满分计划

移动云开发者社区致力于为广大开发者提供技术交流和能力输出&#xff0c;是移动云开发者交流汇聚地、移动云产品首席体验官工作台、移动云技术能力布道者讲台和移动云能力输出窗口。通过移动云开发者社区&#xff0c;在帮助移动云开发者用好云、好用云的同时&#xff0c;还可以…

亲历者说 | 完整记录一年多考拉海购的云原生之路

简介&#xff1a; 考拉海购的整个云化改造是从 2019 年 10 月份开始的&#xff0c;当时的唯一目标就是短时间内快速完成迁移。在不到 4 个月的时间里&#xff0c;考拉团队唯一考虑的是如何以最快的速度完成使命&#xff0c;云原生是我们选择的最合适的一条路。 前言 考拉海购的…

为了一个HTTPS,浏览器操碎了心···

作者&#xff1a;轩辕之风O来源&#xff1a;编程技术宇宙 浏览器我是一个浏览器&#xff0c;每到夜深人静的时候&#xff0c;主人就打开我开始学习。为了不让别人看到浏览记录&#xff0c;主人选择了“无痕模式”。但网络中总是有很多坏人&#xff0c;他们通过抓包截获我和服务…