【项目:实现美颜相机——java】

        我们可以用java代码实现美颜相机的功能。

类似于之前的图片处理效果:

【java用监听器实现选择处理图片的效果】_ZERO_HOPE的博客-CSDN博客

摄像头抓取的图片一帧一帧地绘制在界面上,得到视频效果。

我们对图片进行处理,就能得到滤镜效果的视频。

导包操作

先要实现摄像头类的功能,我们先需要进行导包操作;

官网下载-> IDEA中右键项目->Open Module Settings   -> Libraries -> " + "号, 寻找存放包的目录。

1、找到官网

Webcam Capture in Java (sarxos.pl)

 2、点击ZIP进行下载,将包存在一个目录中

3、如果用的是IDEA,可以参考此位dalao的下载

IDEA安装、基本使用、快捷键(超详细)_凌晨吖的博客-CSDN博客_idea 快捷键

4、右键项目 Open Module Settings -> Libraries -> " + "号, 寻找目录即可。

实现原理

        创建一个界面,用于显示摄像头抓取图片后经过处理的画面。添加按钮,用鼠标监听器来实现不同功能滤镜的切换,用动作监听器来获取点击的文本信息,进行匹配并做出对应的处理效果。

类与方法实现:

项目由四大类实现:

VideoUI(界面),VideoListener(动作监听器),PlayVideo(播放视频),VideoEff(视频效果);

下面对每一个类逐一进行分解:

一、VideoUI类

1、构造方法VideoUI:

        界面设置,创建动作监听器对象vl 。添加动作监听器对象到按钮中,最后实现可视化。

导入Webcam 包以后,创建webcam对象,获取默认值。创建playVideo 对象,将其传入监听器对象中。

2、添加按钮方法addButton

用字符串数组储存按钮文本,用循环遍历的方式添加到界面,并将按钮对象传入监听器。

3、主函数方法, main

创建对象,进入程序;

4、代码实现


public class VideoUI extends JFrame {

    public VideoUI(){
        setTitle("图像处理");       
        setSize(1000,1000);
        setDefaultCloseOperation(3); //退出方式
        setLayout(new FlowLayout()); //设置流式布局
        VideoListener vl = new VideoListener();
        addButton (vl);
        setVisible(true);

        //摄像头
        Webcam webcam = Webcam.getDefault();
        webcam.setViewSize(WebcamResolution.VGA.getSize()); //设置视图大小;
        webcam.open();       //打开摄像头;
        
        //创建PlayVideo 类对象;
        PlayVideo playVideo = new PlayVideo();

        //得将playVIdeo 传到监听器当中去
        vl.playVideo = playVideo;

        //这是死循环,之后不能再写代码,获取图像,将图像传入处理效果程序中
        playVideo.runVideo(webcam,getGraphics());

        }

    public void addButton(VideoListener vl){
        // 先定义一个字符串数组 存储所有按钮的字符串
        String[] btnstrs = {
                "原图","马赛克","刷新图片", "反片", "灰度", "二值化", "油画", "轮廓提取","珠纹化";
        };

        for(int i = 0; i < btnstrs.length; i++){
            String btnstr = btnstrs[i];
            JButton btn = new JButton (btnstr);
            add (btn);
            // 按钮添加监听器
            btn.addActionListener (vl);
        }
    }

       //主函数,程序入口
    public static void main(String[] args) {
        new VideoUI();
    }

二、VideoListener类

1、重写ActionListener类中的方法actionPerformed(ActionEvent e):

创建String 对象btnstr,用来接收动作指令,并将其设置给playVideo类中的 btnstr对象;

2、代码实现

public class VideoListener implements ActionListener {
    PlayVideo playVideo;

