第一章 基于Android的图片卡通化及肤色改变

一、基于Visual Studio的图片卡通化

二、基于Visual Studio的肤色改变

三、Android代码移植

最近由于工作比较忙,很抱歉没有抽出时间来更新这个系列的博客。在这里感谢一下关注该博客的同学。其实写这个系列的初衷,主要还是想记录读书的过程,同时给自己一些动力坚持下去,没有期望关注度。但是大家的关注将给我更大的动力坚持下去。以后也会尽量抽时间更新后面的章节。

书归正传,今天继续完成第一章的最后一部分的内容:Android代码的移植

关于本书第一章所涉及到的知识点,其实在前两部分已经介绍的差不多了,本节的重点在于介绍在app集成opencv的方法和基本调用流程。没有什么理论知识,大部分是程序化的流程。另外,这部分要求对android开发有一些基础。如果你对android开发没有兴趣,或是只想了解opencv或本书涉及到的图像处理知识,这一节可以直接忽略。

老规矩,先上效果图。这张照片是对着显示器拍的,纹理比较明显,局部效果可能不是很好。有兴的同学可以将demo下载下来,自拍玩一玩。demo的地址会在文章最后给出。

涉及到的知识点:

1、Android studio工程集成opencv sdk的相关配置

2、图像处理的移植

1、opencv集成配置

首先到官网下载Opencv Android版sdk:https://opencv.org/opencv-3-4-1/。下载完成后得到压缩文件opencv-3.4.1-android-sdk.zip,解压之。

新建AndroidStudio项目,通过File -> New -> Import Module导入模块。模块路径选择如下图,选到java这一层即可。

将native->libs文件夹下的内容,拷贝到libs文件夹下。

然后做如下配置:

  • 修改module的sdkversion与主app一致

  • 删除模块清单文件中的version声明

  • 主app中添加依赖项和native库搜索路径

做完上述配置之后,尝试编译你的app。编译成功证明基本环境已经配置完毕。

2、opencv的使用和代码移植

opencv对应的java接口基本与c++接口保持一致。将第二章图像处理部分的源码复制过来,改为java语法格式,基本就能使用了。在项目中需要注意的有两点。

  • 必须手动初始化Opencv库,调用如下方法进行初始化
OpenCVLoader.initAsync
  • opencv底层均由native c++方法实现,因此必须加载so,否则会error
System.loadLibrary("opencv_java3");

关于图像处理过程的代码,正如上面所说,改成java语法格式就能够使用了,直接上改过之后的源码。

