今天是2017年最后一晚,希望大家元旦前夕玩得开心,准备迎接2018全新的一年,活出程序员的态度。
最近发现有些女孩在朋友圈发的自拍照肤白貌美,甚至头上魔幻般地长出猫耳朵、猫鼻子、猫胡须,各种调皮搞怪。这一切归功于程序员们不懈努力,推动科技发展,最终科技提高生活品质。美颜相机、美妆相机、秒拍、天天P图们让自拍更加精彩,带有滤镜、美颜、宠萌等各种效果。讲真的,一开始我比较好奇的是宠萌效果,认真分析后总结出实现过程经过三个步骤:人脸检测——>计算放置位置——>绘制宠萌图标。按照国际惯例,先看下图片效果:
其实,最关键是第一步:人脸检测。这里采用openCV开源库实现(如果不了解openCV这个计算机视觉开源库的,可以去官网学习:https://opencv.org/),先把openCVLibrary集成到项目里,使用训练好的haarcascade模型来初始化Detector,在摄像头每帧预览数据回调时,对图片区域搜索式扫描进行人脸检测。需要注意的是,Android使用的是Bitmap,而openCV使用的是Mat,两者需要进行转换。关键代码如下:
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
// 检测人脸
Rect[] object = mFaceDetector.detectObject(mGray, mObject);
if(object != null && object.length > 0){
//检测到人脸矩形
Rect rect = object[0];
//矩形标识
// Imgproc.rectangle(mRgba, rect.tl(), rect.br(), mFaceDetector.getRectColor(), 3);
if(beauty != null){
//添加宠萌妆饰
addBeauty((int)rect.tl().y, (int)(rect.tl().x+rect.br().x-beauty.cols())/2);
}
}
//拍照一帧数据回调
if(onPhotoTakenListener != null){
onPhotoTakenListener.onPhotoTaken(mRgba);
}
return mRgba;
}
在检测到人脸后,得到人脸在图片的矩形位置,然后计算出宠萌特效放置的位置,y轴坐标为矩形的top,x轴坐标为(矩形left+矩形right-beauty宽度)/2。接着绘制图标:
/**
* 添加宠萌效果
* @param offsetX x坐标偏移量
* @param offsetY y坐标偏移量
*/
private void addBeauty(int offsetX, int offsetY){
offsetX -= 200;//高度校正
if(offsetX < 0){
offsetX = 0;
}
for (int x=0; x<beauty.rows(); x++){
for (int y=0; y<beauty.cols(); y++){
double[] array = beauty.get(x, y);
if(array[0] != 0) {//过滤全黑像素
mRgba.put(x+offsetX, y+offsetY, array);
}
}
}
}
/**
* 获取宠萌妆饰list集合
*/
private void getBeauty(){
Drawable drawable1 = getResources().getDrawable(R.drawable.cat, null);
Bitmap bitmap1 = ((BitmapDrawable) drawable1).getBitmap();
bitmap1 = Bitmap.createScaledBitmap(bitmap1, 320, 320, true);
Mat beauty1 = new Mat();
Utils.bitmapToMat(bitmap1, beauty1);
beautyList.add(beauty1);
Drawable drawable2 = getResources().getDrawable(R.drawable.rabbit, null);
Bitmap bitmap2 = ((BitmapDrawable) drawable2).getBitmap();
bitmap2 = Bitmap.createScaledBitmap(bitmap2, 320, 320, true);
Mat beauty2 = new Mat();
Utils.bitmapToMat(bitmap2, beauty2);
beautyList.add(beauty2);
}
在拍照时,回调数据格式是Mat,需要先转成Bitmap,然后保存图片:
/**
* 保存图片
* @param frameData 帧数据
*/
private void savePicture(Mat frameData){
Bitmap bitmap = Bitmap.createBitmap(frameData.width(), frameData.height(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(frameData, bitmap);
String fileName = PATH + File.separator + dataFormat.format(new Date(System.currentTimeMillis())) + ".jpg";
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
如果觉得静态图片的宠萌效果不够酷,那么来看下拍照预览的动态效果(GIF图处理比较模糊,大家勿喷):
备注:人脸检测部分参考http://blog.csdn.net/q4878802/article/details/51841793
接下来我会继续研究美颜、滤镜、抠图。欢迎热爱图片处理与多媒体开发的同行朋友相互交流,互相学习。
文章浏览阅读3.2k次,点赞2次,收藏5次。1.只有寄存器类型变量才能在initial内部被赋值。 2.verilog系统任务 (1):finish/finish/finish/stop finish:如果遇到finish:如果遇到finish:如果遇到finish,仿真器完成仿真并退出。 stop:当遇到stop:当遇到stop:当遇到stop,仿真器停止仿真,但不退出,同时提供一个命令提示符,在命令提..._不可综合的verilog语句
文章浏览阅读903次,点赞2次,收藏2次。一.准备硬件准备树莓派 一套SIM7600CE 4G HAT 一套 (摆脱网线束缚)按照下图连接:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wq01f097-1609922520384)(https://www.waveshare.net/photo/accBoard/SIM7600CE-4G-HAT/SIM7600CE-4G-HAT-2_960.jpg)]软件准备安装minicomapt-get install minicom查看dev下面_7600 拨号设置
文章浏览阅读1.9k次。如果是在Xcode11 & IOS 13之前,如果不用storyboard创建新项目,一般是在appDelegate.swift中,例子如下,我们简单的创建一个SearchBar用UINavigationController。现在,有一些小改变,sceneDelegate.swift相比于appDelegate.swift,更像是一个top-level UI object,所..._xcode 创建ios项目没有appdelegate.swift,scenedelegate.swift
文章浏览阅读1.5k次。/etc/profile.d/colorgrep.sh:行3: /usr/libexec/grepconf.sh: 参数列表过长/etc/profile.d/vim.sh:行3: /usr/bin/id: 参数列表过长/etc/profile.d/vim.sh: 第 4 行:[: : 期待整数表达式/etc/profile:行31: /usr/bin/id: 参数列表过长_参数列表过长
文章浏览阅读4.3k次,点赞2次,收藏4次。为了解决在门户访问各子系统时出现的javascript跨域错误,我们需要安装nginx反向代理工具来将不同子系统的访问路径映射到同一URL下面。安装nginx 建议在线安装,内网环境需要挂载相应的源 yum -y install nginx 离线安装,会涉及大量的依赖的下载,可参考文档:https://blog.csdn.net/w410589502/article/de..._verynginx
文章浏览阅读1.9k次。搜索x64即可找到x64 Native Tools Command Prompt for VS 2019终端,切换路径和虚拟环境。最后执行安装pytorch3D的代码等待10分钟,就装好了《pytorch3D Windows下安装经验总结》《win10系统下安装PyTorch3d》等可能的解决方案:使用VS2019而不是VS2022,VS2019的具体小版本倒无所谓,因为我去找community社区版也只有最后一版可供下载了。_pytorch3d windows
文章浏览阅读3.7k次,点赞6次,收藏40次。1.项目简介1.1 系统研究背景伴随着中国经济的飞速发展,城市化进程的加快,求职者队伍的不断壮大,传统人才招聘的弊端初露端倪。首先,传统人才应聘的形式是求职者和企业的负责人面对面地交流。这就需要企业和求职者提前规划自己的时间,准备大量的纸质材料,并选好举办招聘会的地点,这一系列流程都需要双方把大量的精力投入到准备活动中去,使得应聘还未开始,成本就已大幅增加。其次,企业在筛选数以百计,甚至数以万计简历的时候,往往会由于阅读疲劳,漏掉一些真正有价值的简历,使得企业丧失掉一批有用的人才。对于求职者而言,也_校园人才招聘系统开发背景
文章浏览阅读327次。一、redis的安装win版本详见:下面是linux版本的安装步骤:step1、下载http://redis.io/download下载完后直接make然后make install,注意sudostep2、启动服务>cd redis安装目录/src>./redis-server //注意,这种是带默认配置启动,如果要带配置使用:>./redis-server redis-co..._linux php 添加redis
文章浏览阅读1.1k次。Bean的拷贝我们不陌生,经常与之打交道,看了很多评测,抛开功能不说,性能上前三大致就是原生的get/set、MapStruct、cglib bean copy。之所以需要是用beanCopy,就是因为大量的get/set不雅观(绝对不是我们懒)。MapStruct是在编译时期生成的代码,但是其使用让我觉得繁琐。cglib使用动态字节码技术生成class文件,在全局缓存的copier之后速度也是非常的快。但是也有很多不方便的地方,我结合实际需求,对它动了心。..._java beancopier 封装
文章浏览阅读76次。先导入jar包(commons-dbcp.jar,commons-pool.jar)方法一: 不使用配置文件BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl(..._数据库连接池管理员工信息
文章浏览阅读2.4k次,点赞2次,收藏11次。关于图像分割和hough变换(19_02_12学习进度)关于hough变换边界连接的matlab实现matlab提供了三个函数用于Hough变换连接边界,使用Hough函数可以对图像进行Hough变换,将直角坐标系变为极坐标,然后对极坐标尽心修正之后使用houghpeak函数对图像进行峰值检测,检测出密集的交点最后使用houghline函数对图像进行直线的连接Hough变换的函数为Hou..._hough变换有断点
文章浏览阅读281次。给定一个范围为 32 位 int 的整数,将其颠倒。例 1:输入: 123输出: 321 例 2:输入: -123输出: -321 例 3:输入: 120输出: 21 注意:假设我们的环境只能处理 32 位 int 范围内的整数。根据这个假设,如果颠倒后的结果超过这个范围,则返回 0。class Solution: def reverse(self, x): ""..._32位逆序