    @Override
    public void actionPerformed(ActionEvent e) {
        String btnstr = e.getActionCommand();
        //点击按钮之后,修改死循环中的判断所用到的变量的值
        playVideo.btnstr=btnstr;
        System.out.println("点击了"+btnstr);
    }
}

三、PlayVideo类:

1、类属性:

按钮字符串btnstr; 视频效果对象imageEff ;

2、方法runVideo:

用死循环一帧一帧处理图片。首先获取缓冲图片,将图片转化为图片数组,根据鼠标点击的按钮来对应相应的方法实现。

3、代码实现

public class PlayVideo {
    //定义一个属性 按钮文本
    String btnstr="";      //得给一个默认值,不然提示报错为空;
//VideoEff 视频效果对象imageEff 
    VideoEff imageEff = new VideoEff();
    /*
    *播放视频
    */
    public void runVideo(Webcam webcam, Graphics g){
        //用死循环来一帧一帧处理图片
        while (true){
        //1、获取图片
            BufferedImage img = webcam.getImage();
            int [][]imagePixArray = imageEff.getImagePixArray(img);
        //2、判断如何处理图片
        if(btnstr.equals("原图")){
            //不需要处理
            g.drawImage(img,100,100,null);
        }
        if(btnstr.equals("马赛克")){
            //传入图像数组,图片对象,视频效果对象调用该类中的方法来绘制
            imageEff.drawImage_02(imagePixArray,g);
        }
            if(btnstr.equals ("反片")){
                imageEff.drawImage_03(imagePixArray,g);
            }
            if(btnstr.equals ("脸部提亮")){
                imageEff.drawImage_04(imagePixArray,g);
            }
            if(btnstr.equals ("灰度")){
                imageEff.drawImage_05(imagePixArray,g);
            }
            if(btnstr.equals ("二值化")){
                imageEff.drawImage_06(imagePixArray,g);
            }
            if(btnstr.equals ("油画")){
                imageEff.drawImage_08(imagePixArray,g);
            }
            if(btnstr.equals ("轮廓提取")){
                imageEff.drawImage_09(imagePixArray,g);
            }
            if(btnstr.equals("珠纹化")) {
                imageEff.drawImage_13(imagePixArray,g);
            }
        }
    }
}

四、VideoEff类

1、类属性final 修饰不可改变的起始绘制点 坐标X=100,Y=100(可自行定义);

2、类方法:

获取图片对象的方法;实现"原图","马赛克","刷新图片", "反片", "灰度", "二值化", "油画", "轮廓提取","珠纹化"的功能方法。

3、类代码:

public class VideoEff {
    //图片绘制坐标的参数
    final int X=100;
    final int Y=100;

    /**
     * 将一张图片转为二位数
     *
     * @param buffimg
     *         缓冲图片对象
     * @return 存有图片像素值的二维数组
     */



    public int[][] getImagePixArray(BufferedImage buffimg) {

        // 获取图片尺寸
        int w=buffimg.getWidth();
        int h=buffimg.getHeight();
        //创建新的二维数组来保存图片信息
        int [][]imgarr=new int[w][h];

        for(int i=0;i<w;i++) {
            for(int j=0;j<h;j++) {
                imgarr[i][j]=buffimg.getRGB(i,j);
            }
        }
        //返回图片数组
        return imgarr;
    }



//————————————————————————————————————————————————————————————————————————————————————

//以下是绘制图片效果部分


    /**
     * 1、绘制原图方法
     * @param imgarr 图片数组
     * @param g 图像画笔对象
     */

    public BufferedImage drawImage_01(int[][] imgarr,Graphics g) {

        BufferedImage img = new BufferedImage(imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
        // 如何不绘制特殊形状, 可以考虑直接设置RGB
        for(int i=0;i<imgarr.length;i++) {
            for(int j=0;j<imgarr[i].length;j++) {
                int rgb = imgarr[i][j];
                //将RGB	遍历存入BufferedImage;
                img.setRGB(i,j,rgb);
            }
        }
        
        g.drawImage(img,X,Y,null);
        return img;
    }



     * 2、马赛克:每隔几个点取几个像素,并将图像放大 只需要在原图基础上设置取点位置以及放大g的宽和高
     * @param imgarr 图片数组
     * @param g 图像画笔对象
     */
    public BufferedImage drawImage_02(int[][] imgarr,Graphics g) {

        BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
        //获取缓冲区画
//        g = img.getGraphics();

        for(int i=0;i<imgarr.length;i+=10) {
            for(int j=0;j<imgarr[i].length;j+=10) {
                int rgb = imgarr[i][j];

                Color color =new Color(rgb);

                g.setColor(color);
                g.fillRect(X+i,Y+j,10,10);
            }
        }
        g.drawImage(img,X,Y,null);

        return img;
    }


    /**
     * 3、反片  利用获取颜色255-red,255-green,255-blue来做处理
     * @param imgarr 图片数组
     * @param g 图像画笔对象
     */
    public BufferedImage drawImage_03(int[][] imgarr,Graphics g) {
        //创建缓冲图片
        BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);

//        Graphics g1 = img.getGraphics();

        for(int i=0;i<imgarr.length;i++) {
            for(int j=0;j<imgarr[i].length;j++) {
                int rgb = imgarr[i][j];
                Color color =new Color(rgb);
                int red = color.getRed();
                int blue = color.getBlue();
                int green = color.getGreen();
                Color ncolor =new Color(255-red,255-green,255-blue);

                g.setColor(ncolor);
                g.fillRect(X+i,Y+j,1,1);
            }
        }
        g.drawImage(img,X,Y,null);

        return img;
    }

