小浩浅谈之Java美颜相机pc端(视频)

在之前的文章中,给大家介绍了如果使用WebCamp来使用电脑的摄像头以及如何为图片添加各种滤镜,那么在这我们进行一个相互结合,就构成了一个我们pc端的美颜相机。

1.第一步和之前一样,就是框体 的创建,以及按钮的相关设置

public class Draw0211 {
    public void get(){
        JFrame jFrame=new JFrame();
        jFrame.setTitle("小浩美颜相机摄像");
        jFrame.setSize(800,900);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setLocationRelativeTo(null);
        BorderLayout borderLayout=new BorderLayout();
        jFrame.setLayout(borderLayout);
        //面板类对象的设定以及添加到窗体,和设置窗体的位置
        JPanel center=new JPanel();
        //颜色设定
        center.setBackground(Color.cyan);
        //设置爱完以后需要添加到窗体,否则无效
        jFrame.add(center,BorderLayout.CENTER);
        //监听器的设置
        Mouse0211 mouse0211=new Mouse0211();
        //开始定义菜单,菜单栏以及相关按钮
        JMenuBar jMenuBar=new JMenuBar();
        jFrame.add(jMenuBar,BorderLayout.NORTH);
        //定义在菜单栏中的菜单选项
        String[]name1={"文件","视频","图片","拍照","特殊滤镜","编辑","帮助"};
        //开辟一个menu数组来存储调用与添加
        JMenu[]menu=new JMenu[name1.length];
        for (int i=0;i< name1.length;i++) {
            JMenu jMenu = new JMenu(name1[i]);
            menu[i]=jMenu;
            jMenuBar.add(jMenu);
        }
        //子菜单中的菜单选项
        String[]name={"打开","关闭","退出"};
        for (int i=0;i<name.length;i++) {
            JMenuItem jMenuItem = new JMenuItem(name[i]);
            jMenuItem.addActionListener(mouse0211);
            menu[0].add(jMenuItem);
        }
        String[]name2={"打开摄像头","关闭摄像头","录制"};
        for (int i=0;i<name2.length;i++) {
            JMenuItem jMenuItem = new JMenuItem(name2[i]);
            jMenuItem.addActionListener(mouse0211);
            menu[1].add(jMenuItem);
        }
        String[]name3={"原图","马赛克","灰度","油画","珠纹","素描"};
        for (int i=0;i<name3.length;i++) {
            JMenuItem jMenuItem = new JMenuItem(name3[i]);
            jMenuItem.addActionListener(mouse0211);
            menu[2].add(jMenuItem);
        }
        String[]name4={"打开","关闭","保存"};
        for (int i=0;i<name4.length;i++) {
            JMenuItem jMenuItem = new JMenuItem(name4[i]);
            jMenuItem.addActionListener(mouse0211);
            menu[3].add(jMenuItem);
        }
        String[]name5={"怀旧","梦幻","浮雕","卷积","哈哈镜"};
        for (int i=0;i<name5.length;i++) {
            JMenuItem jMenuItem = new JMenuItem(name5[i]);
            jMenuItem.addActionListener(mouse0211);
            menu[4].add(jMenuItem);
        }
        String[]name6={"左旋转90度","右旋转90度","左旋转180度","右旋转180度"};
        for (int i=0;i<name6.length;i++) {
            JMenuItem jMenuItem = new JMenuItem(name6[i]);
            jMenuItem.addActionListener(mouse0211);
            menu[5].add(jMenuItem);
        }
        String[]name7={"撤回"};
        for (int i=0;i<name7.length;i++) {
            JMenuItem jMenuItem = new JMenuItem(name7[i]);
            jMenuItem.addActionListener(mouse0211);
            menu[6].add(jMenuItem);
        }
        jFrame.setVisible(true);
        //画笔的传输
        mouse0211.graphicsmouse=center.getGraphics();
    }
    public static void main(String[] args) {
        Draw0211 draw0211=new Draw0211();
        draw0211.get();
    }
}

2.第二步通过监听器来获取按钮的点击,来获取调动命令,并对线程的启用以及滤镜的编写

