EDISON和cvPyrMeanShiftFiltering之间的区别是什么?

时间:2012-03-10 10:34:23

标签: opencv filter image-segmentation computer-vision

我正在做一些平均班次细分的员工。我找到了名为EDISON(http://coewww.rutgers.edu/riul/research/code/EDISON/)的代码,它实现了一个很好的代码。此外,opencv还有一个名为cvPyrMeanShiftFiltering的函数。

但是它们在下图中有所不同。在EDISON系统中,两个参数是7& 6.5。在opencv中,我使用 cvPyrMeanShiftFiltering(result, result, 7, 6.5,level);(结果已转换为LUV)右图中的边框不清晰。我也尝试过level = 0 ......

有人可以帮忙吗?我希望在openCV的帮助下获得相同的结果。 (我已经实现了聚类步骤)

Comparison

1 个答案:

答案 0 :(得分:3)

我尝试了rsbweb的另一个代码......效果比openCV好得多!

这是我的新结果

Mean Shift Filter

我改变了部分代码,使用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_);
        }

    }
}
}