原Java代码: public static void main(String[] args) throws IOException { //源文件 File testDataDir = new File("d:\\5.jpg"); //处理后路径 final String destDir = "d:\\ss"; cleanLinesInImage(testDataDir, destDir); }
public static void cleanLinesInImage(File sfile, String destDir) throws IOException{ File destF = new File(destDir); if (!destF.exists()) { destF.mkdirs(); }
BufferedImage bufferedImage = ImageIO.read(sfile); int h = bufferedImage.getHeight(); int w = bufferedImage.getWidth();
// 灰度化 int[][] gray = new int[w][h]; for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { int argb = bufferedImage.getRGB(x, y); // 图像加亮(调整亮度识别率非常高) int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30); int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30); int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30); if (r >= 255) { r = 255; } if (g >= 255) { g = 255; } if (b >= 255) { b = 255; } gray[x][y] = (int) Math.pow((Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2) * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2); } }
// 二值化 int threshold = ostu(gray, w, h); BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY); for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { if (gray[x][y] > threshold) { gray[x][y] |= 0x00FFFF; } else { gray[x][y] &= 0xFF0000; } binaryBufferedImage.setRGB(x, y, gray[x][y]); } }
//去除干扰线条 for(int y = 1; y < h-1; y++){ for(int x = 1; x < w-1; x++){ boolean flag = false ; if(isBlack(binaryBufferedImage.getRGB(x, y))){ //左右均为空时,去掉此点 if(isWhite(binaryBufferedImage.getRGB(x-1, y)) && isWhite(binaryBufferedImage.getRGB(x+1, y))){ flag = true; } //上下均为空时,去掉此点 if(isWhite(binaryBufferedImage.getRGB(x, y+1)) && isWhite(binaryBufferedImage.getRGB(x, y-1))){ flag = true; } //斜上下为空时,去掉此点 if(isWhite(binaryBufferedImage.getRGB(x-1, y+1)) && isWhite(binaryBufferedImage.getRGB(x+1, y-1))){ flag = true; } if(isWhite(binaryBufferedImage.getRGB(x+1, y+1)) && isWhite(binaryBufferedImage.getRGB(x-1, y-1))){ flag = true; } if(flag){ binaryBufferedImage.setRGB(x,y,-1); } } } }
// 矩阵打印 for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if (isBlack(binaryBufferedImage.getRGB(x, y))) { System.out.print("*"); } else { System.out.print(" "); } } System.out.println(); } ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile.getName())); }
public static boolean isBlack(int colorInt) { Color color = new Color(colorInt); if (color.getRed() + color.getGreen() + color.getBlue() <= 300) { return true; } return false; }
public static boolean isWhite(int colorInt) { Color color = new Color(colorInt); if (color.getRed() + color.getGreen() + color.getBlue() > 300) { return true; } return false; }
public static int isBlackOrWhite(int colorInt) { if (getColorBright(colorInt) < 30 || getColorBright(colorInt) > 730) { return 1; } return 0; }
public static int getColorBright(int colorInt) { Color color = new Color(colorInt); return color.getRed() + color.getGreen() + color.getBlue(); }
public static int ostu(int[][] gray, int w, int h){ int[] histData = new int[w * h]; // Calculate histogram for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++){ int red = 0xFF & gray[x][y]; histData[red]++; } } // Total number of pixels int total = w * h; float sum = 0; for (int t = 0; t < 256; t++) sum += t * histData[t]; float sumB = 0; int wB = 0; int wF = 0; float varMax = 0; int threshold = 0; for (int t = 0; t < 256; t++) { wB += histData[t]; // Weight Background if (wB == 0) continue; wF = total - wB; // Weight Foreground if (wF == 0) break; sumB += (float) (t * histData[t]); float mB = sumB / wB; // Mean Background float mF = (sum - sumB) / wF; // Mean Foreground\ // Calculate Between Class Variance float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF); // Check if new maximum found if (varBetween > varMax) { varMax = varBetween; threshold = t; } } return threshold; } } **********我翻译的Delphi代码********** function getRGB(Bitmap:TBitmap;x,y:Integer):Integer; var p:PRGBTriple; begin p:=bitmap.ScanLine[y]; Inc(p,x); Result:=p^.rgbtBlue Shl 16 or p^.rgbtGreen shl 8 or p^.rgbtRed; end;
procedure setRGB(Bitmap:TBitmap;x,y:Integer;colorInt:Integer); var p:PRGBTriple; begin bitmap.Canvas.Pixels[x,y]:=colorInt; p:=bitmap.ScanLine[y]; Inc(p,x); p^.rgbtRed:=GetRValue(colorInt); p^.rgbtGreen:=GetGValue(colorInt); p^.rgbtBlue:=GetBValue(colorInt); end;
function RGBToColor(R,G,B: byte): TColor; begin Result := B Shl 16 or G shl 8 or R; end;
procedure ColorToRGB(color:TColor;var R,G,B:Integer); begin R := Color and $FF; G := (Color and $FF00) shr 8; B := (Color and $FF0000) shr 16; end;
function RemoveBackgroud(src:TBitmap):TBitmap; var p: PRGBTriple; x,y:Integer; c:TColor; begin result := TBitmap.Create; result.Assign(src); Result.PixelFormat := pf24bit; for y := 0 to Result.Height - 1 do begin p:=Result.ScanLine[y]; for x := 0 to Result.Width - 1 do begin c:=RGBToColor(p^.rgbtRed,p^.rgbtGreen,p^.rgbtBlue); if isWhite(c) then begin p^.rgbtRed:=255; p^.rgbtGreen:=255; p^.rgbtBlue:=255; end else begin p^.rgbtRed:=0; p^.rgbtGreen:=0; p^.rgbtBlue:=0; end; Inc(p); end; end; end;
function isBlack(colorInt:Integer):Boolean; var r,g,b:byte; c:LongInt; begin c:=Graphics.ColorToRGB(colorInt); r:=GetRValue(c); g:=GetGValue(c); b:=GetBValue(c); Result:=r+g+b<=300; end;
function isWhite(colorInt:Integer):Boolean; var r,g,b:byte; c:LongInt; begin c:=Graphics.ColorToRGB(colorInt); r:=GetRValue(c); g:=GetGValue(c); b:=GetBValue(c); Result:=r+g+b>300; end;
function getColorBright(colorInt:Integer):Integer; var r,g,b:byte; c:LongInt; begin c:=Graphics.ColorToRGB(colorInt); r:=GetRValue(c); g:=GetGValue(c); b:=GetBValue(c); Result:=r+g+b; end;
function isBlackOrWhite(colorInt:Integer):Integer; begin if (getColorBright(colorInt)<30) or (getColorBright(colorInt)>730) then Result:=1 else Result:=0; end;
function ostu(gray:MyInt; w, h:Integer):Integer; var hisData:array of Integer; Total,wB,wF,t,threshold,x,y:Integer; red:Byte; varBetween,mB,mF,varMax,sum,sumB:Single; begin SetLength(hisData,w*h); for x:=0 to w-1 do begin for y:=0 to h-1 do begin red:=$FF and gray[x,y]; hisData[red]:=hisData[red]+1; end; end; total := w * h; sum := 0; for t:=0 to 255 do sum:=sum+t*hisData[t];
sumB := 0; wB := 0; varMax := 0; threshold := 0; for t:=0 to 255 do begin wB := wB+hisData[t]; // Weight Background if (wB = 0) then continue;
wF := total - wB; // Weight Foreground if (wF = 0) then break;
sumB := sumB+ (t * hisData[t]);
mB := sumB / wB; // Mean Background mF := (sum - sumB) / wF; // Mean Foreground
// Calculate Between Class Variance varBetween := wB * wF * (mB - mF) * (mB - mF);
// Check if new maximum found if (varBetween > varMax) then begin varMax := varBetween; threshold := t; end; end; Result:=threshold; end;
procedure cleanLinesInImage(sfile,destDir:String); var bufferedImage,binaryBufferedImage:TBitmap; argb,x,y,I,w,h,r,g,b,threshold:Integer; gray:MyInt; p: PRGBTriple; flag:Boolean; begin bufferedImage:=TBitmap.Create ; bufferedImage.LoadFromFile(sfile); h := bufferedImage.Height; w := bufferedImage.Width; // 灰度化 setLength(gray,w); for I:=0 to w-1 do SetLength(gray[I],h); for x := 0 to w-1 do begin for y := 0 to h-1 do begin argb:=bufferedImage.Canvas.Pixels[x,y]; // 图像加亮(调整亮度识别率非常高) r := Trunc(((argb shl 16) and $FF) * 1.1 + 30); g := Trunc(((argb shl 8) and $FF) * 1.1 + 30); b := Trunc(((argb shl 0) and $FF) * 1.1 + 30); if (r >= 255) then r := 255; if (g >= 255) then g := 255; if (b >= 255) then b := 255; gray[x][y] := Trunc(Math.Power((Math.power(r, 2.2) * 0.2973 + Math.power(g, 2.2) * 0.6274 + Math.power(b, 2.2) * 0.0753), 1 / 2.2)); end; end; // 二值化 threshold := ostu(gray, w, h); binaryBufferedImage :=TBitmap.Create ; binaryBufferedImage.Width :=w; binaryBufferedImage.Height :=h; binaryBufferedImage.PixelFormat:=pf24bit; for y := 0 to h-1 do begin p:=binaryBufferedImage.ScanLine[y]; for x := 0 to w-1 do begin if (gray[x][y] > threshold) then gray[x][y] := gray[x][y] or $00FFFF else gray[x][y] := gray[x][y] and $FF0000; ColorToRGB(gray[x][y],r,g,b); p^.rgbtRed:=r; p^.rgbtGreen:=g; p^.rgbtBlue:=b; Inc(p); end; end; //去除干扰线条 for y := 1 to h-2 do begin p:=binaryBufferedImage.ScanLine[y]; for x := 1 to w-2 do begin Inc(p); flag := false; if isBlack(RGBToColor(p^.rgbtRed,p^.rgbtGreen,p^.rgbtBlue)) then begin //左右均为空时,去掉此点 if (isWhite(getRGB(binaryBufferedImage,x-1, y)) and isWhite(getRGB(binaryBufferedImage,x+1, y))) then flag := true; //上下均为空时,去掉此点 if (isWhite(getRGB(binaryBufferedImage,x, y+1)) and isWhite(getRGB(binaryBufferedImage,x, y-1))) then flag := true; //斜上下为空时,去掉此点 if (isWhite(getRGB(binaryBufferedImage,x-1, y+1)) and isWhite(getRGB(binaryBufferedImage,x+1, y-1))) then flag := true; if (isWhite(getRGB(binaryBufferedImage,x+1, y+1)) and isWhite(getRGB(binaryBufferedImage,x-1, y-1))) then flag := true; if (flag) then setRGB(binaryBufferedImage,x,y,-1); end; end; end; // 矩阵打印 // for y := 0 to h-1 do // begin // for x := 0 to w-1 do // begin // if (isBlack(getRGB(binaryBufferedImage,x, y))) // begin // System.out.print("*"); // end else // begin // System.out.print(" "); // end; // end; // end; binaryBufferedImage.SaveToFile(destDir); end;
----------------------------------------------
vvvvvvvvvv
type MyInt=array of array of Integer; PRGBTripleArray = ^TRGBTripleArray; TRGBTripleArray = array[0..4095] of TRGBTriple;
// 去除图片噪点 并将彩色转为纯色(黑色) function removeBackgroud(src:TBitmap):TBitmap; // 去噪 procedure cleanLinesInImage(bufferedImage,binaryBufferedImage:TBitmap);
function getRGB(Bitmap:TBitmap;x,y:Integer):Integer; procedure setRGB(Bitmap:TBitmap;x,y:Integer;colorInt:Integer);
implementation
function getRGB(Bitmap:TBitmap;x,y:Integer):Integer; var p:PRGBTripleArray; begin p:=bitmap.ScanLine[y]; Result:=p[x].rgbtBlue Shl 16 xor p[x].rgbtGreen shl 8 xor p[x].rgbtRed; end;
procedure setRGB(Bitmap:TBitmap;x,y:Integer;colorInt:Integer); var p:PRGBTripleArray; begin p:=bitmap.ScanLine[y]; p[x].rgbtRed:=GetRValue(colorInt); p[x].rgbtGreen:=GetGValue(colorInt); p[x].rgbtBlue:=GetBValue(colorInt); end;
function RGBToColor(R,G,B: byte): TColor; begin Result := B Shl 16 xor G shl 8 xor R; end;
procedure ColorToRGB(color:TColor;var R,G,B:Integer); begin R := Color and $FF; G := (Color and $FF00) shr 8; B := (Color and $FF0000) shr 16; end;
function isWhite(colorInt:Integer):Boolean; var r,g,b:byte; c:LongInt; begin c:=Graphics.ColorToRGB(colorInt); r:=GetRValue(c); g:=GetGValue(c); b:=GetBValue(c); if (r + g + b > 200) and (r + g + b < 500) then Result:=False else Result:=True; end;
function RemoveBackgroud(src:TBitmap):TBitmap; var p: PRGBTripleArray; x,y:Integer; c:TColor; begin result := TBitmap.Create; result.Assign(src); Result.PixelFormat := pf24bit; for y := 0 to Result.Height - 1 do begin p:=Result.ScanLine[y]; for x := 0 to Result.Width - 1 do begin c:=RGBToColor(p[x].rgbtRed,p[x].rgbtGreen,p[x].rgbtBlue); if isWhite(c) then begin p[x].rgbtRed:=255; p[x].rgbtGreen:=255; p[x].rgbtBlue:=255; end else begin p[x].rgbtRed:=0; p[x].rgbtGreen:=0; p[x].rgbtBlue:=0; end; end; end; end;
function isBlack2(colorInt:Integer):Boolean; var r,g,b:byte; c:LongInt; begin c:=Graphics.ColorToRGB(colorInt); r:=GetRValue(c); g:=GetGValue(c); b:=GetBValue(c); Result:=r+g+b<=300; end;
function isWhite2(colorInt:Integer):Boolean; var r,g,b:byte; c:LongInt; begin c:=Graphics.ColorToRGB(colorInt); r:=GetRValue(c); g:=GetGValue(c); b:=GetBValue(c); Result:=r+g+b>300; end;
function getColorBright(colorInt:Integer):Integer; var r,g,b:byte; c:LongInt; begin c:=Graphics.ColorToRGB(colorInt); r:=GetRValue(c); g:=GetGValue(c); b:=GetBValue(c); Result:=r+g+b; end;
function isBlackOrWhite(colorInt:Integer):Integer; begin if (getColorBright(colorInt)<30) or (getColorBright(colorInt)>730) then Result:=1 else Result:=0; end;
function ostu(gray:MyInt; w, h:Integer):Integer; var hisData:array of Integer; Total,wB,wF,t,threshold,x,y:Integer; red:Byte; varBetween,mB,mF,varMax,sum,sumB:Single; begin SetLength(hisData,w*h); for x:=0 to w-1 do begin for y:=0 to h-1 do begin red:=$FF and gray[x,y]; hisData[red]:=hisData[red]+1; end; end; total := w * h; sum := 0; for t:=0 to 255 do sum:=sum+t*hisData[t];
sumB := 0; wB := 0; varMax := 0; threshold := 0; for t:=0 to 255 do begin wB := wB+hisData[t]; // Weight Background if (wB = 0) then continue;
wF := total - wB; // Weight Foreground if (wF = 0) then break;
sumB := sumB+ (t * hisData[t]);
mB := sumB / wB; // Mean Background mF := (sum - sumB) / wF; // Mean Foreground
// Calculate Between Class Variance varBetween := wB * wF * (mB - mF) * (mB - mF);
// Check if new maximum found if (varBetween > varMax) then begin varMax := varBetween; threshold := t; end; end; Result:=threshold; end;
procedure cleanLinesInImage(bufferedImage,binaryBufferedImage:TBitmap); var argb,x,y,I,w,h,r,g,b:Integer; // threshold:Integer; gray:MyInt; //p: PRGBTripleArray; flag:Boolean; begin h := bufferedImage.Height; w := bufferedImage.Width; // 灰度化 setLength(gray,w); for I:=0 to w-1 do SetLength(gray[I],h); for x := 0 to w-1 do begin for y := 0 to h-1 do begin argb:=getRGB(bufferedImage,x,y); // 图像加亮(调整亮度识别率非常高) r := Trunc(((argb shl 16) and $FF) * 1.1 + 30); g := Trunc(((argb shl 8) and $FF) * 1.1 + 30); b := Trunc(((argb shl 0) and $FF) * 1.1 + 30); if (r >= 255) then r := 255; if (g >= 255) then g := 255; if (b >= 255) then b := 255; gray[x][y] := Trunc(Math.Power((Math.power(r, 2.2) * 0.2973 + Math.power(g, 2.2) * 0.6274 + Math.power(b, 2.2) * 0.0753), 1 / 2.2)); end; end; // 二值化 //threshold := ostu(gray, w, h); //binaryBufferedImage :=TBitmap.Create ; binaryBufferedImage.Assign(bufferedImage); binaryBufferedImage.PixelFormat:=pf24bit; // for y := 0 to h-1 do // begin // for x := 0 to w-1 do // begin // if (gray[x][y] > threshold) then // gray[x][y] := gray[x][y] xor $00FFFF else // gray[x][y] := gray[x][y] and $FF0000; // setRGB(binaryBufferedImage,x,y,gray[x,y]); // end; // end; //去除干扰线条 for y := 1 to h-2 do begin for x := 1 to w-2 do begin flag := false; if isBlack2(getRGB(binaryBufferedImage,x,y)) then begin //左右均为空时,去掉此点 if (isWhite2(getRGB(binaryBufferedImage,x-1, y)) and isWhite2(getRGB(binaryBufferedImage,x+1, y))) then flag := true; //上下均为空时,去掉此点 if (isWhite2(getRGB(binaryBufferedImage,x, y+1)) and isWhite2(getRGB(binaryBufferedImage,x, y-1))) then flag := true; //斜上下为空时,去掉此点 if (isWhite2(getRGB(binaryBufferedImage,x-1, y+1)) and isWhite2(getRGB(binaryBufferedImage,x+1, y-1))) then flag := true; if (isWhite2(getRGB(binaryBufferedImage,x+1, y+1)) and isWhite2(getRGB(binaryBufferedImage,x-1, y-1))) then flag := true; if (flag) then setRGB(binaryBufferedImage,x,y,-1); end; end; end; end;
----------------------------------------------
vvvvvvvvvv