图片处理——基于openCV实现美颜相机_opencv android 相机预览实现改变除鼻子嘴巴眼睛外的颜色-程序员宅基地

技术标签: 美颜相机  宠萌妆饰  人脸识别  

        今天是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

        接下来我会继续研究美颜、滤镜、抠图。欢迎热爱图片处理与多媒体开发的同行朋友相互交流,互相学习。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u011686167/article/details/78943824

智能推荐

Verilog语法(不可综合)_不可综合的verilog语句-程序员宅基地

文章浏览阅读3.2k次,点赞2次,收藏5次。1.只有寄存器类型变量才能在initial内部被赋值。 2.verilog系统任务 (1):finish/finish/finish/stop finish:如果遇到finish:如果遇到finish:如果遇到finish,仿真器完成仿真并退出。 stop:当遇到stop:当遇到stop:当遇到stop,仿真器停止仿真,但不退出,同时提供一个命令提示符,在命令提..._不可综合的verilog语句

SIM7600X PPP 拨号并开机自启动_7600 拨号设置-程序员宅基地

文章浏览阅读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 拨号设置

不用storyboard创建新项目之SceneDelegate.swift (Xcode 11 & IOS 13)_xcode 创建ios项目没有appdelegate.swift,scenedelegate.swi-程序员宅基地

文章浏览阅读1.9k次。如果是在Xcode11 & IOS 13之前,如果不用storyboard创建新项目,一般是在appDelegate.swift中,例子如下,我们简单的创建一个SearchBar用UINavigationController。现在,有一些小改变,sceneDelegate.swift相比于appDelegate.swift,更像是一个top-level UI object,所..._xcode 创建ios项目没有appdelegate.swift,scenedelegate.swift

【 -bash: /usr/bin/id: 参数列表过长】-程序员宅基地

文章浏览阅读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: 参数列表过长_参数列表过长

nginx配置说明以及VeryNginx使用-程序员宅基地

文章浏览阅读4.3k次,点赞2次,收藏4次。为了解决在门户访问各子系统时出现的javascript跨域错误,我们需要安装nginx反向代理工具来将不同子系统的访问路径映射到同一URL下面。安装nginx 建议在线安装,内网环境需要挂载相应的源 yum -y install nginx 离线安装,会涉及大量的依赖的下载,可参考文档:https://blog.csdn.net/w410589502/article/de..._verynginx

win下配置pytorch3d_pytorch3d windows-程序员宅基地

文章浏览阅读1.9k次。搜索x64即可找到x64 Native Tools Command Prompt for VS 2019终端,切换路径和虚拟环境。最后执行安装pytorch3D的代码等待10分钟,就装好了《pytorch3D Windows下安装经验总结》《win10系统下安装PyTorch3d》等可能的解决方案:使用VS2019而不是VS2022,VS2019的具体小版本倒无所谓,因为我去找community社区版也只有最后一版可供下载了。_pytorch3d windows

随便推点

基于Springboot的大学生招聘网站系统_校园人才招聘系统开发背景-程序员宅基地

文章浏览阅读3.7k次,点赞6次,收藏40次。1.项目简介1.1 系统研究背景伴随着中国经济的飞速发展,城市化进程的加快,求职者队伍的不断壮大,传统人才招聘的弊端初露端倪。首先,传统人才应聘的形式是求职者和企业的负责人面对面地交流。这就需要企业和求职者提前规划自己的时间,准备大量的纸质材料,并选好举办招聘会的地点,这一系列流程都需要双方把大量的精力投入到准备活动中去,使得应聘还未开始,成本就已大幅增加。其次,企业在筛选数以百计,甚至数以万计简历的时候,往往会由于阅读疲劳,漏掉一些真正有价值的简历,使得企业丧失掉一批有用的人才。对于求职者而言,也_校园人才招聘系统开发背景

linux php添加redis,linux下的redis安装以及php添加redis扩展-程序员宅基地

文章浏览阅读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

关于我封装了BeanCopier这件事_java beancopier 封装-程序员宅基地

文章浏览阅读1.1k次。Bean的拷贝我们不陌生,经常与之打交道,看了很多评测,抛开功能不说,性能上前三大致就是原生的get/set、MapStruct、cglib bean copy。之所以需要是用beanCopy,就是因为大量的get/set不雅观(绝对不是我们懒)。MapStruct是在编译时期生成的代码,但是其使用让我觉得繁琐。cglib使用动态字节码技术生成class文件,在全局缓存的copier之后速度也是非常的快。但是也有很多不方便的地方,我结合实际需求,对它动了心。..._java beancopier 封装

数据库连接池的使用--DBCP_数据库连接池管理员工信息-程序员宅基地

文章浏览阅读76次。先导入jar包(commons-dbcp.jar,commons-pool.jar)方法一: 不使用配置文件BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl(..._数据库连接池管理员工信息

关于hough变换边界连接的matlab实现_hough变换有断点-程序员宅基地

文章浏览阅读2.4k次,点赞2次,收藏11次。关于图像分割和hough变换(19_02_12学习进度)关于hough变换边界连接的matlab实现matlab提供了三个函数用于Hough变换连接边界,使用Hough函数可以对图像进行Hough变换,将直角坐标系变为极坐标,然后对极坐标尽心修正之后使用houghpeak函数对图像进行峰值检测,检测出密集的交点最后使用houghline函数对图像进行直线的连接Hough变换的函数为Hou..._hough变换有断点

leetcode-7颠倒整数_32位逆序-程序员宅基地

文章浏览阅读281次。给定一个范围为 32 位 int 的整数,将其颠倒。例 1:输入: 123输出: 321 例 2:输入: -123输出: -321 例 3:输入: 120输出: 21 注意:假设我们的环境只能处理 32 位 int 范围内的整数。根据这个假设,如果颠倒后的结果超过这个范围,则返回 0。class Solution: def reverse(self, x): ""..._32位逆序

推荐文章

热门文章

相关标签