图像滤镜功能Java实现

前置内容

  • RGB图片: 对于图片中的像素, 使用Red, Green, Blue 三种颜色共同得到一个最终的显示颜色, 其数值均在0 - 255 之间

  • 在Java中对于图像的处理可以在使用IO流得到的BufferedImage类的实例操作, 也可以读入矩阵进行操作

  • BufferedImage类实例中会提供一个Graphics实例, 可以直接对BufferedImage实例进行操作


操作前的原图

对单点像素处理的滤镜算法

在这类方法中, 对于每个像素的处理只与这个像素本身有关, 与图片的其他信息无关, 于是可以简单对每个像素进行遍历, 按照预定的方法进行逐个处理

    public void pixelRasterize(BufferedImage bufImg, String op) {Graphics g = bufImg.getGraphics();for (int i = 0; i < bufImg.getWidth(); i++) {for (int j = 0; j < bufImg.getHeight(); j++) {int pixelVal = bufImg.getRGB(i, j);int red = (pixelVal >> 16) & 0xFF;int green = (pixelVal >> 8) & 0xFF;int blue = pixelVal & 0xFF;Color color = pixelShader(red, green, blue, op);bufImg.setRGB(i, j, color.getRGB());}}this.bufImg = bufImg;}

RGB拆分

  • 对于图片中的像素, RGB数值使用一个int来表示, 由于其每种颜色只需要0 - 255, 所以仅使用了 1 byte 进行封装, 最高的8位置1, 次高的每8位依次为Red, Green, Blue

这些功能中都只需要对单个像素进行处理: 灰度化, 二值化, 去除深色背景, 负片, 复古, 明亮

    public Color pixelShader(int red, int green, int blue, String op) {switch (op) {case "Original":case "Second":return new Color(red, green, blue);case "Gray":int gray = (red + green + blue) / 3;return new Color(gray, gray, gray);case "Binary":gray = (red + green + blue) / 3;if (gray < 70)return new Color(0, 0, 0);else return new Color(255, 255, 255);case "Rid Bg":gray = (red + green + blue) / 3;if (gray > 63)return new Color(red, green, blue);else return new Color(225, 225, 225);case "Negative":red = 255 - red;green = 255 - green;blue = 255 - blue;return new Color(red, green, blue);case "OldFashion":int R = (int) (0.393 * red + 0.469 * green + 0.049 * blue);int G = (int) (0.349 * red + 0.586 * green + 0.068 * blue);int B = (int) (0.272 * red + 0.534 * green + 0.031 * blue);return new Color(R, G, B);case "Bright":red = Math.min(255, red + 10);blue = Math.min(255, blue + 10);green = Math.min(255, green + 10);return new Color(red, green, blue);}return null;}
  • 灰度化

    对于一个像素, 仅保留一个色彩通道的值, 使其三个色彩混合后只留下明暗信息

    常见做法为, 使用一个通道的数值代替所有通道, 或者平均其在三个通道上的数值

  • 二值化

    将整个图片的像素颜色进行二分类, 使其被转变为纯黑或者纯白的信息, 分类标准一般按照需求来制定

    常见做法为, 像素的灰度值高于一定数值将被认为是黑色, 否则为白色

  • 去除背景

    不基于机器学习的简单背景去除往往也不需要进行轮廓勾勒, 可以根据一定的需求去除一定范围内的颜色

    比如, 灰度值高于一定数值可以渲染原色, 而低于一定数值会被去除

  • 负片

    负片的效果为颜色反转, 只需要使用其RGB的颜色使用最大深度减去原色数值即可


这图突然有点奇怪

  • 复古

    此类特效属于数值调整类特效, 一般做法只需要按照目前成熟的参数进行调整即可

  • 明亮

    此特效需要整体上调所有通道的数值使其更偏向于白色

    常用方法为给所有通道加上固定的值, 但注意不要超过255

对区域进行采样后实现的滤镜算法

一些算法需要对图片中的某些像素进行采样, 然后用采样并处理过的数据进行滤镜操作, 这类算法一定是有损图片质量的

    public void areaSamplingRasterize(BufferedImage bufImg, String op, boolean recOrOval, int sampleSize, int fillSize) {Random rand = null;BufferedImage orgImg = new BufferedImage(bufImg.getWidth(), bufImg.getHeight(), BufferedImage.TYPE_INT_RGB);Graphics g = orgImg.getGraphics();g.drawImage(bufImg, 0, 0, null);g = bufImg.getGraphics();if (op == "Oil")rand = new Random();for (int i = 0; i < orgImg.getWidth(); i += sampleSize) {for (int j = 0; j < orgImg.getHeight(); j += sampleSize) {g.setColor(pixelShader(orgImg.getRGB(i, j), op));if (recOrOval) {g.fillRect(i, j, fillSize, fillSize);} else {int fs = fillSize;if (op.equals("Oil"))fs = rand.nextInt(fillSize) + sampleSize;g.fillOval(i, j, fs, fs);}}}this.bufImg = bufImg;}
  • 油画

    油画风格的特点是着色精细度相对较粗糙, 所以可以通过对图片进行一定的随机区域着色的方法来进行制作

    常见方法为, 对一定的采样大小区域内, 填充随机大小的圆形区域, 颜色为区域内的一个采样点的颜色, 注意填充时应尽量覆盖采样区域以免留下空白(或者使用原画作为底片), 也可以进行一点点的偏色处理