    /**
     * 4、脸部提亮
     * @param imgarr 图片数组
     * @param g 图像画笔对象
     * @return
     */
    public BufferedImage drawImage_04(int[][] imgarr,Graphics g) {

        BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);

        for(int i=0;i<imgarr.length;i++) {
            for(int j=0;j<imgarr[i].length;j++) {
                int rgb = imgarr[i][j];

                Color color =new Color(rgb);

                int red = color.getRed();
                int blue = color.getBlue();
                int green = color.getGreen();


                int grey = (int)(red*0.299+green*0.587+blue*0.114);

                Color ncolor = new Color(Math.abs(red-255+245),green,blue);
                g.setColor(ncolor);
                g.fillRect(X+i,Y+j,1,1);
            }
        }
        g.drawImage(img,X,Y,null);
        return img;
    }

    /**
     * 5、灰度处理
     * @param imgarr 图片数组
     * @param g 图像画笔对象
     * @return
     */
    public BufferedImage drawImage_05(int[][] imgarr,Graphics g) {
        //创建缓冲图片
        BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);
        //获取缓冲区笔

        for(int i=0;i<imgarr.length;i++) {
            for(int j=0;j<imgarr[i].length;j++) {
                int rgb = imgarr[i][j];
                Color color =new Color(rgb);
                int red = color.getRed();
                int blue = color.getBlue();
                int green = color.getGreen();

                //int grey = (int)(red+blue+green)/3;     较为简单的方法
//		RGB转换成灰度图像的方法
//	    Gray = R*0.299 + G*0.587 + B*0.114

              
                //更精确的表示
                int grey = (int)(red*0.299+green*0.587+blue*0.114);

                Color ncolor = new Color(grey,grey,grey);

                g.setColor(ncolor);

                g.fillRect(X+i,Y+j,1,1);
            }
        }
        g.drawImage(img,X,Y,null);
        return img;
    }

    /**
     * 6、二值化
     * @param imgarr 图片数组
     * @param g 图像画笔对象
     * @return
     */
    public BufferedImage drawImage_06(int[][] imgarr,Graphics g) {

        BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);


        for(int i=0;i<imgarr.length;i++) {
            for(int j=0;j<imgarr[i].length;j++) {
                int rgb = imgarr[i][j];
                Color color =new Color(rgb);
                int red = color.getRed();
                int blue = color.getBlue();
                int green = color.getGreen();
                
//先进行灰度化处理
                int grey = (int)(red*0.299+green*0.587+blue*0.114);
                Color ncolor = new Color(grey,grey,grey);
//用灰度值大小与110进行比较(修改参数值可以得到不同的深浅度)
                if(grey <110)
                {
                    g.setColor (Color.BLACK);
                }
                else{
                    g.setColor (Color.WHITE);
                }
                g.fillRect (100 + i, 100 + j, 1, 1);
            }
        }
        g.drawImage(img,X,Y,null);

        return img;
    }


    /**
     * 8、油画
     * @param imgarr 图片数组
     * 原理:每隔五个像素点取一个,然后用随机大小的椭圆填充每个像素点周围的区域
     * @param g 图像画笔对象
     * return
     */


    public BufferedImage drawImage_08(int[][] imgarr,Graphics g) {

        BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);

        for(int i=0;i<imgarr.length-5;i+=5) {
            for(int j=0;j<imgarr[i].length-5;j+=5) {
                int rgb = imgarr[i][j];
                Color color =new Color(rgb);

                g.setColor(color);

                Random ran=new Random();

                int r=ran.nextInt(20)+5;

                g.fillOval(X+i,Y+j,r,r);
            }
        }
        g.drawImage(img,X,Y,null);
        return img;
    }

    /**
     * 9、轮廓处理
     * @param imgarr 图片数组
     * @param g 图像画笔对象
     * @return
     */
    public BufferedImage drawImage_09(int[][] imgarr, Graphics g){
        BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);


        for(int i = 0; i < imgarr.length-1; i++){
            for(int j = 0; j < imgarr[i].length-1; j++){
                int rgb = imgarr[i][j];
                Color color = new Color (rgb);
                int red = color.getRed ();
                int green = color.getGreen ();
                int blue = color.getBlue ();
                int gray = (int) (red * 0.41 + green * 0.36 + blue * 0.23);

                // 取出右下斜方向的像素按照 灰度值 作比较
                int nrgb = imgarr[i + 1][j + 1];
                Color ncolor = new Color (nrgb);
                int nred = ncolor.getRed ();
                int ngreen = ncolor.getGreen ();
                int nblue = ncolor.getBlue ();
                int ngray = (int) (nred * 0.41 + ngreen * 0.36 + nblue * 0.23);

                if(Math.abs (gray - ngray) > 15){
                    g.setColor (Color.black);
                } else{
                    g.setColor (Color.white);
                }
                g.fillRect (X + i, Y + j, 1, 1);
            }
        }
        g.drawImage(img,X,Y,null);
        return img;
    }

  
    /**
     * 13、珠纹化
     * @param imgarr 图片数组
     * @param g 图像画笔对象
     * 原理,每隔10取一个像素点,后用大小为9的圆填充
     */
    public BufferedImage drawImage_13(int[][] imgarr,Graphics g) {
        BufferedImage img = new BufferedImage (imgarr.length,imgarr[0].length,BufferedImage.TYPE_INT_ARGB);

        for(int i=0;i<imgarr.length;i+=10) {
            for(int j=0;j<imgarr[i].length;j+=10) {
                int rgb = imgarr[i][j];
                Color color =new Color(rgb);
                g.setColor(color);
                g.fillOval(X+i,Y+j,9,9);
            }
        }
        g.drawImage(img,X,Y,null);
        return img;
    }

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
美颜相机 3.1.0 大小:22.49MB 版本:3.1.0 适用系统:Android 2.3.1以上 开发者:厦门美图网科技有限公司 应用简介 美颜相机-把手机变成自拍神器! •美图秀秀团队倾力打造!大牌明星强力推荐! •最流行的自拍软件,亿万用户正在使用, 好评率全球第一!! 专为爱自拍的女生量身定制,颠覆传统自拍效果,瞬间自动美颜,效果比化妆品神奇! 【美颜相机3.1.0更新信息】 1、“高级美颜-增高”功能惊艳登场,瞬间拥有修长美腿; 2、提升美颜效果,照片细节更清晰; 3、 全新体验,国际化界面和多语言支持~ ===== 特色亮点 ===== •自 拍• #一键变美# 一键让你的肌肤瞬间完美无暇!傻瓜式操作,七个美颜级别,量身打造你的美丽! #效果出众# 全自动磨皮、美白、降噪、瘦脸、美化眼睛,让你拥有嫩白肌肤、尖俏小v脸! #人脸识别# 通过智能的人脸识别技术和极速美颜算法,皮肤和头发细节完美呈现。 •视频自拍• 重磅推出“视频自拍”功能,最流行的10秒短视频拍摄,采用领先的视频美颜技术,令你时刻拥有水嫩肌肤,拍视频也能美美哒! •高级美颜• 1、一键美颜:只需按一下,即可变美,7种美颜风格,比化妆品还神奇; 2、磨皮美白:让皮肤白皙透亮,自然收细毛孔; 3、祛斑祛痘:轻松点掉烦恼的痘痘,祛斑不留痕; 4、瘦脸瘦身:划指间,自然修容,优化脸型,强效击退双下巴,提拉紧致瘦身,让象腿变长腿、胖妞变超模~ 5、祛黑眼圈:熬夜晚睡,也可以跟细纹、熊猫眼saygoodbye; 6、美化眼睛:让您1秒拥有水灵灵的大眼睛; 7、亮眼:加亮眼部轮廓,让你的眼睛明眸闪耀; 8、美颜特效:独家研发的多款细腻的人像特效,瞬间渗透,快速拥有惊艳面容; 还支持分享到instagram、facebook、line、微信、朋友圈、新浪微博哦,赶快下载体验吧! 如果觉得好别忘记告诉朋友哦!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值