public class Mouse0211  implements ActionListener {
    //画笔
    public Graphics graphicsmouse;
    //name来获取点击的名字
    public String name;
    //类来传递数据
    public Thread0211 thread0211;
    //监听器的接口方法使用
    public void actionPerformed(ActionEvent e){
        name=e.getActionCommand();
        System.out.println("正在点击的操作按钮为:"+name);
        if ("打开摄像头".equals(name)){
            //开始启动多线程,并且同时创建线程对象则显示线程创建一次
            if (thread0211==null){
                thread0211=new Thread0211(graphicsmouse,this);
                //开始启动线程
                thread0211.start();
            }
        }else if ("关闭摄像头".equals(name)){
            thread0211.flag=false;
            System.out.println("关闭");
        }if("原图".equals(name)){
            thread0211.name="原图";
        }if ("灰度".equals(name)){
            thread0211.name="灰度";
        }if ("马赛克".equals(name)){
            thread0211.name="马赛克";
        }if ("油画".equals(name)){
            thread0211.name="油画";
        }if ("哈哈镜".equals(name)){
            thread0211.name="哈哈镜";
        }if ("珠纹".equals(name)){
            thread0211.name="珠纹";
        }if ("素描".equals(name)){
            thread0211.name="素描";
        }
    }
    //灰度算法
    public BufferedImage drawHD(int[][] pixelArr) {
        //创建缓冲区
        BufferedImage bufferedImage = new BufferedImage(pixelArr.length,
                pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
        // 获取缓冲区画笔
        Graphics buffG = bufferedImage.getGraphics();
        for (int i = 0; i < pixelArr.length; i++) {
            for (int j = 0; j < pixelArr[0].length; j++) {
                // 像素值
                int pixel = pixelArr[i][j];
                // 马赛克,灰度,底片
                // 转成Color对象,设置给画笔,画出像素点
                Color color = new Color(pixel);
                // 取出三原色
                int red = color.getRed();
                int blue = color.getBlue();
                int green = color.getGreen();
                // 算法平均值
                int num = (red + blue + green) / 3;
                Color pixelColor = new Color(num, num, num);
                //设置缓冲区的像素值
                bufferedImage.setRGB(i, j, pixelColor.getRGB());
                // 把像素点画在缓冲图片上
//                buffG.setColor(pixelColor);
//                buffG.drawLine(i + 100, j + 100, i + 100, j + 100);
            }
        }
        return bufferedImage;
    }
    //马赛克算法
    public BufferedImage drawMSK(int[][] pixelArr) {
        //创建缓冲区
        BufferedImage bufferedImage = new BufferedImage(pixelArr.length,
                pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
        // 获取缓冲区画笔
        Graphics buffG = bufferedImage.getGraphics();
        for (int i = 0; i < pixelArr.length; i += 3) {
            for (int j = 0; j < pixelArr[0].length; j += 3) {
                // 像素值
                int pixel = pixelArr[i][j];
                // 把像素点画在缓冲图片上
                buffG.setColor(new Color(pixel));
                buffG.fillRect(i, j, 10, 10);
            }
        }
        return bufferedImage;
    }
    //哈哈镜算法
    public BufferedImage drawHHJ(int x,int y,int[][] pixelArr) {;
        int w= pixelArr.length;
        int h= pixelArr[0].length;
        //计算中心点位置
        int zx=x-100;
        int zy=y-100;
        //放大半径,自己设置
        int r=100;
        //创建缓冲区
        BufferedImage bufferedImage = new BufferedImage(w,
                h, BufferedImage.TYPE_INT_RGB);
        // 获取缓冲区画笔
        Graphics buffG = bufferedImage.getGraphics();
        for (int i = 0; i <w; i++) {
            for (int j = 0; j <h;j++) {
                //计算当前位置是否在中心位置
                int tx=i-zx;
                int ty=j-zy;
                //当前点到中心点的距离
                int dis=(int) Math.sqrt(tx*tx+ty*ty);
                if (dis<r){
                    //越靠近中心点,偏移量越大
                    int nx=tx*dis/r+zx;
                    int ny=ty*dis/r+zy;
                    bufferedImage.setRGB(i,j,pixelArr[nx][ny]);
                }
            }
        }
        return bufferedImage;
    }
    //油画算法
    public BufferedImage drawYH(int[][] pixelArr) {
        //创建缓冲区
        BufferedImage bufferedImage = new BufferedImage(pixelArr.length,
                pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
        // 获取缓冲区画笔
        Graphics buffG = bufferedImage.getGraphics();
        for (int i = 0; i < pixelArr.length; i++) {
            for (int j = 0; j < pixelArr[0].length; j++) {
                int pixel = pixelArr[i][j];
                Color color = new Color(pixel);
                buffG.setColor(color);
                Random random = new Random();
                int r = random.nextInt(10) + 5;
                buffG.fillOval(i, j, r, r);
            }
        }
        return bufferedImage;
    }
    //珠纹算法
    public BufferedImage drawZW(int[][] pixelArr) {
        //创建缓冲区
        BufferedImage bufferedImage = new BufferedImage(pixelArr.length,
                pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
        // 获取缓冲区画笔
        Graphics buffG = bufferedImage.getGraphics();
        for (int i = 0; i < pixelArr.length; i += 4) {
            for (int j = 0; j < pixelArr[0].length; j += 4) {
                int pixel = pixelArr[i][j];
                Color color = new Color(pixel);
                buffG.setColor(color);
                buffG.fillOval(i, j, 8, 8);
            }
        }
        return bufferedImage;
    }
    //素描算法
    public BufferedImage drawSM(int[][] pixelArr) {
        //创建缓冲区
        BufferedImage bufferedImage = new BufferedImage(pixelArr.length,
                pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
        // 获取缓冲区画笔
        Graphics buffG = bufferedImage.getGraphics();
        for (int i = 0; i < pixelArr.length; i += 2) {
            for (int j = 0; j < pixelArr[0].length; j += 2) {
                int pixel = pixelArr[i][j];
                Color color = new Color(pixel);
                int b = color.getBlue();
                if (b < 60) {
                    buffG.setColor(Color.black);
                } else {
                    buffG.setColor(Color.WHITE);
                }
                buffG.fillOval(i, j, 4, 4);
            }
        }
        return bufferedImage;
    }
    //旋转算法
    public BufferedImage drawXZ(int[][] pixelArr) {
        //创建缓冲区
        BufferedImage bufferedImage = new BufferedImage(pixelArr.length,
                pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
        // 获取缓冲区画笔
        Graphics buffG = bufferedImage.getGraphics();
        int[][] newArr = new int[pixelArr[0].length][pixelArr.length];
        for (int i = 0, n = pixelArr.length - 1; i < pixelArr.length; i++, n--) {
            for (int j = 0; j < pixelArr[0].length; j++) {
                newArr[j][n] = pixelArr[i][j];
            }
        }
        return bufferedImage;
    }
}

3.线程类,并通过按钮调动滤镜算法

public class Thread0211 extends Thread {
    //画笔初始化
    public Graphics graphicsthread;
    //flag做标记来实现开关视频
    public boolean flag = true;
    //flag做标记来实现开关视频
    public int flag1 = 0;
    //滤镜名称
    public String name="原图";
    //类的对象构造
    public Mouse0211 mouse11;
    //处理后的缓冲图片
    public BufferedImage buffered;

    //构造方法进行参数的传递,初始化画笔对象
    public Thread0211(Graphics graphicsthread, Mouse0211 mouse11) {
        this.graphicsthread = graphicsthread;
        this.mouse11 = mouse11;
    }

    //处理线程,启动线程后运行的程序,run 方法执行完,该线程结束,线程一旦结束不能再次启动
    public void run() {
        //这个this给到的是什么
        System.out.println("启动线程.." + this.getName());
        //启动摄像头,在这个线程中使用
        Webcam webcam = Webcam.getDefault();
        webcam.open();
        while (flag) {
            // 获取摄像头拍到的数据
            BufferedImage bufferedImage = webcam.getImage();
//            if (name.equals("原图")) {
//                graphicsthread.drawImage(bufferedImage, 100, 100, 500, 400, null);
//            }
//            if (name.equals("灰度")) {
//                int[][] pixel = getImagePixel(bufferedImage);
//                buffered = mouse11.drawHD(pixel);
//                break;
//            }
//            if (name.equals("马赛克")){
//                    int[][] pixel = getImagePixel(bufferedImage);
//                    buffered = mouse11.drawMSK(pixel);
//                    System.out.println("222222222222222222");
//                    break;
//            }
            switch (name) {
                case "原图":
                    graphicsthread.drawImage(bufferedImage, 100, 100, 600,600,null);
                    break;
                case "灰度":
                    int[][] pixel = getImagePixel(bufferedImage);
                    buffered =mouse11.drawHD(pixel);
                    break;
                case "马赛克":
                    int[][] pixel1 = getImagePixel(bufferedImage);
                    buffered = mouse11.drawMSK(pixel1);
                    break;
                case "哈哈镜":
                    int[][] pixel2 = getImagePixel(bufferedImage);
                    buffered = mouse11.drawHHJ(200,200,pixel2);
                    break;
                case "油画":
                    int[][] pixel3 = getImagePixel(bufferedImage);
                    buffered = mouse11.drawYH(pixel3);
                    break;
                case "珠纹":
                    int[][] pixel4 = getImagePixel(bufferedImage);
                    buffered = mouse11.drawZW(pixel4);
                    break;
                case "素描":
                    int[][] pixel5 = getImagePixel(bufferedImage);
                    buffered = mouse11.drawSM(pixel5);
                    break;
            }
            //绘制滤镜效果
            graphicsthread.drawImage(buffered, 100, 100,600,600, null);
            if (name.equals("保存")){
                //保存图片的文件
                File file=new File("");
                try {
                    ImageIO.write(buffered,"PNG",file);
                    break;
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
    public int[][] getImagePixel(BufferedImage buffImage) {
            int w = buffImage.getWidth();
            int h = buffImage.getHeight();
            int[][] pixelArr = new int[w][h];
            // 获取图片中的每一个像素值保存到二维数组中
            for (int i = 0; i < w; i++) {
                for (int j = 0; j < h; j++) {
                    int pixel = buffImage.getRGB(i, j);
                    pixelArr[i][j] = pixel;
                }
            }
            return pixelArr;
        }
}

4.效果如下(菜单栏中些许功能没有完善,后续会继续完善)

 

 

 

(马赛克,油画,灰度,哈哈镜效果) 

猜你喜欢

转载自blog.csdn.net/weixin_64625868/article/details/123030611