private void alignMat(Mat src) {Size size = src.size();Mat gray = new Mat(src.size(), CV_8UC3);Mat yuv = new Mat(size, CV_8UC3);Mat faceOutline = Mat.zeros(size, CV_8UC3);Mat srcClone = src.clone();Scalar color = new Scalar(255, 255, 0);Imgproc.cvtColor(src, gray, COLOR_BGR2GRAY);Imgproc.cvtColor(src, yuv, COLOR_BGR2YCrCb); // 色彩空间转换//画笑脸开始double sw = size.width;double sh = size.height;int thickness = 4;double faceH = sh / 2 * 70 / 100;double faceW = faceH * 72 / 100;Imgproc.ellipse(faceOutline, new Point(sw / 2, sh / 2), new Size(faceW, faceH), 0.0, 0.0, 360.0, color, thickness, LINE_4 ,0);double eyeW = faceW * 23 / 100;double eyeH = faceH * 11 / 100;double eyeX = faceW * 48 / 100;double eyeY = faceH * 13 / 100;Size eyeSize = new Size(eyeW, eyeH);int eyeA = 15;int eyeYshift = 11;Imgproc.ellipse(faceOutline, new Point(sw / 2 - eyeX, sh / 2 - eyeY), eyeSize, 0, 180 + eyeA, 360 - eyeA, color, thickness, LINE_AA, 0);Imgproc.ellipse(faceOutline, new Point(sw / 2 - eyeX, sh / 2 - eyeY - eyeYshift), eyeSize, 0, 0 + eyeA, 180 - eyeA, color, thickness, LINE_AA, 0);Imgproc.ellipse(faceOutline, new Point(sw / 2 + eyeX, sh / 2 - eyeY), eyeSize, 0, 180 + eyeA, 360 - eyeA, color, thickness, LINE_AA, 0);Imgproc.ellipse(faceOutline, new Point(sw / 2 + eyeX, sh / 2 - eyeY - eyeYshift), eyeSize, 0, 0 + eyeA, 180 - eyeA, color, thickness, LINE_AA, 0);double mouthY = faceH * 48 / 100;double mouthW = faceW * 45 / 100;double mouthH = faceH * 6 / 100;Imgproc.ellipse(faceOutline, new Point(sw / 2, sh / 2 + mouthY), new Size(mouthW, mouthH), 0, 0, 180, color, thickness, LINE_AA, 0);int fontFace = FONT_HERSHEY_COMPLEX;float fontScale = 1.0f;int fontThickness = 2;String szMsg = "Put your face here";Imgproc.putText(faceOutline, szMsg, new Point(sw * 23 / 100, sh * 10 / 100), fontFace, fontScale, color, fontThickness, LINE_AA, false);//画笑脸结束//中值+拉普拉斯+闭运算进行轮廓提取Mat mask, maskPlusBorder;maskPlusBorder = Mat.zeros((int)sh + 2, (int)sw + 2, CV_8UC1);mask = maskPlusBorder.submat(new Rect(1, 1, (int)sw, (int)sh));Imgproc.medianBlur(gray, gray, 7);Mat edges = gray.clone();Imgproc.Laplacian(gray, edges, CV_8U);Imgproc.resize(edges, mask, size);int EDGES_THRESHOLD = 80;Imgproc.threshold(mask, mask, EDGES_THRESHOLD, 255, THRESH_BINARY);Imgproc.dilate(mask, mask, new Mat());Imgproc.erode(mask, mask, new Mat());//种子像素点int NUM_SKIN_POINTS = 6;Point[] skinPts = new Point[NUM_SKIN_POINTS];skinPts[0] = new Point(sw / 2, sh / 2 - sh / 6);skinPts[1] = new Point(sw / 2 - sw / 11, sh / 2 - sh / 6);skinPts[2] = new Point(sw / 2 + sw / 11, sh / 2 - sh / 6);skinPts[3] = new Point(sw / 2, sh / 2 - sh / 16);skinPts[4] = new Point(sw / 2 - sw / 9, sh / 2 - sh / 16);skinPts[5] = new Point(sw / 2 + sw / 9, sh / 2 - sh / 16);//上下限int LOWER_Y = 60;int UPPER_Y = 80;int LOWER_Cr = 25;int UPPER_Cr = 15;int LOWER_Cb = 20;int UPPER_Cb = 15;Scalar lowerDiff = new Scalar(LOWER_Y, LOWER_Cr, LOWER_Cb);Scalar upperDiff = new Scalar(UPPER_Y, UPPER_Cr, UPPER_Cb);//漫水填充int CONNECTED_COMPONENTS = 4;int flags = CONNECTED_COMPONENTS | FLOODFILL_FIXED_RANGE | FLOODFILL_MASK_ONLY;Mat edgeMask = mask.clone();for (int i = 0; i < NUM_SKIN_POINTS; i++) {Imgproc.floodFill(yuv, maskPlusBorder, skinPts[i], new Scalar(255, 255, 255), null, lowerDiff, upperDiff, flags);}//最后叠加矩阵Imgproc.threshold(mask, mask, 0, 255, THRESH_BINARY);Core.subtract(mask, edgeMask, mask);int Red = 0;int Green = 70;int Blue = 0;Core.add(src, new Scalar(Red, Green, Blue), src, mask);}

本章结语

本章介绍了Mastering Opencv一书第一章所涉及到的知识点,并实现了一个简易的demo。

关于图像处理的流程还有很多能够提升的地方。比如,现在的流程中,漫水填充的六个seed点完全是经验值,而且比例是写死的。这就要求拍照时,必须距离合适,而且是正面照才能得到不错的效果,稍远或者稍近都会导致效果都不好。解决这个问题的方法当然是首先进行图像中的人脸检测,然后根据人脸大小,按比例选取漫水填充的seed。关于人脸检测算法,在后面的章节会有所提及,但这并不是本章的重点。作为本书的第一章,其目的主要还是要告诉读者,opencv其实可以实现许多有意思的功能,并介绍一些图像处理方面的思想。随着对后面章节的学习,对opencv的认识,也将会逐步深入。

最后,贴上本Android工程的源码,仅供借鉴 https://github.com/mymottoissh/Mastering-Opencv-Chapter1。

实战精通OpenCV第一章--基于Android的图片卡通化及肤色改变(三)相关推荐

  1. 实战精通OpenCV第一章--基于Android的图片卡通化及肤色改变(二)

    转载请注明出处:https://blog.csdn.net/mymottoissh/article/details/86723580 第一章 基于Android的图片卡通化及肤色改变 一.基于Visu ...

  2. 实战精通OpenCV第一章--基于Android的图片卡通化及肤色改变(一)

    转载请注明出处:https://blog.csdn.net/mymottoissh/article/details/86709457 本系列博客是基于<Mastering OpenCV with ...

  3. 《RabbitMQ 实战指南》第一章 RabbitMQ 简介

    <RabbitMQ 实战指南>第一章 RabbitMQ 简介 文章目录 <RabbitMQ 实战指南>第一章 RabbitMQ 简介 一.什么是消息中间件 二.消息中间件的作用 ...

  4. Spring入门到精通:第一章 基础入门:1.Spring框架概述

    Spring入门到精通:第一章 基础入门:1.Spring框架概述 前言:为什么要学习Spring框架? 为什么要学习Spring框架呐? (1)使用广泛:现在很多的企业都有Spring的影子,不管是 ...

  5. 李艺《微信小程序全栈开发实战》(第一章)

    李艺<微信小程序全栈开发实战>(第一章) 双线程运行机制 小程序的特点及开发能力 小程序的特点 小程序的开发能力 开发小程序的一般流程 小程序的运行机制 小程序双线程 视图的持续更新是如何 ...

  6. 1. Vue从入门到精通(第一章 vue核心)

    Vue从入门到精通(第一章 vue核心) 第一章 Vue核心 1. Vue简介 1.1 Vue是什么? 1.2 Vue的作者以及迭代版本 1.3 Vue的特点 2. 搭建Vue开发环境 2.1 安装V ...

  7. 基于Android的手机订餐系统设计与实现(三)

    基于Android的手机订餐系统设计与实现(三) 文章目录 基于Android的手机订餐系统设计与实现(三) 一.HomeFragmet中的listItem的点击事件. 1.gain() 2.建立*C ...

  8. 基于ONNX的人物卡通化

    照片进行卡通化,是研究的重点.主要原理是检测人头分割.然后卡通化网络.直接ONNX调用,得到卡通化的效果. 效果如下图所示: C++和PYTHON都能实现,具体效果见下面链接 照片卡通化,只需要OPE ...

  9. 2022 最新 Android 基础教程,从开发入门到项目实战【b站动脑学院】学习笔记——第一章:Android开发环境搭建

    第 1 章 Android开发环境搭建 本章介绍了如何在个人电脑上搭建Android开发环境,主要包括:Android开发的发展历史是怎样的.Android Studio的开发环境是如何搭建的.如何创 ...

最新文章

  1. phpversion() 与 phpinfo()
  2. DLPack构建跨框架深度学习编译器-实现张量之间的相互转换【pytorch】
  3. 信息系统项目管理师案例分析
  4. JS读取嵌套的JSON数据
  5. MySQL UPDATE 语句一个“经典”的坑
  6. 通过引入switch表达式来增强Java switch语句
  7. redis集群搭建【简版】
  8. mysql服务器守护程序_MySQL主从服务器的守护进程监视
  9. 软件_mongo占用磁盘空间过大
  10. iOS could not set nil as the value for the key
  11. linux系统权限和用户
  12. java_eclipse中添加外部动态链接库(dll文件)的三种方式
  13. 简述RHEL7新特性(二)
  14. 2023考研王道计算机408数据结构+操作系统+计算机组成原理+计算机网络
  15. 360浏览器在b站看直播html5,用360浏览器看Bilibili视频很卡怎么办_360浏览器看B站视频卡如何解决-win7之家...
  16. Java对接苹果账号授权登录
  17. Android 设计模式之二:MVP模式与MVC模式 .
  18. Conventional-path insert(传统路径插入)
  19. 最全的WiFi速率对应表(802.11b、802.11g、802.11a、802.11n、802.11ac、802.11ax)及速率计算方法
  20. RocketMQ(七)RocketMQ消息生产及消息储存机制

热门文章

  1. java jsp班主任辅导员管理系统
  2. python单元测试框架对比_Python单元测试框架pytest常用测试报告类型
  3. windows初始化所有设置
  4. 详解Linux系统CentOS的安装步骤
  5. js下载excel表格,下载pdf
  6. Datax安装及使用文档
  7. 制作一个简单HTML电影网页设计(HTML+CSS)---电影主题网站 6页带
  8. 葛兰岱尔3D/BIM/GIS轻量化融合引擎支持Rhinoceros(犀牛)软件
  9. 云队友丨替刘强东花钱的人
  10. AUTOSAR从入门到精通-【基础软件层级篇】AUTOSAR-BSW基础软件层