public Color pixelShader(int pixelVal, String op) {switch (op) {case "Mosaic":case "Points":case "Oil":Random rand = new Random();int red = (pixelVal >> 16) & 0xFF + (rand.nextInt(2) - 1);int green = (pixelVal >> 8) & 0xFF + (rand.nextInt(2) - 1);int blue = pixelVal & 0xFF + (rand.nextInt(2) - 1);return new Color(Math.min(255, red), Math.min(255, green), Math.min(255, blue));}return null;
}
  • 马赛克

    马赛克的简单实现就是将一个采样区域内填充成同一种采样色, 同样可以进行适当的偏色

对区域处理实现的滤镜算法

图像卷积

使用一定的卷积窗口(权重矩阵) 对一个区域内的图像进行特征的提取, 综合或过滤

public void areaConvRasterize(BufferedImage bufImg, String op, int kernelSize, double[] rights) {BufferedImage orgImg = new BufferedImage(bufImg.getWidth(), bufImg.getHeight(), BufferedImage.TYPE_INT_RGB);Graphics g = orgImg.getGraphics();g.drawImage(bufImg, 0, 0, null);for (int i = 0; i < orgImg.getWidth(); i++) {for (int j = 0; j < orgImg.getHeight(); j++) {int reds = 0, greens = 0, blues = 0;int edgeSize = (int) Math.sqrt(kernelSize);int mx = Math.min(orgImg.getWidth(), i + edgeSize);int my = Math.min(orgImg.getHeight(), j + edgeSize);ArrayList<Integer> pixelVal = new ArrayList(kernelSize);for (int nx = i; nx < mx; nx++) {for (int ny = j; ny < my; ny++) {pixelVal.add(orgImg.getRGB(nx, ny));}}while (pixelVal.size() < kernelSize) {pixelVal.add(orgImg.getRGB(i, j));}int x = Math.min(mx - 1, i + edgeSize / 2);int y = Math.min(my - 1, j + edgeSize / 2);bufImg.setRGB(x, y, convPixelShader(kernelSize, pixelVal, op, new int[]{x, y}).getRGB());}}this.bufImg = bufImg;}

常见的卷积一般以卷积窗口覆盖的中心作为目标对象, 所以对于边界来说, 处理方法一般为认为图片无限重复或者直接抛弃边界

   public Color convPixelShader(int kernelSize, ArrayList<Integer> pixelVal, String op, int[] centerPos) {int radius = (int) Math.sqrt(kernelSize);double[] rights = new double[kernelSize];int reds = 0, greens = 0, blues = 0;switch (op) {case "Sharpen":Arrays.fill(rights, 0, kernelSize, -1);rights[kernelSize >> 1] = 9;break;case "Blur":int l = 0;for (int x = -radius >> 1; x < radius >> 1; x++) {for (int y = 0; y < radius; y++) {rights[l++] = Math.pow((int) Math.E, -(x * x + y * y) / (2 * GuassBlur.sigma * GuassBlur.sigma))/ (2 * pi * GuassBlur.sigma * GuassBlur.sigma);}}break;}for (int i = 0; i < kernelSize; i++) {reds += ((pixelVal.get(i) >> 16) & 0xFF) * rights[i];greens += ((pixelVal.get(i) >> 8) & 0xFF) * rights[i];blues += (pixelVal.get(i) & 0xFF) * rights[i];}reds += 20;greens += 20;blues += 20;reds = Math.min(255, reds);reds = Math.max(0, reds);greens = Math.min(255, greens);greens = Math.max(0, greens);blues = Math.min(255, blues);blues = Math.max(0, blues);return new Color(reds, greens, blues);}
  • 锐化

    锐化操作的目的是增强图片中不同颜色间边界的对比度, 突出边界

    其卷积核相对固定,常用为 3x3 卷积 的 (1,1)位置为9, 其他位置为 -1 的权重矩阵

  • 模糊

    模糊操作的实现有很多, 以高斯模糊为例, 其需要通过计算某像素相邻位置对该像素的影响来得到结果,其公式为

    ​ (x,y)为卷积核的中心坐标, 一般作为坐标原点
    效果一般取决于模糊半径和σ

