9

在java中从图像中自动裁剪白色边框的最简单方法是什么?提前致谢...

4

4 回答 4

23

这是一种裁剪所有 4 个边的方法,使用左上角像素的颜色作为基线,并允许颜色变化的容差,这样图像中的噪声不会使裁剪无用

public BufferedImage getCroppedImage(BufferedImage source, double tolerance) {
   // Get our top-left pixel color as our "baseline" for cropping
   int baseColor = source.getRGB(0, 0);

   int width = source.getWidth();
   int height = source.getHeight();

   int topY = Integer.MAX_VALUE, topX = Integer.MAX_VALUE;
   int bottomY = -1, bottomX = -1;
   for(int y=0; y<height; y++) {
      for(int x=0; x<width; x++) {
         if (colorWithinTolerance(baseColor, source.getRGB(x, y), tolerance)) {
            if (x < topX) topX = x;
            if (y < topY) topY = y;
            if (x > bottomX) bottomX = x;
            if (y > bottomY) bottomY = y;
         }
      }
   }

   BufferedImage destination = new BufferedImage( (bottomX-topX+1), 
                 (bottomY-topY+1), BufferedImage.TYPE_INT_ARGB);

   destination.getGraphics().drawImage(source, 0, 0, 
               destination.getWidth(), destination.getHeight(), 
               topX, topY, bottomX, bottomY, null);

   return destination;
}

private boolean colorWithinTolerance(int a, int b, double tolerance) {
    int aAlpha  = (int)((a & 0xFF000000) >>> 24);   // Alpha level
    int aRed    = (int)((a & 0x00FF0000) >>> 16);   // Red level
    int aGreen  = (int)((a & 0x0000FF00) >>> 8);    // Green level
    int aBlue   = (int)(a & 0x000000FF);            // Blue level

    int bAlpha  = (int)((b & 0xFF000000) >>> 24);   // Alpha level
    int bRed    = (int)((b & 0x00FF0000) >>> 16);   // Red level
    int bGreen  = (int)((b & 0x0000FF00) >>> 8);    // Green level
    int bBlue   = (int)(b & 0x000000FF);            // Blue level

    double distance = Math.sqrt((aAlpha-bAlpha)*(aAlpha-bAlpha) +
                                (aRed-bRed)*(aRed-bRed) +
                                (aGreen-bGreen)*(aGreen-bGreen) +
                                (aBlue-bBlue)*(aBlue-bBlue));

    // 510.0 is the maximum distance between two colors 
    // (0,0,0,0 -> 255,255,255,255)
    double percentAway = distance / 510.0d;     

    return (percentAway > tolerance);
}
于 2012-09-28T18:57:58.933 回答
6

如果您希望白色部分不可见,最好的方法是使用图像过滤器并使白色像素透明, @PhiLho在此处讨论了一些很好的示例,如果您想调整图像大小使其边框不会有白色颜色,你可以用四个简单的循环来完成,我为你写的这个小方法可以解决问题,注意它只是裁剪图像的上半部分,你可以写剩下的,

    private Image getCroppedImage(String address) throws IOException{
    BufferedImage source = ImageIO.read(new File(address)) ;

    boolean flag = false ;
    int upperBorder = -1 ; 
    do{
        upperBorder ++ ;
        for (int c1 =0 ; c1 < source.getWidth() ; c1++){
            if(source.getRGB(c1, upperBorder) != Color.white.getRGB() ){
                flag = true;
                break ;
            }
        }

        if (upperBorder >= source.getHeight())
            flag = true ;
    }while(!flag) ;

    BufferedImage destination = new BufferedImage(source.getWidth(), source.getHeight() - upperBorder, BufferedImage.TYPE_INT_ARGB) ;
    destination.getGraphics().drawImage(source, 0, upperBorder*-1, null) ;

    return destination ;
}
于 2012-05-21T03:40:10.320 回答
0

这里只是另一个例子

private static BufferedImage autoCrop(BufferedImage sourceImage) {
    int left = 0;
    int right = 0;
    int top = 0;
    int bottom = 0;
    boolean firstFind = true;
    for (int x = 0; x < sourceImage.getWidth(); x++) {
        for (int y = 0; y < sourceImage.getWidth(); y++) {
            // pixel is not empty
            if (sourceImage.getRGB(x, y) != 0) {

                // we walk from left to right, thus x can be applied as left on first finding
                if (firstFind) {
                    left = x;
                }

                // update right on each finding, because x can grow only
                right = x;

                // on first find apply y as top
                if (firstFind) {
                    top = y;
                } else {
                    // on each further find apply y to top only if a lower has been found
                    top = Math.min(top, y);
                }

                // on first find apply y as bottom
                if (bottom == 0) {
                    bottom = y;
                } else {
                    // on each further find apply y to bottom only if a higher has been found
                    bottom = Math.max(bottom, y);
                }
                firstFind = false;
            }
        }
    }

    return sourceImage.getSubimage(left, top, right - left, bottom - top);
}
于 2017-09-28T19:30:31.587 回答
-1

img is original image source BufferedImage subImg = img.getSubimage(0, 0, img.getWidth() - 1, img.getHeight() - 1);

于 2019-04-21T16:57:39.633 回答