写了四个方法,分别实现图片的灰度化,直方图均衡,灰度线性变化,灰度拉伸,其中好多地方特别是灰度拉伸这一块觉得自己实现的有问题,请大大们多多指教。
1 import java.awt.Image; 2 import java.awt.image.BufferedImage; 3 import java.awt.image.PixelGrabber; 4 import java.io.File; 5 import java.io.IOException; 6 import java.util.Iterator; 7 import java.util.Scanner; 8 9 import javax.imageio.ImageIO; 10 import javax.imageio.ImageReader; 11 import javax.imageio.stream.ImageInputStream; 12 import javax.swing.filechooser.FileNameExtensionFilter; 13 14 15 public class ImageProcessing { 16 17 /** 18 * @param args 19 */ 20 21 static Image tmp; 22 static int iwidth,iheight;//图像宽度,高度 23 static double ma,mi;//线性变化灰度上下限 24 static int[] pixels;//图像所有像素点 25 static int[] pixels2;//备份pixels,用于灰度线性变化 26 static int[] pixels3;//备份pixels,用于灰度拉伸 27 static int[] histogram=new int[256]; 28 static String filename=null,directory=null,fileFormat=null;//要变换的图像路径名+文件名 29 public static void main(String[] args) throws IOException, InterruptedException { 30 // TODO Auto-generated method stub 31 System.out.println("请输入文件路径"); 32 Scanner in=new Scanner(System.in); 33 directory=in.next();//读入文件路径 34 System.out.println("请输入文件名"); 35 filename=in.next();//读入文件名 36 System.out.println("请输入文件格式"); 37 fileFormat=in.next();//读入文件格式 38 grayImage();//灰度化 39 histogramEqualization();//均衡化并输出 40 System.out.println("请输入线性变换的灰度下限"); 41 mi=in.nextInt(); 42 System.out.println("请输入线性变换的灰度上限"); 43 ma=in.nextInt(); 44 linearConversion(); 45 grayStretch(); 46 } 47 48 //灰度化 49 public static void grayImage() throws IOException, InterruptedException 50 { 51 File input=new File(directory+"\"+filename+"."+fileFormat); 52 BufferedImage reader=ImageIO.read(input);//图片文件读入流 53 54 iwidth=reader.getWidth(); 55 iheight=reader.getHeight(); 56 pixels=new int[iwidth*iheight]; 57 pixels2=new int[iwidth*iheight]; 58 pixels3=new int[iwidth*iheight]; 59 60 BufferedImage grayImage=new BufferedImage(iwidth,iheight,BufferedImage.TYPE_BYTE_GRAY);//无符号 byte 灰度级图像 61 for(int i=0;i<iwidth;i++) 62 for(int j=0;j<iheight;j++) 63 { 64 int rgb=reader.getRGB(i, j); 65 int grey=(int) ((0.3*((rgb&0xff0000)>>16)+0.59*((rgb&0xff00)>>8))+0.11*((rgb&0xff))); 66 rgb=255<<24|grey<<16|grey<<8|grey; 67 grayImage.setRGB(i, j, rgb); 68 }//读入所有像素,转换图像信号,使其灰度化 69 tmp=grayImage; 70 PixelGrabber pg=new PixelGrabber(tmp, 0, 0, iwidth, iheight, pixels,0,iwidth); 71 pg.grabPixels();//将该灰度化后的图片所有像素点读入pixels数组 72 PixelGrabber pg2=new PixelGrabber(tmp, 0, 0, iwidth, iheight, pixels2,0,iwidth); 73 pg2.grabPixels(); 74 PixelGrabber pg3=new PixelGrabber(tmp, 0, 0, iwidth, iheight, pixels3,0,iwidth); 75 pg3.grabPixels();// 76 } 77 78 //直方图均衡 79 public static void histogramEqualization() throws InterruptedException, IOException 80 { 81 //PixelGrabber pg=new PixelGrabber(tmp, 0, 0, iwidth, iheight, pixels,0,iwidth); 82 //pg.grabPixels(); 83 BufferedImage greyImage=new BufferedImage(iwidth, iheight, BufferedImage.TYPE_BYTE_GRAY); 84 85 for(int i=0;i<iheight-1;i++) 86 for(int j=0;j<iwidth-1;j++) 87 { 88 int grey=pixels[i*iwidth+j]&0xff; 89 histogram[grey]++; 90 }//计算每一个灰度级的像素数 91 double a=(double)255/(iwidth*iheight); 92 double[] c=new double[256]; 93 c[0]=(a*histogram[0]); 94 for(int i=1;i<256;i++) 95 c[i]=c[i-1]+(int)(a*histogram[i]);//直方图均衡化(离散情况) 96 for(int i=0;i<iheight;i++) 97 for(int j=0;j<iwidth;j++) 98 { 99 int grey=pixels[i*iwidth+j]&0x0000ff; 100 int hist=(int)c[grey]; 101 pixels[i*iwidth+j]=255<<24|hist<<16|hist<<8|hist; 102 greyImage.setRGB(j, i, pixels[i*iwidth+j]); 103 } 104 tmp=greyImage; 105 File f=new File(directory+"\"+"均衡化.jpg"); 106 ImageIO.write(greyImage, "jpg", f);//在原路径下输出均衡化后的图像 107 } 108 109 //灰度线性变换 110 public static void linearConversion() throws IOException 111 { 112 int min=255,max=0; 113 for(int i=0;i<256;i++) 114 { 115 if(histogram[i]>0) 116 { 117 if(i<min) 118 min=i; 119 if(i>max) 120 max=i; 121 } 122 }//找出灰度的最大级和最小级 123 double k=(ma-mi)/(max-min);//计算变换比 124 BufferedImage greyImage=new BufferedImage(iwidth, iheight, BufferedImage.TYPE_BYTE_GRAY); 125 for(int i=0;i<iheight;i++) 126 for(int j=0;j<iwidth;j++) 127 { 128 int grey=pixels2[i*iwidth+j]&0xff; 129 grey=(int)(k*(grey-min)+mi); 130 if(grey>255) 131 grey=255; 132 if(grey<0) 133 grey=0; 134 pixels2[i*iwidth+j]=255<<24|grey<<16|grey<<8|grey; 135 greyImage.setRGB(j, i, pixels2[i*iwidth+j]); 136 }//灰度线性变换 137 File f=new File(directory+"\"+"线性变换.jpg"); 138 ImageIO.write(greyImage, "jpg", f);//在原路径下输出均衡化后的图像 139 } 140 141 //灰度拉伸 142 public static void grayStretch() throws IOException 143 { 144 int min = 0,max = 1; 145 int sum=0; 146 for(int i=0;i<256;i++) 147 { 148 sum+=histogram[i]; 149 if(sum>iwidth*iheight*0.05) 150 { 151 min=i; 152 break; 153 } 154 }//找出灰度的大部分像素范围的最小级 155 sum=0; 156 for(int i=255;i>=0;i--) 157 { 158 sum+=histogram[i]; 159 if(sum>iwidth*iheight*0.05) 160 { 161 max=i; 162 break; 163 } 164 }//找出灰度的大部分像素范围的最大级 165 double k=(ma-mi)/(max-min); 166 BufferedImage greyImage=new BufferedImage(iwidth, iheight, BufferedImage.TYPE_BYTE_GRAY); 167 for(int i=0;i<iheight;i++) 168 for(int j=0;j<iwidth;j++) 169 { 170 int grey=pixels3[i*iwidth+j]&0xff; 171 if(grey<min) 172 grey=(int) mi;//小于min部分设为下限 173 else if(grey>=max) 174 grey=(int) ma;//大于max部分设为上限 175 else 176 { 177 grey=(int)(k*(grey-min)+mi); 178 if(grey>255) 179 grey=255; 180 if(grey<0) 181 grey=0; 182 }//大部分区域线性变换 183 184 pixels3[i*iwidth+j]=255<<24|grey<<16|grey<<8|grey; 185 greyImage.setRGB(j, i, pixels3[i*iwidth+j]); 186 }//灰度拉伸 187 File f=new File(directory+"\"+"灰度拉伸.jpg"); 188 ImageIO.write(greyImage, "jpg", f);//在原路径下输出拉伸后的图像 189 } 190 }