java实现rgb图片二值化处理

395 阅读1分钟

java将rgb彩色图片二值化处

OTSU算法,获取临界值,大于等于临界值的是白色,小于临界值的是黑色

public int getOptVal(int[][] arr,int w,int h){
    int optimize=0;
    double fc=0;
    double[] p=new double[256];
    int[] num=new int[256];
    double total=w*h;
    for(int i=0;i<256;i++){
        int count=0;
        for (int a = 0; a < w; a++) {
            for (int b = 0; b < h; b++) {
                int pixel=arr[a][b];
                if(pixel==i){
                    count++;
                }
            }
        }
        p[i]=count/total;
        num[i]=count;
    }
    for(int i=0;i<256;i++){
        double p0=0;
        double p1=0;
        double u0=0;
        double u1=0;
        int n0=0;
        int n1=0;
        for(int j=0;j<256;j++){
            if(j<=i){
                p0+=p[j];
                u0=u0+j*p[j];
                n0+=num[j];
            }else{
                p1+=p[j];
                u1=u1+j*p[j];
                n1+=num[j];
            }
        }
        u0=u0*total/n0;
        u1=u1*total/n1;
        double fcTmp=p0*p1*((u0-u1)*(u0-u1));
        if(fcTmp>fc){
            fc=fcTmp;
            optimize=i;
        }
    }
    return optimize;
}

生成黑白图片

public void getSplitRow(String src) throws IOException {
    File file = new File(src);
    BufferedImage bufferedImage = ImageIO.read(file);
    int h = bufferedImage.getHeight();
    int w = bufferedImage.getWidth();
    int arr[][] = new int[w][h];
    int[][] rowArr= new int[h][w];
    // 获取图片每一像素点的灰度值
    for (int i = 0; i < w; i++) {
        for (int j = 0; j < h; j++) {
            int rgb = bufferedImage.getRGB(i, j);
            int gray=this.getImageRgb(rgb);
            arr[i][j]=gray;
            rowArr[j][i]=gray;
        }
    }
    int optimize = this.getOTSU(arr, w, h);
    BitSet[] binary=new BitSet[h];
    for(int i=0;i<h;i++){
        BitSet rowData=new BitSet(w);
        for(int j=0;j<w;j++){
            if(rowArr[i][j]>=optimize){
                rowData.set(j);
            }
        }
        binary[i]=rowData;
    }
    int mostW=w;
    for(int i=0;i<h;i++){
        for(int j=0;j<w;j++){
            boolean flag=binary[i].get(j);
            if(!flag){
                if(j<mostW){
                    mostW=j;
                }
                break;
            }
        }
    }
    List<String> allBlank=new ArrayList<>();
    int start=0;
    int end=0;
    for(int i=0;i<h;i++){
        boolean flag=binary[i].get(mostW);
        if(flag){
            end++;
        }else{
            if(end>0&&start>0){
                allBlank.add(start+"@"+(start+end));
            }
            end=0;
            start=i;
        }
    }
    BufferedImage bufImg =
            new BufferedImage(w, h, BufferedImage.TYPE_INT_BGR);
    for (int i = 0; i < w; i++) {
        for (int j = 0; j < h; j++) {
            boolean flag= binary[j].get(i);
            if(flag){
                int white=new Color(255,255,255).getRGB();
                bufImg.setRGB(i,j,white);
            }else{
                int black=new Color(0,0,0).getRGB();
                bufImg.setRGB(i,j,black);
            }
        }
    }
    File newFile = new File("D:\zhanganhua\工作日志\2023-02-20\Desktop(1)\1001000.jpg");
    ImageIO.write(bufImg, "png", newFile);
}

像素点的rgb转为一个灰度值

public int getImageRgb(int i) {
    // argb分别代表透明,红,绿,蓝 分别占16进制2位
    final int r = (i >> 16) & 0xff;
    final int g = (i >> 8) & 0xff;
    final int b = i & 0xff;
    int result=(int)((r+g+b)/3);
    return result;
}