我尝试了另一个来自rsbweb的代码……效果比 openCV 好得多!
这是我的新结果
我更改了部分代码,使用 Luv 而不是 YIQ 以获得更好的结果。颜色方程来自easyrgb
这是我的代码
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class test {
public static void main(String[] args) throws IOException {
BufferedImage img = ImageIO.read(new File("2.png"));
filterRGBImage(img);
ImageIO.write(img, "png", new File("3.png"));
}
private static int rad = 10, rad2=rad*rad;
private static double radCol2 = Math.pow(10,2);
private static void RGB2XYZ(double rgb[], double xyz[])
{
double var_R = ( rgb[0] / 255. ),var_G = ( rgb[1] / 255. ),var_B = ( rgb[2] / 255. );
if ( var_R > 0.04045 )
var_R = Math.pow(( ( var_R + 0.055 ) / 1.055 ),2.4);
else
var_R = var_R / 12.92;
if ( var_G > 0.04045 )
var_G = Math.pow( ( var_G + 0.055 ) / 1.055 , 2.4);
else
var_G = var_G / 12.92;
if ( var_B > 0.04045 )
var_B = Math.pow( ( var_B + 0.055 ) / 1.055 ,2.4);
else
var_B = var_B / 12.92;
var_R = var_R * 100;
var_G = var_G * 100;
var_B = var_B * 100;
xyz[0] = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
xyz[1] = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
xyz[2] = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
}
private static void XYZ2RGB(double xyz[], double rgb[])
{
double var_X = xyz[0] / 100, var_Y = xyz[1] / 100 , var_Z = xyz[2] / 100;
double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986,
var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415,
var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
if ( var_R > 0.0031308 )
var_R = 1.055 * Math.pow(var_R, 1 / 2.4 ) - 0.055;
else
var_R = 12.92 * var_R;
if ( var_G > 0.0031308 )
var_G = 1.055 * Math.pow(var_G , 1 / 2.4 ) - 0.055;
else
var_G = 12.92 * var_G;
if ( var_B > 0.0031308 )
var_B = 1.055 * Math.pow(var_B ,1 / 2.4 ) - 0.055;
else
var_B = 12.92 * var_B;
rgb[0] = var_R * 255;
rgb[1] = var_G * 255;
rgb[2] = var_B * 255 ;
}
private static void XYZ2Luv(double xyz[], double luv[])
{
double var_U = ( 4 * xyz[0] ) / ( xyz[0] + ( 15 * xyz[1] ) + ( 3 * xyz[2] ) ),
var_V = ( 9 * xyz[1] ) / ( xyz[0] + ( 15 * xyz[1] ) + ( 3 * xyz[2] ) ),
var_Y = xyz[1] / 100;
if ( var_Y > 0.008856 )
var_Y = Math.pow(var_Y, 1./3 );
else
var_Y = ( 7.787 * var_Y ) + ( 16. / 116 );
double ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883;
double ref_U = ( 4 * ref_X ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) ),
ref_V = ( 9 * ref_Y ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) );
luv[0] = ( 116 * var_Y ) - 16;
luv[1] = 13 * luv[0] * ( var_U - ref_U );
luv[2] = 13 * luv[0] * ( var_V - ref_V );
}
private static void Luv2XYZ(double luv[],double xyz[])
{
double var_Y = ( luv[0] + 16 ) / 116;
if ( Math.pow(var_Y,3) > 0.008856 )
var_Y = Math.pow(var_Y,3);
else
var_Y = ( var_Y - 16./ 116 ) / 7.787;
double ref_X = 95.047 ,ref_Y = 100.000,ref_Z = 108.883;
double ref_U = ( 4 * ref_X ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) ),
ref_V = ( 9 * ref_Y ) / ( ref_X + ( 15 * ref_Y ) + ( 3 * ref_Z ) );
double var_U = luv[1] / ( 13 * luv[0] ) + ref_U,
var_V =luv[2] / ( 13 * luv[0] ) + ref_V;
xyz[1] = var_Y * 100;
xyz[0] = - ( 9 * xyz[1] * var_U ) / ( ( var_U - 4 ) * var_V - var_U * var_V );
xyz[2] = ( 9 * xyz[1] - ( 15 * var_V * xyz[1]) - ( var_V * xyz[0] ) ) / ( 3 * var_V );
}
//http://rsbweb.nih.gov/ij/plugins/download/Mean_Shift.java
public static void filterRGBImage(BufferedImage ip) {
int width = ip.getWidth();
int height = ip.getHeight();
double[][][] pixelsf = new double[width][height][3];
for (int y=0; y<height; y++) {
for (int x=0; x<width; x++) {
int argb = ip.getRGB(x,y);
int r = (argb >> 16) & 0xff;
int g = (argb >> 8) & 0xff;
int b = (argb) & 0xff;
// YIQ
/*pixelsf[x][y][0] = 0.299f *r + 0.587f *g + 0.114f *b;
pixelsf[x][y][1] = 0.5957f *r - 0.2744f*g - 0.3212f *b;
pixelsf[x][y][2] = 0.2114f *r - 0.5226f*g + 0.3111f *b;*/
double tmp[]={r,g,b},tmp2[]={0,0,0};
RGB2XYZ(tmp,tmp2);
XYZ2Luv(tmp2,pixelsf[x][y]);
}
}
double shift = 0;
int iters = 0;
for (int y=0; y<height; y++) {
for (int x=0; x<width; x++) {
int xc = x;
int yc = y;
int xcOld, ycOld;
double YcOld, IcOld, QcOld;
double Yc = pixelsf[x][y][0];
double Ic = pixelsf[x][y][1];
double Qc = pixelsf[x][y][2];
iters = 0;
do {
xcOld = xc;
ycOld = yc;
YcOld = Yc;
IcOld = Ic;
QcOld = Qc;
float mx = 0;
float my = 0;
float mY = 0;
float mI = 0;
float mQ = 0;
int num=0;
for (int ry=-rad; ry <= rad; ry++) {
int y2 = yc + ry;
if (y2 >= 0 && y2 < height) {
for (int rx=-rad; rx <= rad; rx++) {
int x2 = xc + rx;
if (x2 >= 0 && x2 < width) {
//if (ry*ry + rx*rx <= rad2) {
double Y2 = pixelsf[x2][y2][0];
double I2 = pixelsf[x2][y2][1];
double Q2 = pixelsf[x2][y2][2];
double dY = Yc - Y2;
double dI = Ic - I2;
double dQ = Qc - Q2;
if (dY*dY+dI*dI+dQ*dQ <= radCol2) {
mx += x2;
my += y2;
mY += Y2;
mI += I2;
mQ += Q2;
num++;
}
//}
}
}
}
}
double num_ = 1./num;
Yc = mY*num_;
Ic = mI*num_;
Qc = mQ*num_;
xc = (int) (mx*num_+0.5);
yc = (int) (my*num_+0.5);
int dx = xc-xcOld;
int dy = yc-ycOld;
double dY = Yc-YcOld;
double dI = Ic-IcOld;
double dQ = Qc-QcOld;
shift = dx*dx+dy*dy+dY*dY+dI*dI+dQ*dQ;
iters++;
}
while (shift > 3 && iters < 100);
double tmp[]={Yc,Ic,Qc},tmp2[]={0,0,0};
Luv2XYZ(tmp,tmp2);
XYZ2RGB(tmp2,tmp);
int r_ = (int) tmp[0];
int g_ = (int) tmp[1];
int b_ = (int) tmp[2];
ip.setRGB(x, y, (0xFF<<24)|(r_<<16)|(g_<<8)|b_);
}
}
}
}