图像处理方法java(一)

目录

  • 图像处理方法java(一)
    • 1.引言
    • 2.基本原理
      • 2.1图像的基本原理
      • 2.2图像数据的处理
      • 2.3位运算
    • 3.图片读写与滤镜效果
      • 3.1图片读写
      • 3.2滤镜效果
        • 3.2.1原图输出
        • 3.2.2马赛克
        • 3.2.3灰度
        • 3.2.4滤镜颜色
        • 3.2.5轮廓
    • 4.交互式处理
      • 4.1带按钮的窗体
      • 4.2动作监听器
      • 4.3综合起来
        • 4.3.1创建ImageUtils类
        • 4.3.2创建ImageListener类
        • 4.3.3创建ImageUI类
        • 4.3.4运行结果
    • 5.心得体会

1.引言

  初学java,想做一个简易的美颜相机,对图像处理的一些方法进行了相应的学习。主要包括图像的原理、图像的数据处理、位运算、滤镜效果、图片读写等。

2.基本原理

2.1图像的基本原理

  每一张图像,其实都是由一个个的带有颜色的点组成的矩阵,也就是我们常说的像素点矩阵,同时横纵坐标像素点的个数乘积就是图像的分辨率。
  每一个像素点的颜色,都是有相应的编号的,一般的存储格式是RGB和ARGB格式。RGB格式:RGB其实就是三原色,Red、Green、Blue,每一种原色的编号范围是0-255,也就是存储在一个字节(8位2进制)中。Red从0到255颜色会越来越“红”,红的程度会加深。
  举个例子来说,对于RGB: 123, 200,13 来说,这个颜色是由Red123,Green200,Blue13这三种颜色合成的。
  所以我们很容易知道,RGB是占三个字节,可以存储在整型变量(四个字节)中,并且存储在低24位,那么就会出现高8位没有使用的情况。ARGB格式就是把高8位也利用起来,用来存其他的信息例如照片拍摄日期等等。

2.2图像数据的处理

  初始化生成一个窗体,然后通过随机数随机生成一张RGB格式的图片。通过位移运算计算RGB格式里red、green、blue的值(位移运算在2.3会讲解)。对于滤镜等操作,就可以通过调节red、green、blue的值来实现,比如说red=red/2,就能实现图片红色降度,也就是照片的红色不会太鲜艳。
  我们常常也会听说灰度图片,就是照片会变成灰色,这种照片的每一个像素点的RGB值均满足red=green=blue,我们可以调整三原色的占比来确定灰阶(详见代码)。
  二维码:有了灰阶,也就是对每一个像素值都有唯一标准了。我们可以确定一个分界值a,当算出的灰度值大于a,就用白色来表示;若小于a,就用黑色来表示,并且使用fiilRect方法的时候,把像素点的宽和高调大一点,我们就可以得到这张图片的二维码了,也就是说,这个二维码储存了我这张图片的数据。

import javax.swing.*;
import java.awt.*;
import java.util.Random;import javax.swing.JFrame;
public class ImageUI extends JFrame {//初始化一个窗体public void initUI(){setTitle("图像编程");setSize(1000,1000);setVisible(true);setDefaultCloseOperation(EXIT_ON_CLOSE);}/** 窗体出现在屏幕上时调用* 绘制窗体本身* 在窗体上绘制像素点* @param g :图形对象 可以来绘制图形* Graphics 图形* g.fillRect(x,y,w,h);*/public void paint(Graphics g){super.paint(g);//g.fillRect(100,100,10,10);int[][] imgarr=new int[300][300];// 随机创建颜色矩阵Random random = new Random();for (int i = 0; i < 300; i++) {for (int j = 0; j < 300; j++) {int colorValue = random.nextInt(256*256*256);imgarr[i][j]=colorValue;Color color = new Color(colorValue);g.setColor(color);g.fillRect(50+i,50+j,1,1);}}for (int i = 0; i <imgarr.length; i+=10) {for (int j = 0; j < imgarr[i].length; j+=10) {int value = imgarr[i][j];int red =(value>>16)&0xFF;int green =(value>>8)&0xFF;int blue =(value>>0)&0xFF;// 灰度 r=g=b// 有了灰阶 一张照片所有的像素值都具有同样的标准了int gray =(int)(red*0.36+green*0.29+blue*0.35);if(gray>128){g.setColor(Color.white);}else{g.setColor(Color.black);}g.fillRect(400+i,50+j,10,10);}}}// 启动程序public static void main(String[] args) {ImageUI img = new ImageUI();img.initUI();}
}