简单图像滤镜功能的Java实现相关推荐

  1. 从零开始开发Android相机app(三)简单介绍图像滤镜功能

    目前章节 1.从零开始安卓端相机功能开发(一)了解用什么去开发以及流程 2.从零开始安卓端相机功能开发(二)让我们来开发一个相机 3.从零开始开发Android相机app(三)简单介绍图像滤镜功能 文 ...

  2. Java图片gh颜色渐变_强大的Java图像滤镜特效类库Java Image Filters

    Java Image Filters是一款基于Java的图像处理类库,特别是在图像滤镜特效方面,Java Image Filters简直就是强大到天衣无缝.它几乎提供了PS上大部分的图像特效.比如反色 ...

  3. 用Java实现相机滤镜功能(一)

    今天我们来用java实现相机滤镜功能.显然首先要有一个窗体,所以我们创建类来设置窗体,类名取为VideoCapture,这里我们简写一下,让VideoCapture类继承JFrame,作为它的子类,然 ...

  4. java商品搜索功能_JavaWeb实现简单查询商品功能

    本文实例为大家分享了javaWeb实现简单查询商品功能的具体代码,供大家参考,具体内容如下 CustomerServlet.java package com.subing.web; import ja ...

  5. java 手机声音提醒功能_Android基于广播事件机制实现简单定时提醒功能代码

    本文实例讲述了Android基于广播事件机制实现简单定时提醒功能代码.分享给大家供大家参考,具体如下: 1.Android广播事件机制 Android的广播事件处理类似于普通的事件处理.不同之处在于, ...

  6. mysql+jdbc连接数据库简单实现登录功能 --java

    初识java web 实现简单的登录功能 mvc结构实现mysql 连接 什么是mvc MVC是模型(model).视图(view).控制(controller)这三个单词上的首字母组成.它是一种应用 ...

  7. Java调用百度API实现文本与图像审核功能

    文档: API文档:https://ai.baidu.com/ai-doc/ANTIPORN/ek3h6x90n SDK下载:https://ai.baidu.com/sdk#anti github链 ...

  8. java的简单数字时钟_Java实现的简单数字时钟功能示例

    本文实例讲述了java实现的简单数字时钟功能.分享给大家供大家参考,具体如下: 应用名称:java数字时钟 用到的知识:java gui编程,线程 开发环境:win8+eclipse+jdk1.8 功 ...

  9. java简单atm_Java实现简单银行ATM功能

    本文实例为大家分享了Java实现简单银行ATM功能的具体代码,供大家参考,具体内容如下 实现功能 1.用户需要通过输入银行卡号和密码才能进入ATM系统 2.用户可以在ATM中实现取款.存款.转账.余额 ...

最新文章

  1. centos环境变量设置
  2. [魔方]28秒!地铁站真是个破纪录的好地方
  3. n!mod p 的求法 数学
  4. hibernate Disabling contextual LOB creation as connection was null
  5. java鼠标图片裁剪,如何用Java中的鼠标指针捕获屏幕图像
  6. 防火墙(12)——查看协议被连接的次数、通过连接状态来写规则
  7. I - Ant Trip (无向图欧拉回路+并查集),判断
  8. Android之使用getIdentifier()获取资源Id
  9. awt jtable 多线程加载图片_Java项目实战之天天酷跑(三):缓冲加载游戏界面
  10. zoj 1074 To the MAX
  11. 程序员的进阶课-架构师之路(8)-二叉树
  12. 基于alsa的音量控制代码
  13. java进程因机器内存不足被系统kill的定位
  14. C# 事件和Unity3D
  15. [转贴]怎样学好法语?
  16. 测试计划与测试方案区别
  17. 计算机械效率的公式四种,初级中学物理计算公式定律整编汇总.doc
  18. 运放的开环增益和相移
  19. 写乐100道练习题_【写乐钢笔使用】_摘要频道_什么值得买
  20. w ndows10系统怎么退出安全模式,Windows 10安全模式怎么解除

热门文章

  1. 学校运动会广播稿计算机,学校运动会广播稿十篇
  2. oracle sql中( ),Oracle SQL中的函数
  3. Cent OS 7.4 1708 下载安装
  4. Page Cache 与 Kafka 那些事儿
  5. matlab里面sin函数是角度,matlab-如何用matlab编写sin函数要求定义一 – 手机爱问
  6. ⑦Java SE知识点回顾与小结(面向对象)
  7. 2021中国AI产业10大趋势,一分钟看明白 | WAIC2021
  8. 中央电大 c语言程序设计a 试题,中央电大2008年秋C语言程序设计A试题1
  9. c/c++通过域名解析ip地址
  10. 计算机毕业设计Python+uniapp学生考勤系统小程序(小程序+源码+LW)