简单图像滤镜功能的Java实现
图像滤镜功能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实现相关推荐
- 从零开始开发Android相机app(三)简单介绍图像滤镜功能
目前章节 1.从零开始安卓端相机功能开发(一)了解用什么去开发以及流程 2.从零开始安卓端相机功能开发(二)让我们来开发一个相机 3.从零开始开发Android相机app(三)简单介绍图像滤镜功能 文 ...
- Java图片gh颜色渐变_强大的Java图像滤镜特效类库Java Image Filters
Java Image Filters是一款基于Java的图像处理类库,特别是在图像滤镜特效方面,Java Image Filters简直就是强大到天衣无缝.它几乎提供了PS上大部分的图像特效.比如反色 ...
- 用Java实现相机滤镜功能(一)
今天我们来用java实现相机滤镜功能.显然首先要有一个窗体,所以我们创建类来设置窗体,类名取为VideoCapture,这里我们简写一下,让VideoCapture类继承JFrame,作为它的子类,然 ...
- java商品搜索功能_JavaWeb实现简单查询商品功能
本文实例为大家分享了javaWeb实现简单查询商品功能的具体代码,供大家参考,具体内容如下 CustomerServlet.java package com.subing.web; import ja ...
- java 手机声音提醒功能_Android基于广播事件机制实现简单定时提醒功能代码
本文实例讲述了Android基于广播事件机制实现简单定时提醒功能代码.分享给大家供大家参考,具体如下: 1.Android广播事件机制 Android的广播事件处理类似于普通的事件处理.不同之处在于, ...
- mysql+jdbc连接数据库简单实现登录功能 --java
初识java web 实现简单的登录功能 mvc结构实现mysql 连接 什么是mvc MVC是模型(model).视图(view).控制(controller)这三个单词上的首字母组成.它是一种应用 ...
- Java调用百度API实现文本与图像审核功能
文档: API文档:https://ai.baidu.com/ai-doc/ANTIPORN/ek3h6x90n SDK下载:https://ai.baidu.com/sdk#anti github链 ...
- java的简单数字时钟_Java实现的简单数字时钟功能示例
本文实例讲述了java实现的简单数字时钟功能.分享给大家供大家参考,具体如下: 应用名称:java数字时钟 用到的知识:java gui编程,线程 开发环境:win8+eclipse+jdk1.8 功 ...
- java简单atm_Java实现简单银行ATM功能
本文实例为大家分享了Java实现简单银行ATM功能的具体代码,供大家参考,具体内容如下 实现功能 1.用户需要通过输入银行卡号和密码才能进入ATM系统 2.用户可以在ATM中实现取款.存款.转账.余额 ...
最新文章
- centos环境变量设置
- [魔方]28秒!地铁站真是个破纪录的好地方
- n!mod p 的求法 数学
- hibernate Disabling contextual LOB creation as connection was null
- java鼠标图片裁剪,如何用Java中的鼠标指针捕获屏幕图像
- 防火墙(12)——查看协议被连接的次数、通过连接状态来写规则
- I - Ant Trip (无向图欧拉回路+并查集),判断
- Android之使用getIdentifier()获取资源Id
- awt jtable 多线程加载图片_Java项目实战之天天酷跑(三):缓冲加载游戏界面
- zoj 1074 To the MAX
- 程序员的进阶课-架构师之路(8)-二叉树
- 基于alsa的音量控制代码
- java进程因机器内存不足被系统kill的定位
- C# 事件和Unity3D
- [转贴]怎样学好法语?
- 测试计划与测试方案区别
- 计算机械效率的公式四种,初级中学物理计算公式定律整编汇总.doc
- 运放的开环增益和相移
- 写乐100道练习题_【写乐钢笔使用】_摘要频道_什么值得买
- w ndows10系统怎么退出安全模式,Windows 10安全模式怎么解除
热门文章
- 学校运动会广播稿计算机,学校运动会广播稿十篇
- oracle sql中( ),Oracle SQL中的函数
- Cent OS 7.4 1708 下载安装
- Page Cache 与 Kafka 那些事儿
- matlab里面sin函数是角度,matlab-如何用matlab编写sin函数要求定义一 – 手机爱问
- ⑦Java SE知识点回顾与小结(面向对象)
- 2021中国AI产业10大趋势,一分钟看明白 | WAIC2021
- 中央电大 c语言程序设计a 试题,中央电大2008年秋C语言程序设计A试题1
- c/c++通过域名解析ip地址
- 计算机毕业设计Python+uniapp学生考勤系统小程序(小程序+源码+LW)