接上一篇的使用 Java 提取图片的色彩边界,这一篇增加了去除噪点,锐化,模糊,S曲线加深,各向异性等处理,想做成类似于 PS 的人物卡通化的功能的,失败了,效果不行. 这其中参考了大量的网上例子,感谢各位大佬的分享,引用网址都在代码里面了.
引入jar包
<!-- java图片工具 https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.12</version>
</dependency>
实现代码
import net
.coobird
.thumbnailator
.Thumbnails
;
import javax
.imageio
.ImageIO
;
import java
.awt
.image
.BufferedImage
;
import java
.io
.*
;
import java
.nio
.charset
.StandardCharsets
;
public class ImageUtil {
private static final int threshold
= 3000000;
private static final int picWidth
= 500;
public static void main(String
[] args
) throws IOException
{
String fromPic
= "C:\\Users\\Public\\Pictures\\Sample Pictures\\QQ图片20201022091237.jpg";
String toTxt
= "d:\\test5.txt";
BufferedImage bufferedImage
= ImageIO
.read(new File(fromPic
));
BufferedImage compactImage
= Thumbnails
.of(bufferedImage
).size(picWidth
, 2000).asBufferedImage();
BufferedImage curveImage
= curveProcess(compactImage
);
BufferedImage grayImage
= grayingImage(curveImage
);
BufferedImage binaryImage
= binaryImage(grayImage
);
BufferedImage borderImage
= getImageBorder(binaryImage
);
File newFile
= new File("d:\\test8.jpg");
ImageIO
.write(borderImage
, "jpg", newFile
);
}
private static BufferedImage
grayingImage(BufferedImage bufferedImage
) {
BufferedImage grayImage
= new BufferedImage(bufferedImage
.getWidth(), bufferedImage
.getHeight(),
BufferedImage
.TYPE_BYTE_GRAY
);
for (int i
= 0; i
< bufferedImage
.getWidth(); i
++) {
for (int j
= 0; j
< bufferedImage
.getHeight(); j
++) {
int color
= bufferedImage
.getRGB(i
, j
);
grayImage
.setRGB(i
, j
, color
);
}
}
return grayImage
;
}
private static BufferedImage
binaryImage(BufferedImage bufferedImage
) {
BufferedImage grayImage
= new BufferedImage(bufferedImage
.getWidth(), bufferedImage
.getHeight(), bufferedImage
.getType());
int threshold
= getMeanThreshold(bufferedImage
);
for (int i
= 0; i
< bufferedImage
.getWidth(); i
++) {
for (int j
= 0; j
< bufferedImage
.getHeight(); j
++) {
int color
= bufferedImage
.getRGB(i
, j
);
int r
= (color
>> 16) & 0xff;
int g
= (color
>> 8) & 0xff;
int b
= color
& 0xff;
int gray
= (int) (0.3 * r
+ 0.59 * g
+ 0.11 * b
);
if (gray
> threshold
) {
grayImage
.setRGB(i
, j
, 0xFFFFFF);
} else {
grayImage
.setRGB(i
, j
, 0);
}
}
}
return grayImage
;
}
private static int getMeanThreshold(BufferedImage bufferedImage
) {
int w
= bufferedImage
.getWidth();
int h
= bufferedImage
.getHeight();
int num
= 0;
int sum
= 0;
for (int i
= 0; i
< w
; i
++) {
for (int j
= 0; j
< h
; j
++) {
int color
= bufferedImage
.getRGB(i
, j
);
int r
= (color
>> 16) & 0xff;
int g
= (color
>> 8) & 0xff;
int b
= color
& 0xff;
int gray
= (int) (0.3 * r
+ 0.59 * g
+ 0.11 * b
);
sum
+= gray
;
num
+= 1;
}
}
int threshold
= sum
/ num
;
if (threshold
* 1.2 < 255) {
threshold
= (int) (1.2 * sum
/ num
);
}
System
.out
.println("width: " + w
+ " height: " + h
+ " threshold: " + threshold
);
return threshold
;
}
public static void writeToTxt(BufferedImage bufferedImage
, String toSaveFilePath
) {
File file
= new File(toSaveFilePath
);
try {
Writer writer
= new OutputStreamWriter(new FileOutputStream(file
, true), StandardCharsets
.UTF_8
);
StringBuilder builder
= new StringBuilder();
for (int j
= 0; j
< bufferedImage
.getHeight(); j
++) {
for (int i
= 0; i
< bufferedImage
.getWidth(); i
++) {
int color
= bufferedImage
.getRGB(i
, j
);
if (color
== -1) {
builder
.append(" ");
} else {
builder
.append("0 ");
}
}
builder
.append("\r\n");
}
writer
.write(builder
.toString());
writer
.close();
} catch (Exception e
) {
e
.printStackTrace();
}
}
private static BufferedImage
getImageBorder(BufferedImage bufferedImage
) {
BufferedImage borderImage
= new BufferedImage(bufferedImage
.getWidth(), bufferedImage
.getHeight(), bufferedImage
.getType());
int imgWidth
= bufferedImage
.getWidth();
int imgHeight
= bufferedImage
.getHeight();
for (int i
= 1; i
< imgWidth
- 1; i
++) {
for (int j
= 1; j
< imgHeight
- 1; j
++) {
int color
= bufferedImage
.getRGB(i
, j
);
int upColor
= bufferedImage
.getRGB(i
, j
- 1);
int downColor
= bufferedImage
.getRGB(i
, j
+ 1);
int leftColor
= bufferedImage
.getRGB(i
- 1, j
);
int rightColor
= bufferedImage
.getRGB(i
+ 1, j
);
if (isQualified(color
, upColor
, downColor
, leftColor
, rightColor
)) {
borderImage
.setRGB(i
, j
, 0xFFFFFF);
} else {
borderImage
.setRGB(i
, j
, color
);
}
}
}
return borderImage
;
}
public static boolean isQualified(int color
, int upColor
, int downColor
, int leftColor
, int rightColor
) {
return color
!= -1 && (Math
.abs(color
- upColor
) < threshold
&& Math
.abs(color
- downColor
) < threshold
&& Math
.abs(color
- leftColor
) < threshold
&& Math
.abs(color
- rightColor
) < threshold
);
}
public static boolean isNoise(int color
, int upColor
, int downColor
, int leftColor
, int rightColor
) {
if (color
!= -1) {
int whiteCount
= 0;
if (upColor
== -1) {
whiteCount
++;
}
if (downColor
== -1) {
whiteCount
++;
}
if (leftColor
== -1) {
whiteCount
++;
}
if (rightColor
== -1) {
whiteCount
++;
}
return whiteCount
>= 3;
}
return false;
}
private static BufferedImage
clearNoise(BufferedImage bufferedImage
) {
BufferedImage noNoiseImage
= new BufferedImage(bufferedImage
.getWidth(), bufferedImage
.getHeight(), bufferedImage
.getType());
int imgWidth
= bufferedImage
.getWidth();
int imgHeight
= bufferedImage
.getHeight();
for (int i
= 1; i
< imgWidth
- 1; i
++) {
for (int j
= 1; j
< imgHeight
- 1; j
++) {
int color
= bufferedImage
.getRGB(i
, j
);
int upColor
= bufferedImage
.getRGB(i
, j
- 1);
int downColor
= bufferedImage
.getRGB(i
, j
+ 1);
int leftColor
= bufferedImage
.getRGB(i
- 1, j
);
int rightColor
= bufferedImage
.getRGB(i
+ 1, j
);
if (isNoise(color
, upColor
, downColor
, leftColor
, rightColor
)) {
noNoiseImage
.setRGB(i
, j
, 0xFFFFFF);
} else {
noNoiseImage
.setRGB(i
, j
, color
);
}
}
}
return noNoiseImage
;
}
private static final int[][] sharpen
= new int[][]{{-1, -1, -1}, {-1, 9, -1}, {-1, -1, -1}};
private static BufferedImage
sharpenImage(BufferedImage bufferedImage
) {
BufferedImage image
= new BufferedImage(bufferedImage
.getWidth(), bufferedImage
.getHeight(), bufferedImage
.getType());
int imgWidth
= bufferedImage
.getWidth();
int imgHeight
= bufferedImage
.getHeight();
int[][] pixels
= new int[3][3];
for (int i
= 1; i
< imgWidth
- 1; i
++) {
for (int j
= 1; j
< imgHeight
- 1; j
++) {
pixels
[0][0] = bufferedImage
.getRGB(i
- 1, j
- 1);
pixels
[0][1] = bufferedImage
.getRGB(i
, j
- 1);
pixels
[0][2] = bufferedImage
.getRGB(i
+ 1, j
- 1);
pixels
[1][0] = bufferedImage
.getRGB(i
- 1, j
);
pixels
[1][1] = bufferedImage
.getRGB(i
, j
);
pixels
[1][2] = bufferedImage
.getRGB(i
+ 1, j
);
pixels
[2][0] = bufferedImage
.getRGB(i
- 1, j
+ 1);
pixels
[2][1] = bufferedImage
.getRGB(i
, j
+ 1);
pixels
[2][2] = bufferedImage
.getRGB(i
+ 1, j
+ 1);
int newPixels
= pixels
[0][0] * sharpen
[0][0] + pixels
[0][1] * sharpen
[0][1] + pixels
[0][2] * sharpen
[0][2] +
pixels
[1][0] * sharpen
[1][0] + pixels
[1][1] * sharpen
[1][1] + pixels
[1][2] * sharpen
[1][2] +
pixels
[2][0] * sharpen
[2][0] + pixels
[2][1] * sharpen
[2][1] + pixels
[2][2] * sharpen
[2][2];
image
.setRGB(i
, j
, newPixels
);
}
}
return image
;
}
private static BufferedImage
sharpenImage2(BufferedImage src
) {
int[] LAPLACE
= new int[]{0, -1, 0, -1, 4, -1, 0, -1, 0};
int width
= src
.getWidth();
int height
= src
.getHeight();
int[] pixels
= new int[width
* height
];
int[] outPixels
= new int[width
* height
];
int type
= src
.getType();
if (type
== BufferedImage
.TYPE_INT_ARGB
|| type
== BufferedImage
.TYPE_INT_RGB
) {
src
.getRaster().getDataElements(0, 0, width
, height
, pixels
);
}
src
.getRGB(0, 0, width
, height
, pixels
, 0, width
);
int k0
= 0, k1
= 0, k2
= 0;
int k3
= 0, k4
= 0, k5
= 0;
int k6
= 0, k7
= 0, k8
= 0;
k0
= LAPLACE
[0];
k1
= LAPLACE
[1];
k2
= LAPLACE
[2];
k3
= LAPLACE
[3];
k4
= LAPLACE
[4];
k5
= LAPLACE
[5];
k6
= LAPLACE
[6];
k7
= LAPLACE
[7];
k8
= LAPLACE
[8];
int offset
= 0;
int sr
= 0, sg
= 0, sb
= 0;
int r
= 0, g
= 0, b
= 0;
for (int row
= 1; row
< height
- 1; row
++) {
offset
= row
* width
;
for (int col
= 1; col
< width
- 1; col
++) {
r
= (pixels
[offset
+ col
] >> 16) & 0xff;
g
= (pixels
[offset
+ col
] >> 8) & 0xff;
b
= (pixels
[offset
+ col
]) & 0xff;
sr
= k0
* ((pixels
[offset
- width
+ col
- 1] >> 16) & 0xff)
+ k1
* ((pixels
[offset
- width
+ col
] >> 16) & 0xff)
+ k2
* ((pixels
[offset
- width
+ col
+ 1] >> 16) & 0xff)
+ k3
* ((pixels
[offset
+ col
- 1] >> 16) & 0xff) + k4
* ((pixels
[offset
+ col
] >> 16) & 0xff) + k5
* ((pixels
[offset
+ col
+ 1] >> 16) & 0xff) + k6
* ((pixels
[offset
+ width
+ col
- 1] >> 16) & 0xff)
+ k7
* ((pixels
[offset
+ width
+ col
] >> 16) & 0xff)
+ k8
* ((pixels
[offset
+ width
+ col
+ 1] >> 16) & 0xff);
sg
= k0
* ((pixels
[offset
- width
+ col
- 1] >> 8) & 0xff) + k1
* ((pixels
[offset
- width
+ col
] >> 8) & 0xff) + k2
* ((pixels
[offset
- width
+ col
+ 1] >> 8) & 0xff) + k3
* ((pixels
[offset
+ col
- 1] >> 8) & 0xff) + k4
* ((pixels
[offset
+ col
] >> 8) & 0xff) + k5
* ((pixels
[offset
+ col
+ 1] >> 8) & 0xff) + k6
* ((pixels
[offset
+ width
+ col
- 1] >> 8) & 0xff) + k7
* ((pixels
[offset
+ width
+ col
] >> 8) & 0xff) + k8
* ((pixels
[offset
+ width
+ col
+ 1] >> 8) & 0xff);
sb
= k0
* (pixels
[offset
- width
+ col
- 1] & 0xff) + k1
* (pixels
[offset
- width
+ col
] & 0xff) + k2
* (pixels
[offset
- width
+ col
+ 1] & 0xff) + k3
* (pixels
[offset
+ col
- 1] & 0xff) + k4
* (pixels
[offset
+ col
] & 0xff) + k5
* (pixels
[offset
+ col
+ 1] & 0xff) + k6
* (pixels
[offset
+ width
+ col
- 1] & 0xff) + k7
* (pixels
[offset
+ width
+ col
] & 0xff) + k8
* (pixels
[offset
+ width
+ col
+ 1] & 0xff);
r
+= sr
;
g
+= sg
;
b
+= sb
;
outPixels
[offset
+ col
] = (0xff << 24) | (clamp(r
) << 16) | (clamp(g
) << 8) | clamp(b
);
}
}
BufferedImage dest
= new BufferedImage(width
, height
, src
.getType());
dest
.setRGB(0, 0, width
, height
, outPixels
, 0, width
);
return dest
;
}
public static BufferedImage
sobelProcess(BufferedImage src
) {
int[] sobel_y
= new int[]{-1, -2, -1, 0, 0, 0, 1, 2, 1};
int[] sobel_x
= new int[]{-1, 0, 1, -2, 0, 2, -1, 0, 1};
int width
= src
.getWidth();
int height
= src
.getHeight();
int[] pixels
= new int[width
* height
];
int[] outPixels
= new int[width
* height
];
src
.getRGB(0, 0, width
, height
, pixels
, 0, width
);
int offset
= 0;
int x0
= sobel_x
[0];
int x1
= sobel_x
[1];
int x2
= sobel_x
[2];
int x3
= sobel_x
[3];
int x4
= sobel_x
[4];
int x5
= sobel_x
[5];
int x6
= sobel_x
[6];
int x7
= sobel_x
[7];
int x8
= sobel_x
[8];
int k0
= sobel_y
[0];
int k1
= sobel_y
[1];
int k2
= sobel_y
[2];
int k3
= sobel_y
[3];
int k4
= sobel_y
[4];
int k5
= sobel_y
[5];
int k6
= sobel_y
[6];
int k7
= sobel_y
[7];
int k8
= sobel_y
[8];
int yr
= 0, yg
= 0, yb
= 0;
int xr
= 0, xg
= 0, xb
= 0;
int r
= 0, g
= 0, b
= 0;
for (int row
= 1; row
< height
- 1; row
++) {
offset
= row
* width
;
for (int col
= 1; col
< width
- 1; col
++) {
yr
= k0
* ((pixels
[offset
- width
+ col
- 1] >> 16) & 0xff)
+ k1
* ((pixels
[offset
- width
+ col
] >> 16) & 0xff)
+ k2
* ((pixels
[offset
- width
+ col
+ 1] >> 16) & 0xff)
+ k3
* ((pixels
[offset
+ col
- 1] >> 16) & 0xff) + k4
* ((pixels
[offset
+ col
] >> 16) & 0xff) + k5
* ((pixels
[offset
+ col
+ 1] >> 16) & 0xff) + k6
* ((pixels
[offset
+ width
+ col
- 1] >> 16) & 0xff)
+ k7
* ((pixels
[offset
+ width
+ col
] >> 16) & 0xff)
+ k8
* ((pixels
[offset
+ width
+ col
+ 1] >> 16) & 0xff);
xr
= x0
* ((pixels
[offset
- width
+ col
- 1] >> 16) & 0xff)
+ x1
* ((pixels
[offset
- width
+ col
] >> 16) & 0xff)
+ x2
* ((pixels
[offset
- width
+ col
+ 1] >> 16) & 0xff)
+ x3
* ((pixels
[offset
+ col
- 1] >> 16) & 0xff) + x4
* ((pixels
[offset
+ col
] >> 16) & 0xff) + x5
* ((pixels
[offset
+ col
+ 1] >> 16) & 0xff) + x6
* ((pixels
[offset
+ width
+ col
- 1] >> 16) & 0xff)
+ x7
* ((pixels
[offset
+ width
+ col
] >> 16) & 0xff)
+ x8
* ((pixels
[offset
+ width
+ col
+ 1] >> 16) & 0xff);
yg
= k0
* ((pixels
[offset
- width
+ col
- 1] >> 8) & 0xff) + k1
* ((pixels
[offset
- width
+ col
] >> 8) & 0xff) + k2
* ((pixels
[offset
- width
+ col
+ 1] >> 8) & 0xff) + k3
* ((pixels
[offset
+ col
- 1] >> 8) & 0xff) + k4
* ((pixels
[offset
+ col
] >> 8) & 0xff) + k5
* ((pixels
[offset
+ col
+ 1] >> 8) & 0xff) + k6
* ((pixels
[offset
+ width
+ col
- 1] >> 8) & 0xff) + k7
* ((pixels
[offset
+ width
+ col
] >> 8) & 0xff) + k8
* ((pixels
[offset
+ width
+ col
+ 1] >> 8) & 0xff);
xg
= x0
* ((pixels
[offset
- width
+ col
- 1] >> 8) & 0xff) + x1
* ((pixels
[offset
- width
+ col
] >> 8) & 0xff) + x2
* ((pixels
[offset
- width
+ col
+ 1] >> 8) & 0xff) + x3
* ((pixels
[offset
+ col
- 1] >> 8) & 0xff) + x4
* ((pixels
[offset
+ col
] >> 8) & 0xff) + x5
* ((pixels
[offset
+ col
+ 1] >> 8) & 0xff) + x6
* ((pixels
[offset
+ width
+ col
- 1] >> 8) & 0xff) + x7
* ((pixels
[offset
+ width
+ col
] >> 8) & 0xff) + x8
* ((pixels
[offset
+ width
+ col
+ 1] >> 8) & 0xff);
yb
= k0
* (pixels
[offset
- width
+ col
- 1] & 0xff) + k1
* (pixels
[offset
- width
+ col
] & 0xff) + k2
* (pixels
[offset
- width
+ col
+ 1] & 0xff) + k3
* (pixels
[offset
+ col
- 1] & 0xff) + k4
* (pixels
[offset
+ col
] & 0xff) + k5
* (pixels
[offset
+ col
+ 1] & 0xff) + k6
* (pixels
[offset
+ width
+ col
- 1] & 0xff) + k7
* (pixels
[offset
+ width
+ col
] & 0xff) + k8
* (pixels
[offset
+ width
+ col
+ 1] & 0xff);
xb
= x0
* (pixels
[offset
- width
+ col
- 1] & 0xff) + x1
* (pixels
[offset
- width
+ col
] & 0xff) + x2
* (pixels
[offset
- width
+ col
+ 1] & 0xff) + x3
* (pixels
[offset
+ col
- 1] & 0xff) + x4
* (pixels
[offset
+ col
] & 0xff) + x5
* (pixels
[offset
+ col
+ 1] & 0xff) + x6
* (pixels
[offset
+ width
+ col
- 1] & 0xff) + x7
* (pixels
[offset
+ width
+ col
] & 0xff) + x8
* (pixels
[offset
+ width
+ col
+ 1] & 0xff);
r
= (int) Math
.sqrt(yr
* yr
+ xr
* xr
);
g
= (int) Math
.sqrt(yg
* yg
+ xg
* xg
);
b
= (int) Math
.sqrt(yb
* yb
+ xb
* xb
);
outPixels
[offset
+ col
] = (0xff << 24) | (clamp(r
) << 16)
| (clamp(g
) << 8) | clamp(b
);
}
}
BufferedImage dest
= new BufferedImage(width
, height
,
src
.getType());
dest
.setRGB(0, 0, width
, height
, outPixels
, 0, width
);
return dest
;
}
private static BufferedImage
meanValueProcess(BufferedImage src
) {
int width
= src
.getWidth();
int height
= src
.getHeight();
int[] pixels
= new int[width
* height
];
int[] outPixels
= new int[width
* height
];
src
.getRGB(0, 0, width
, height
, pixels
, 0, width
);
int radius
= 1;
int total
= (2 * radius
+ 1) * (2 * radius
+ 1);
int r
= 0, g
= 0, b
= 0;
for (int row
= 0; row
< height
; row
++) {
for (int col
= 0; col
< width
; col
++) {
int rSum
= 0;
int gSum
= 0;
int bSum
= 0;
for (int i
= -radius
; i
<= radius
; i
++) {
int roffset
= row
+ i
;
roffset
= (roffset
< 0) ? 0 : (roffset
>= height
? height
- 1 : roffset
);
for (int j
= -radius
; j
<= radius
; j
++) {
int coffset
= col
+ j
;
coffset
= (coffset
< 0) ? 0 : (coffset
>= width
? width
- 1 : coffset
);
int pixel
= pixels
[roffset
* width
+ coffset
];
r
= (pixel
>> 16) & 0XFF;
g
= (pixel
>> 8) & 0xff;
b
= pixel
& 0xff;
rSum
+= r
;
gSum
+= g
;
bSum
+= b
;
}
}
r
= rSum
/ total
;
g
= gSum
/ total
;
b
= bSum
/ total
;
outPixels
[row
* width
+ col
] = (255 << 24) | (clamp(r
) << 16) | (clamp(g
) << 8) | clamp(b
);
}
}
BufferedImage dest
= new BufferedImage(width
, height
, src
.getType());
dest
.setRGB(0, 0, width
, height
, outPixels
, 0, width
);
return dest
;
}
public static BufferedImage
negativeProcess(BufferedImage src
) {
int width
= src
.getWidth();
int height
= src
.getHeight();
int[] pixels
= new int[width
* height
];
int[] outPixels
= new int[width
* height
];
src
.getRGB(0, 0, width
, height
, pixels
, 0, width
);
int offset
= 0;
for (int row
= 1; row
< height
- 1; row
++) {
offset
= row
* width
;
for (int col
= 1; col
< width
- 1; col
++) {
int r
= (pixels
[offset
+ col
] >> 16) & 0xff;
int g
= (pixels
[offset
+ col
] >> 8) & 0xff;
int b
= (pixels
[offset
+ col
]) & 0xff;
r
= 255 - r
;
g
= 255 - g
;
b
= 255 - b
;
outPixels
[offset
+ col
] = (0xff << 24) | (clamp(r
) << 16)
| (clamp(g
) << 8) | clamp(b
);
}
}
BufferedImage dest
= new BufferedImage(width
, height
, src
.getType());
dest
.setRGB(0, 0, width
, height
, outPixels
, 0, width
);
return dest
;
}
public static BufferedImage
curveProcess(BufferedImage src
) {
int width
= src
.getWidth();
int height
= src
.getHeight();
int[] pixels
= new int[width
* height
];
int[] outPixels
= new int[width
* height
];
src
.getRGB(0, 0, width
, height
, pixels
, 0, width
);
int offset
= 0;
for (int row
= 1; row
< height
- 1; row
++) {
offset
= row
* width
;
for (int col
= 1; col
< width
- 1; col
++) {
int r
= (pixels
[offset
+ col
] >> 16) & 0xff;
int g
= (pixels
[offset
+ col
] >> 8) & 0xff;
int b
= (pixels
[offset
+ col
]) & 0xff;
r
= getSCurve(r
);
g
= getSCurve(g
);
b
= getSCurve(b
);
outPixels
[offset
+ col
] = (0xff << 24) | (clamp(r
) << 16) | (clamp(g
) << 8) | clamp(b
);
}
}
BufferedImage dest
= new BufferedImage(width
, height
, src
.getType());
dest
.setRGB(0, 0, width
, height
, outPixels
, 0, width
);
return dest
;
}
private static BufferedImage
USMSharpen(BufferedImage src
) {
int width
= src
.getWidth();
int height
= src
.getHeight();
int[] pixels
= new int[width
* height
];
int[] outPixels
= new int[width
* height
];
src
.getRGB(0, 0, width
, height
, pixels
, 0, width
);
int radius
= 2;
int total
= (2 * radius
+ 1) * (2 * radius
+ 1);
int r
= 0, g
= 0, b
= 0;
for (int row
= 0; row
< height
; row
++) {
for (int col
= 0; col
< width
; col
++) {
int rSum
= 0;
int gSum
= 0;
int bSum
= 0;
for (int i
= -radius
; i
<= radius
; i
++) {
int roffset
= row
+ i
;
roffset
= (roffset
< 0) ? 0 : (roffset
>= height
? height
- 1 : roffset
);
for (int j
= -radius
; j
<= radius
; j
++) {
int coffset
= col
+ j
;
coffset
= (coffset
< 0) ? 0 : (coffset
>= width
? width
- 1 : coffset
);
int pixel
= pixels
[roffset
* width
+ coffset
];
r
= (pixel
>> 16) & 0XFF;
g
= (pixel
>> 8) & 0xff;
b
= pixel
& 0xff;
rSum
+= r
;
gSum
+= g
;
bSum
+= b
;
}
}
r
= 2 * r
- rSum
/ total
;
g
= 2 * g
- gSum
/ total
;
b
= 2 * b
- bSum
/ total
;
outPixels
[row
* width
+ col
] = (255 << 24) | (clamp(r
) << 16) | (clamp(g
) << 8) | clamp(b
);
}
}
BufferedImage dest
= new BufferedImage(width
, height
, src
.getType());
dest
.setRGB(0, 0, width
, height
, outPixels
, 0, width
);
return dest
;
}
public static BufferedImage
anisotropyImage(BufferedImage srcImage
) {
BufferedImage anisotropyImage
= new BufferedImage(srcImage
.getWidth(), srcImage
.getHeight(), srcImage
.getType());
double k
= 15;
double lambda
= 0.35;
int width
= srcImage
.getWidth();
int height
= srcImage
.getHeight();
double rn
= 0, rs
= 0, re
= 0, rw
= 0;
double gn
= 0, gs
= 0, ge
= 0, gw
= 0;
double bn
= 0, bs
= 0, be
= 0, bw
= 0;
double rnc
= 0, rsc
= 0, rec
= 0, rwc
= 0;
double gnc
= 0, gsc
= 0, gec
= 0, gwc
= 0;
double bnc
= 0, bsc
= 0, bec
= 0, bwc
= 0;
double k2
= k
* k
;
for (int row
= 1; row
< width
- 1; row
++) {
for (int col
= 1; col
< height
- 1; col
++) {
int color
= srcImage
.getRGB(row
, col
);
int upColor
= srcImage
.getRGB(row
- 1, col
);
int downColor
= srcImage
.getRGB(row
+ 1, col
);
int leftColor
= srcImage
.getRGB(row
, col
- 1);
int rightColor
= srcImage
.getRGB(row
, col
+ 1);
int r
= (color
>> 16) & 0xff;
int g
= (color
>> 8) & 0xff;
int b
= color
& 0xff;
rn
= ((upColor
>> 16) & 0xff) - ((color
>> 16) & 0xff);
rs
= ((downColor
>> 16) & 0xff) - ((color
>> 16) & 0xff);
re
= ((leftColor
>> 16) & 0xff) - ((color
>> 16) & 0xff);
rw
= ((rightColor
>> 16) & 0xff) - ((color
>> 16) & 0xff);
rnc
= Math
.exp(-rn
* rn
/ k2
);
rsc
= Math
.exp(-rs
* rs
/ k2
);
rec
= Math
.exp(-re
* re
/ k2
);
rwc
= Math
.exp(-rw
* rw
/ k2
);
gn
= ((upColor
>> 8) & 0xff) - ((color
>> 8) & 0xff);
gs
= ((downColor
>> 8) & 0xff) - ((color
>> 8) & 0xff);
ge
= ((leftColor
>> 8) & 0xff) - ((color
>> 8) & 0xff);
gw
= ((rightColor
>> 8) & 0xff) - ((color
>> 8) & 0xff);
gnc
= Math
.exp(-gn
* gn
/ k2
);
gsc
= Math
.exp(-gs
* gs
/ k2
);
gec
= Math
.exp(-ge
* ge
/ k2
);
gwc
= Math
.exp(-gw
* gw
/ k2
);
bn
= (upColor
& 0xff) - (color
& 0xff);
bs
= (downColor
& 0xff) - (color
& 0xff);
be
= (leftColor
& 0xff) - (color
& 0xff);
bw
= (rightColor
& 0xff) - (color
& 0xff);
bnc
= Math
.exp(-bn
* bn
/ k2
);
bsc
= Math
.exp(-bs
* bs
/ k2
);
bec
= Math
.exp(-be
* be
/ k2
);
bwc
= Math
.exp(-bw
* bw
/ k2
);
int fr
= r
+ (int) (lambda
* (rn
* rnc
+ rs
* rsc
+ re
* rec
+ rw
* rwc
));
int fg
= g
+ (int) (lambda
* (gn
* gnc
+ gs
* gsc
+ ge
* gec
+ gw
* gwc
));
int fb
= b
+ (int) (lambda
* (bn
* bnc
+ bs
* bsc
+ be
* bec
+ bw
* bwc
));
int rgb
= (clamp(fr
) << 16) | (clamp(fg
) << 8) | clamp(fb
);
anisotropyImage
.setRGB(row
, col
, rgb
);
}
}
return anisotropyImage
;
}
private static int clamp(int value
) {
return value
> 255 ? 255 : (Math
.max(value
, 0));
}
private static int getSCurve(int x
) {
double j
= 255 / (1 + Math
.exp(5 - x
* 2/ 51.0));
return (int) Math
.round(j
);
}
}
总结
里面的处理功能都是独立开来的,可以自由组合.另外各种参数的调整需要自己去慢慢调整了.然后还看了图像识别方面的文章,目前的图像识别主要是通过卷积神经网络进行的,需要大量的训练和参数调整,还要有个好显卡,有兴趣的可以了解一下,加入炼丹师大军,参考文章放在下面.
参考链接
基础图像处理之混合空间增强——(Java:拉普拉斯锐化、Sobel边缘检测、均值滤波、伽马变换) 为你详细解读USM锐化 掌握原理 就能让照片更锐利 图像各向异性滤波 各项异性扩散(Anisotropic diffusion)–算法简介(python)代码实现 用OpenCV实现Photoshop算法(三): 曲线调整 S型函数:Sigmoid 函数 函数图像绘制工具 CNN卷积神经网络原理讲解+图片识别应用 如何通过人工神经网络实现图像识别? CUDA——“从入门到放弃”