220808-纯java实现相片素描化

文章目录
  1. 1.实例演示图片转素描效果
  2. 2. 算法原理
    1. 2.1 灰度处理
    2. 2.2 边界凸显
    3. 2.3 相关博文
  3. 3. 快速使用
  4. 一灰灰的联系方式

修图可以说是国内技术领先的一大特点了,现在的图片处理技术可以说是非常厉害了,比如老旧照片修复,自动美化,各种滤镜,自动抠图等等,结合高大上的机器学习,功能越强大,感觉对于我这种图像门外汉来说,门槛也响应的越来越高了

那么有什么简单的方式,可以实现照片的处理嘛,接下来介绍一个纯java的工具包,来做图片处理

1.实例演示图片转素描效果

首先我们来看一下具体的效果,在项目中添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>

<dependency>
<groupId>com.github.liuyueyi</groupId>
<artifactId>java-jhlabs</artifactId>
<!-- replace by newest version -->
<version>1.0</version>
</dependency>
···


实用姿势

```java
private static void toSketch(String imgPath, String output) throws IOException {
BufferedImage src = ImageIO.read(Objects.requireNonNull(Img2SketchTest.class.getClassLoader().getResourceAsStream(imgPath)));
src = ImageUtils.convertImageToARGB(src);

//图像灰度化
PointFilter grayScaleFilter = new GrayscaleFilter();
BufferedImage grayScale = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
grayScaleFilter.filter(src, grayScale);

//灰度图像反色
BufferedImage inverted = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
PointFilter invertFilter = new InvertFilter();
invertFilter.filter(grayScale, inverted);

//高斯模糊处理
GaussianFilter gaussianFilter = new GaussianFilter(20);
BufferedImage gaussianFiltered = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
gaussianFilter.filter(inverted, gaussianFiltered);

// 灰度图像和高斯模糊反向图混合
ColorDodgeComposite cdc = new ColorDodgeComposite(1.0f);
CompositeContext cc = cdc.createContext(inverted.getColorModel(), grayScale.getColorModel(), null);
WritableRaster invertedR = gaussianFiltered.getRaster();
WritableRaster grayScaleR = grayScale.getRaster();
// 混合之后的就是我们希望的结果
BufferedImage composite = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
WritableRaster colorDodgedR = composite.getRaster();
cc.compose(invertedR, grayScaleR, colorDodgedR);

//输出做好的素描
File outputfile = new File(output);
ImageIO.write(composite, "png", outputfile);
}

表现结果如下

2. 算法原理

作为一个图像处理小白,网上搜索了一下,素描算法比较多,通过多番比较,感觉整体思想相差不大,大致是以下几个步骤

  1. 原图灰度化
  2. 临界值处理(小于某个临界值的像素值设置为0)
  3. 第二步的图像反色处理
  4. 第二步与第三步的图片混合处理

接下来将以我自己的粗浅理解出发,尝试做一下算法的解析

2.1 灰度处理

图像灰度处理,主要是为了将最终图片的色彩控制在五彩斑斓的灰白中,保持和我们常见的素描风格保持一致

具体的像素灰度处理,有一个广为流传的公式 (我也没找到原始出处,不知道是哪位大神给出的)

1
avgColor = red * 0.299f + green * 0.587f + blue * 0.114f

2.2 边界凸显

素描效果的一个核心要点在于对于物体的边缘轮廓进行定位,清洗的显示轮廓信息,对于之外的信息进行抽象模糊处理;简单来讲就是改凸显的地方凸显出来,不重要的地方模糊些处理

那么问题就是如何定位轮廓,如何模糊处理?

上面步骤中的第二、第三两步主要就是来干这个事情的;临界值 + 反向,主要就是为了定位边界轮廓(盲猜一波:轮廓边缘的像素差异较大,两次处理叠加之后,轮廓处像素信息受影响较小,和之前的值差别不大,有相关背景知识的大佬可以指点一下)

具体实现的方式呢,最容易想到的一点是

  • 设置一个阈值,小于这个阈值的像素设置为0;然后反向,两个图像进行混合处理,从而凸显轮廓

更先进一点的做法:

  • 傅里叶变换、高斯模糊、梯度算法等出现在各相关论文中的算法(至于为什么有效,我也不知道了…)

2.3 相关博文

3. 快速使用

文章的最开始就给出了一个素描处理的demo,输出效果基本ok,但是使用姿势有点麻烦;其实现就是借助jh-labs的滤镜来实现各种操作,对于应用者而言(比如我),可能并不关心具体细节,只要结果,有更简单的使用姿势么?

当然也是有的,下面这个开源项目已经做好了封装

最新版本为3.0,可以到中央仓库直接获取(如果还没有找到,不要慌,我还没有提交,因为3.0还在内测中)

引入依赖

1
2
3
4
5
<!-- https://mvnrepository.com/artifact/com.github.liuyueyi.media/photo-plugin -->
<dependency>
<groupId>com.github.liuyueyi.media</groupId>
<artifactId>photo-plugin</artifactId>
</dependency>

使用姿势

1
2
3
4
5
6
7
8
@Test
public void testSketch() {
BufferedImage out = PhotoOperateWrapper.of(OperatorEnum.SKETCH)
.setImg("https://t7.baidu.com/it/u=4162611394,4275913936&fm=193&f=GIF")
.build()
.asImg();
System.out.println("----");
}

相比较与前者,这个使用是不是更简单直接方便

说明

  • jhlabs项目 来自于jhlabs官网,未做任何修改,单纯的移入github,发布中央仓库供第三方仓库快速依赖而已;遵循Apache License
  • quick-meida项目 一个java的多媒体处理开源类库,当前已支持图片合成、编辑
    、二维码生成解析、音频转码、markdown/html互转、svg渲染等功能,欢迎感兴趣的小伙伴前往观光查看

一灰灰的联系方式

尽信书则不如无书,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

QrCode

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×