运行图片

2.3位运算

  这里主要讲如何通过存储RGB的整型int得到red、green、blue的值;以及red、green、blue如何合成为一个int。
  我们了解了RGB的存储原理,很容易知道:17-24位存red,9-16位存green,1-8位存blue,用除法和减法可以提取出red、green、blue,但是这样运算速度会慢一些,可以用位移运算,运算速度会快一些。
  假设RGB的值存储在int value中,通过位移运算有:
      int red =(value>>16)&0xFF;
      int green =(value>>8)&0xFF;
      int blue =(value>>0)&0xFF;
为什么要位移之后与0xFF求与运算呢? 仔细分析后,我们知道,与0xFF做与运算后,可以将除低8位以外的所有位的数字变为0。
  所以我们以此类推,我们发现把red、green、blue合成一个RGB时,可以通过位移加上或运算来实现:
      int rgb= (red<<16)|(green<<8)|blue;

3.图片读写与滤镜效果

3.1图片读写

  图片的输入,我写了一个输入图片的方法,加上想要读取的图片路径,路径是相对路径和绝对路径都可以,我的图片和代码是放在一个文件夹里的,所以用的相对路径。
使用ImageIO.read()方法的时候,需要创建BufferedImage类的对象

    int[][] imgarr = getImagePixArr("picture4.jpeg");//这里imgarr是创建的二维数组,用来存储图片的像素点矩阵。public int[][] getImagePixArr(String path){// 声明一个文件对象File file = new File(path);BufferedImage buffimg=null;try {// 处理文件IO异常// 读取为 buffimg 对象buffimg = ImageIO.read(file);} catch (IOException e) {e.printStackTrace();}// 宽 高 图片类型 ARGBint 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;}

  图片输出的话也是一样,也需要创建BufferedImage类的对象,代码如下:

public void outImagePixArr(int[][] imgarr ,String path){// 声明一个文件对象File file = new File(path);BufferedImage buffimg = 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++){buffimg.setRGB(i, j, imgarr[i][j]);}}try {// 处理文件IO异常// 读取为 buffimg 对象ImageIO.write(buffimg, "PNG", file);} catch (IOException e) {e.printStackTrace();//return;}}

3.2滤镜效果

3.2.1原图输出

    // 原图for (int i = 0; i < imgarr.length; i++) {for (int j = 0; j < imgarr[i].length; j++) {Color color = new Color(imgarr[i][j]);g.setColor(color);g.fillRect(i,j,1,1);}}

3.2.2马赛克

  马赛克就是模糊处理,把一个像素点的长宽变大即可。

// 马赛克for (int i = 0; i < imgarr.length; i+=10) {for (int j = 0; j < imgarr[i].length; j+=10) {Color color = new Color(imgarr[i][j]);g.setColor(color);g.fillRect(750+i,j,10,10);}}

3.2.3灰度

  在前面已经讲过,灰度图片的red=green=blue。

// 灰度for (int i = 0; i < imgarr.length; i++) {for (int j = 0; j < imgarr[i].length; j++) {int value = imgarr[i][j];int red=(value>>16)&0xFF;int green=(value>>8)&0xFF;int blue=(value>>0)&0xFF;int gray = (red+green+blue)/3;Color color = new Color(gray,gray,gray);g.setColor(color);g.fillRect(i,400+j,1,1);}}

3.2.4滤镜颜色

  这个滤镜是我自己调的,可能不是很好看,red变为原来的0.8,green变成原来的0.5,blue变成原来的0.6。

//滤镜for (int i = 0; i < imgarr.length; i++){for (int j = 0; j < imgarr[i].length; j++){int value = imgarr[i][j];int red=(value>>16)&0xFF;int green=(value>>8)&0xFF;int blue=(value>>0)&0xFF;red = red*4/5;green = green/2;blue = blue*3/5;//imgarr1 = (red<<16)|(green<<8)|blue;Color color = new Color(red,green,blue);g.setColor(color);g.fillRect(i,400+j,1,1);}}

3.2.5轮廓

//轮廓for (int i = 0; i < imgarr.length-2; i++) {for (int j = 0; j < imgarr[i].length-2; j++) {int value = imgarr[i][j];int red=(value>>16)&0xFF;int green=(value>>8)&0xFF;int blue=(value>>0)&0xFF;int gray = (red+green+blue)/3;int nvalue = imgarr[i+2][j+2];int nred=(nvalue>>16)&0xFF;int ngreen=(nvalue>>8)&0xFF;int nblue=(nvalue>>0)&0xFF;int ngray = (nred+ngreen+nblue)/3;if(Math.abs(gray-ngray)>10){g.setColor(Color.white);}else{g.setColor(Color.black);}// Color color = new Color(ngray,ngray,ngray);g.fillRect(750+i,400+j,1,1);}}

运行图片

4.交互式处理

4.1带按钮的窗体

  创建一个UI类,可以生成带按钮的窗体。那个布局方法是自动把按钮布局。

import javax.swing.*;
import java.awt.*;
import javax.swing.JFrame;
public class UI extends JFrame{// 构造方法// 创建对象时调用String[] strs={"原图","灰度","怀旧","马赛克","二值化","融合","轮廓"};public void initUI() {setTitle("图像窗体");setSize(2200, 1000);setVisible(true);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//布局FlowLayout fl =new FlowLayout();setLayout(fl);for (int i = 0; i < strs.length; i++) {JButton btn = new JButton(strs[i]);add(btn);}setVisible(true);}public static void main(String[] args) {UI img = new UI();img.initUI();}
}

运行结果

但是我们在窗体上点击按钮,是没有反应的,于是我们需要一个Listener类,也就是监听器,来监听按钮是否被点击,如果被点击就会进行相应操作。

4.2动作监听器

  ActionListener——动作监听器,作用是监听按钮是否被点击了,如果被点击了就调用一个预设好的方法(方法的内容需要自己来写 )。实现接口interface时,用implements关键字,可以变相实现多继承。

import java.awt.event.ActionListener;
// 1:首先创建一个类 使用 implements ActionListener
public class ImageListener implements ActionListener{// 2:重写ActionListener 中的方法public void actionPerformed(ActionEvent e){// 3: 点什么按钮就绘制什么图像System.out.println("点击了按钮 ");}
}

运行结果:点一下按钮就会输出“点击了按钮 ”

4.3综合起来

  前文讲了很多细节的处理以及方法,现在我们就可以创建一个窗体,一个有按钮的窗体,点击按钮能得到相应“滤镜”的图片,不再是4.1那样没有反应的按钮;也不再是4.2只输出一句话,我们重写方法后,可以把图片输出在窗体上。

4.3.1创建ImageUtils类

  创建这个工具类目的有两个:第一,读取某个路径下的图片,把他存在我们的像素点矩阵imgarr(二维数组)中,这个我在3.1中有介绍;第二,就是能把处理后的像素点矩阵“画出来”,也就是图片。

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;public class ImageUtils {public int[][] getImagePixArr(String path){// 声明一个文件对象File file = new File(path);BufferedImage buffimg=null;try {// 处理文件IO异常// 读取为 buffimg 对象buffimg = ImageIO.read(file);} catch (IOException e) {e.printStackTrace();}// 宽 高 图片类型 ARGBint 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;}public void drawImage0(int[][] imgarr,Graphics g){for (int i = 0; i < imgarr.length; i++) {for (int j = 0; j < imgarr[i].length; j++) {Color color = new Color(imgarr[i][j]);g.setColor(color);g.fillRect(100+i,100+j,1,1);}}}
}

4.3.2创建ImageListener类

  创建这个动作监听器类,作用是监听按钮是否被点击了,如果点击了就调用相应的方法。我们在4.2中重写了方法,点击就会输出“点击了按钮 ”;现在,我们再次重写方法,点击相应的按钮,就输出对应按钮的图片。(这里我只重写了输出原图的方法,输出其他“滤镜”图片的方法只需要把3.2中的代码粘贴修改即可)

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class ImageListener implements ActionListener{Graphics gr;ImageUtils imageUtils = new ImageUtils();int[][] imgarr=null;{   // 初始化的代码块 创建对象时执行imgarr = imageUtils.getImagePixArr("picture4.jpeg");}// 2:重写ActionListener 中的方法public void actionPerformed(ActionEvent e){// 3: 点什么按钮就绘制什么图像// 如何区分 按钮//获取按钮的字符串String btnstr = e.getActionCommand();//System.out.println("点击了 按钮 "+btnstr);if(btnstr.equals("原图")){// 绘制原图// gr.drawString(btnstr,200,200);imageUtils.drawImage0(imgarr,gr);}}
}

4.3.3创建ImageUI类

  创建这个类,其实就是输出带有按钮的窗体,参考4.1,代码如下:

import javax.swing.*;
import java.awt.*;public class ImageUI extends JFrame {// 构造方法// 创建对象时调用String[] strs={"原图","灰度","怀旧","马赛克","二值化","融合","轮廓"};public ImageUI(String title) {setTitle(title);setSize(1000, 1000);setVisible(true);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//布局FlowLayout fl =new FlowLayout();setLayout(fl);// 监听器对象ImageListener imageL = new ImageListener();for (int i = 0; i < strs.length; i++) {JButton btn = new JButton(strs[i]);btn.setBackground(Color.white);btn.addActionListener(imageL);// 所有的按钮都注册了监听器add(btn);}setVisible(true);// 获取画笔Graphics g = this.getGraphics();imageL.gr=g;}public static void main(String[] args) {new ImageUI("图像处理编程");}}

4.3.4运行结果

  (1)没有点击按钮时:

  (2)点击按钮“原图”时:

5.心得体会

  本文到这里就结束了,后面博客会补充更“厉害”的图像处理方法,如PS等。一介java小白,欢迎大家批评指正。

Java图像处理(后面会补充PS啥的)相关推荐

  1. Java 200+ 面试题补充② Netty 模块

    让我们每天都能看到自己的进步.老王带你打造最全的 Java 面试清单,认真把一件事做到最好. 本文是前文<Java 最常见的 200+ 面试题>的第二个补充模块,第一模块为:<Jav ...

  2. Java图像处理方面的工具库和开发包

    Java图像处理类库Java Image Filters Java Image Filters 是由 Jhlabs 开发的一组用来处理 Java 图像的类库,提供各种常用的图像处理效果,例如反转色.扭 ...

  3. java图像处理-(指定区域内)灰度化、透明化(alpha通道)处理

    java图像处理-(指定区域内)灰度化.透明化(alpha通道)处理 2016年07月25日 21:23:16 阅读数:3944 近日在一家小公司实习,老板要求我写一个图形编辑器,其中涉及到用java ...

  4. java毕业设计——基于java+图像处理技术的医学图像处理系统设计与实现(毕业论文+程序源码)——医学图像处理系统

    基于java+图像处理技术的医学图像处理系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+图像处理技术的医学图像处理系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦 ...

  5. Java图像处理--------RGB调色面板

    Java图像处理--------RGB调色面板 一:概述 因为我们知道颜色是由R.G.B.三种颜色所组成的,那么我们只需要更改这三个的数值.我们就可以实现一个简单的调色面板:以下是代码演示: 二:代码 ...

  6. Java 图像处理教程(人脸检测,添加水印,图像颜色转换)

    Java 图像处理教程(人脸检测,添加水印,图像颜色转换) 文章目录 Java 图像处理教程(人脸检测,添加水印,图像颜色转换) 1:图片的读和写 2:彩色图像转换成灰度图像 3:彩色图像转换成负图像 ...

  7. java imageio处理图像_Linux geoserver调优之Java图像处理优化(原生JAI和ImageIO和java默认库相互转换)...

    注:geoserver 版本 Linux geoserver2.15.0    安装 :bin方式安装(内嵌jetty,非war安装) 一.geoserver调优之Java图像处理优化 1.原生JAI ...

  8. OpenCV3.2 Java图像处理视频学习教程-贾志刚-专题视频课程

    OpenCV3.2 Java图像处理视频学习教程-2434人已学习 课程介绍         OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java Ope ...

  9. [附源码]JAVA毕业设计绿色生活基于PS、DW的绿色环保宣传网站(系统+LW)

    [附源码]JAVA毕业设计绿色生活基于PS.DW的绿色环保宣传网站(系统+LW) 项目运行 环境项配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm ...

最新文章

  1. Hbase完全分布式的搭建
  2. Bzoj 4548: 小奇的糖果(双向链表+排序+树状数组)
  3. 【渝粤教育】国家开放大学2018年秋季 8177-21T (1)工程经济与管理 参考试题
  4. intern_充分利用Outreachy Intern申请流程
  5. OpenShift 4 - DevSecOps Workshop (5) - 为Pipeline增加测试Task
  6. Iocomp.Ultra Pack V5.SP3 for .Net Crack
  7. ANDROID框架揭秘
  8. 电驴让分享继续 服务器不稳定,为什么越来越多的人不再使用eD2k了?回顾电驴的兴与衰...
  9. redhat linux 7的新特性,RHEL7新特性及RHEL6功能对比
  10. 扬帆际海—开网店怎么引流推广?
  11. ffmpeg-nvenc
  12. 初涉网络,自己对服务器的一些基础理解
  13. IDEA创建applicationContext.xml文件图标不是xml文件图标
  14. docker学习 --Compose 容器编排,常用命令等.集成spring。mysql。redis
  15. 关闭iphone来电mac_如何在Mac和iPhone上关闭通用剪贴板切换(以及为什么要禁用此功能)
  16. 【帅琪达】git相关面试题目
  17. 2023年中南财经政法大学西方经济学考研上岸前辈初复试备考经验
  18. 2023年全国最新会计专业技术资格精选真题及答案59
  19. Python丨小学妹喜欢看漫画,于是我写了四十行代码获取了它所有漫画
  20. java 整数规划_线性规划与整数规划求解速度对比

热门文章

  1. 快手本地生活可以入场吗
  2. linux下的扫描软件,4个用于Linux系统的扫描软件 - 爱绿豆
  3. python idle怎么保存_Word文档如何设置自动保存
  4. 大学生会计技能竞赛总决赛(三)
  5. 【定位问题】基于matlab chan算法、fang算法、taylor算法求解目标定位问题【含Matlab源码 2135期】
  6. 遭遇win10激活问题
  7. [禅悟人生]在劳动中品味幸福
  8. android 取imei p10,华为p10如何解锁BootLoader 华为p10解锁BootLoader图文教程
  9. 相敏检波电路matlab,一种消除分布电容影响的电阻测量方法
  10. 人人商城 邀请人 成功购买会员卡之后返现