java实现图像的直方图均衡以及灰度线性变化,灰度拉伸

写了四个方法,分别实现图片的灰度化,直方图均衡,灰度线性变化,灰度拉伸,其中好多地方特别是灰度拉伸这一块觉得自己实现的有问题,请大大们多多指教。

  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 }
原文地址:https://www.cnblogs.com/freestyle-sn/p/3618349.html