一 讀取bmp圖片資料
// 擷取待檢測映像 ,資料儲存在數組 nData[],nB[] ,nG[] ,nR[]中</p><p>public void getBMPImage(String source) throws Exception {</p><p>clearNData(); //清除資料儲存區<br />FileInputStream fs = null;</p><p>try {<br />fs = new FileInputStream(source);<br />int bfLen = 14;<br />byte bf[] = new byte[bfLen];<br />fs.read(bf, 0, bfLen); // 讀取14位元組BMP檔案頭<br />int biLen = 40;<br />byte bi[] = new byte[biLen];<br />fs.read(bi, 0, biLen); // 讀取40位元組BMP資訊頭</p><p>// 源圖寬度<br />nWidth = (((int) bi[7] & 0xff) << 24)<br />| (((int) bi[6] & 0xff) << 16)<br />| (((int) bi[5] & 0xff) << 8) | (int) bi[4] & 0xff;</p><p>// 源圖高度<br />nHeight = (((int) bi[11] & 0xff) << 24)<br />| (((int) bi[10] & 0xff) << 16)<br />| (((int) bi[9] & 0xff) << 8) | (int) bi[8] & 0xff;</p><p>// 位元<br />nBitCount = (((int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;</p><p>// 源圖大小<br />int nSizeImage = (((int) bi[23] & 0xff) << 24)<br />| (((int) bi[22] & 0xff) << 16)<br />| (((int) bi[21] & 0xff) << 8) | (int) bi[20] & 0xff;</p><p>// 對24位BMP進行解析<br />if (nBitCount == 24){<br />int nPad = (nSizeImage / nHeight) - nWidth * 3;<br />nData = new int[nHeight * nWidth];<br />nB=new int[nHeight * nWidth];<br />nR=new int[nHeight * nWidth];<br />nG=new int[nHeight * nWidth];<br />byte bRGB[] = new byte[(nWidth + nPad) * 3 * nHeight];<br />fs.read(bRGB, 0, (nWidth + nPad) * 3 * nHeight);<br />int nIndex = 0;<br />for (int j = 0; j < nHeight; j++){<br />for (int i = 0; i < nWidth; i++) {<br />nData[nWidth * (nHeight - j - 1) + i] = (255 & 0xff) << 24<br />| (((int) bRGB[nIndex + 2] & 0xff) << 16)<br />| (((int) bRGB[nIndex + 1] & 0xff) << 8)<br />| (int) bRGB[nIndex] & 0xff;<br />nB[nWidth * (nHeight - j - 1) + i]=(int) bRGB[nIndex]& 0xff;<br />nG[nWidth * (nHeight - j - 1) + i]=(int) bRGB[nIndex+1]& 0xff;<br />nR[nWidth * (nHeight - j - 1) + i]=(int) bRGB[nIndex+2]& 0xff;<br />nIndex += 3;<br />}<br />nIndex += nPad;<br />}<br />// Toolkit kit = Toolkit.getDefaultToolkit();<br />// image = kit.createImage(new MemoryImageSource(nWidth, nHeight,<br />// nData, 0, nWidth));</p><p>/*<br />//調試資料的讀取 </p><p>FileWriter fw = new FileWriter("C://Documents and Settings//Administrator//My Documents//nDataRaw.txt");//建立新檔案<br />PrintWriter out = new PrintWriter(fw);<br />for(int j=0;j<nHeight;j++){<br />for(int i=0;i<nWidth;i++){<br />out.print((65536*256+nData[nWidth * (nHeight - j - 1) + i])+"_"<br />+nR[nWidth * (nHeight - j - 1) + i]+"_"<br />+nG[nWidth * (nHeight - j - 1) + i]+"_"<br />+nB[nWidth * (nHeight - j - 1) + i]+" ");</p><p>}<br />out.println("");<br />}<br />out.close();<br />*/<br />}<br />}<br />catch (Exception e) {<br />e.printStackTrace();<br />throw new Exception(e);<br />}<br />finally {<br />if (fs != null) {<br />fs.close();<br />}<br />}<br />// return image;<br />}
二 由r g b 擷取灰階數組
public int[] getBrightnessData(int rData[],int gData[],int bData[]){</p><p>int brightnessData[]=new int[rData.length];<br />if(rData.length!=gData.length || rData.length!=bData.length<br />|| bData.length!=gData.length){<br />return brightnessData;<br />}<br />else {<br />for(int i=0;i<bData.length;i++){<br />double temp=0.3*rData[i]+0.59*gData[i]+0.11*bData[i];<br />brightnessData[i]=(int)(temp)+((temp-(int)(temp))>0.5?1:0);<br />}<br />return brightnessData;<br />}</p><p>}
三 長條圖均衡化
public int [] equilibrateGray(int[] PixelsGray,int width,int height)<br />{<br />int gray;<br />int length=PixelsGray.length;<br />int FrequenceGray[]=new int[length];<br />int SumGray[]=new int[256];<br />int ImageDestination[]=new int[length];<br />for(int i = 0; i <length ;i++)<br />{<br />gray=PixelsGray[i];<br />FrequenceGray[gray]++;<br />}<br />// 灰階均衡化<br />SumGray[0]=FrequenceGray[0];<br />for(int i=1;i<256;i++){<br />SumGray[i]=SumGray[i-1]+FrequenceGray[i];<br />}<br />for(int i=0;i<256;i++) {<br />SumGray[i]=(int)(SumGray[i]*255/length);<br />}<br />for(int i=0;i<height;i++)<br />{<br />for(int j=0;j<width;j++)<br />{<br />int k=i*width+j;<br />ImageDestination[k]=0xFF000000 | ((SumGray[PixelsGray[k]]<<<br />16 ) | (SumGray[PixelsGray[k]]<< 8 ) | SumGray[PixelsGray[k]]);<br />}<br />}<br />return ImageDestination;<br />}
四 laplace2階濾波,增強邊緣,映像銳利化
public int[] laplace2DFileter(int []data,int width,int height){</p><p>int filterData[]=new int[data.length];<br />int min=10000;<br />int max=-10000;<br />for(int i=0;i<height;i++){<br />for(int j=0;j<width;j++){<br />if(i==0 || i==height-1 || j==0 || j==width-1)<br />filterData[i*width+j]=data[i*width+j];<br />else<br />filterData[i*width+j]=9*data[i*width+j]-data[i*width+j-1]-data[i*width+j+1]<br />-data[(i-1)*width+j]-data[(i-1)*width+j-1]-data[(i-1)*width+j+1]<br />-data[(i+1)*width+j]-data[(i+1)*width+j-1]-data[(i+1)*width+j+1];<br />if(filterData[i*width+j]<min)<br />min=filterData[i*width+j];<br />if(filterData[i*width+j]>max)<br />max=filterData[i*width+j];<br />}<br />}<br />// System.out.println("max: "+max);<br />// System.out.println("min: "+min);</p><p>for(int i=0;i<width*height;i++){<br />filterData[i]=(filterData[i]-min)*255/(max-min);<br />}<br />return filterData;<br />}
五 laplace2階增強濾波,增強邊緣,增強係數delt
public int[] laplaceHigh2DFileter(int []data,int width,int height,double delt){</p><p>int filterData[]=new int[data.length];<br />int min=10000;<br />int max=-10000;<br />for(int i=0;i<height;i++){<br />for(int j=0;j<width;j++){<br />if(i==0 || i==height-1 || j==0 || j==width-1)<br />filterData[i*width+j]=(int)((1+delt)*data[i*width+j]);<br />else<br />filterData[i*width+j]=(int)((9+delt)*data[i*width+j]-data[i*width+j-1])-data[i*width+j+1]<br />-data[(i-1)*width+j]-data[(i-1)*width+j-1]-data[(i-1)*width+j+1]<br />-data[(i+1)*width+j]-data[(i+1)*width+j-1]-data[(i+1)*width+j+1];<br />if(filterData[i*width+j]<min)<br />min=filterData[i*width+j];<br />if(filterData[i*width+j]>max)<br />max=filterData[i*width+j];<br />}<br />}<br />for(int i=0;i<width*height;i++){<br />filterData[i]=(filterData[i]-min)*255/(max-min);<br />}<br />return filterData;<br />}<br />
六 局部閾值處理2值化
// 局部閾值處理2值化,niblack's method<br />/*原理:<br />T(x,y)=m(x,y) + k*s(x,y)<br />取一個寬度為w的矩形框,(x,y)為這個框的中心。<br />統計框內資料,T(x,y)為閾值,m(x,y)為均值,s(x,y)為均方差,k為參數(推薦-2)計算出t再對(x,y)進行切割255/0。<br />這個演算法的優點是 速度快,效果好。<br />缺點是 niblack's method會產生一定的雜訊。<br />*/</p><p>public int[] localThresholdProcess(int []data,int width,int height,int w,int h,double coefficients,double gate){<br />int[] processData=new int[data.length];<br />for(int i=0;i<data.length;i++){<br />processData[i]=255;<br />}</p><p>if(data.length!=width*height)<br />return processData;</p><p>int wNum=width/w;<br />int hNum=height/h;<br />int delt[]=new int[w*h];</p><p>//System.out.println("w; "+w+" h:"+h+" wNum:"+wNum+" hNum:"+hNum);</p><p>for(int j=0;j<hNum;j++){<br />for(int i=0;i<wNum;i++){<br />//for(int j=0;j<1;j++){<br />// for(int i=0;i<1;i++){<br />for(int n=0;n<h;n++)<br />for(int k=0;k<w;k++){<br />delt[n*w+k]=data[(j*h+n)*width+i*w+k];<br />//System.out.print("delt["+(n*w+k)+"]: "+delt[n*w+k]+" ");<br />}<br />//System.out.println();<br />/*<br />for(int n=0;n<h;n++)<br />for(int k=0;k<w;k++){<br />System.out.print("data["+((j*h+n)*width+i*w+k)+"]: "+data[(j*h+n)*width+i*w+k]+" ");<br />}<br />System.out.println();<br />*/<br />delt=thresholdProcess(delt,w,h,coefficients,gate);<br />for(int n=0;n<h;n++)<br />for(int k=0;k<w;k++){<br />processData[(j*h+n)*width+i*w+k]=delt[n*w+k];<br />// System.out.print("delt["+(n*w+k)+"]: "+delt[n*w+k]+" ");<br />}<br />//System.out.println();<br />/*<br />for(int n=0;n<h;n++)<br />for(int k=0;k<w;k++){<br />System.out.print("processData["+((j*h+n)*width+i*w+k)+"]: "+processData[(j*h+n)*width+i*w+k]+" ");<br />}<br />System.out.println();<br />*/<br />}<br />}</p><p>return processData;<br />}
七 全域閾值處理2值化
public int[] thresholdProcess(int []data,int width,int height,double coefficients,double gate){<br />int [] processData=new int[data.length];<br />if(data.length!=width*height)<br />return processData;<br />else{<br />double sum=0;<br />double average=0;<br />double variance=0;<br />double threshold;</p><p>if( gate!=0){<br />threshold=gate;<br />}<br />else{<br />for(int i=0;i<width*height;i++){<br />sum+=data[i];<br />}<br />average=sum/(width*height);</p><p>for(int i=0;i<width*height;i++){<br />variance+=(data[i]-average)*(data[i]-average);<br />}<br />variance=Math.sqrt(variance);<br />threshold=average-coefficients*variance;<br />}</p><p>for(int i=0;i<width*height;i++){<br />if(data[i]>threshold)<br />processData[i]=255;<br />else<br />processData[i]=0;<br />}</p><p>return processData;<br />}<br />}
八 垂直邊緣檢測,sobel運算元
public int[] verticleEdgeCheck(int []data,int width,int height,int sobelCoefficients) throws Exception{<br />int filterData[]=new int[data.length];<br />int min=10000;<br />int max=-10000;<br />if(data.length!=width*height)<br />return filterData;</p><p>try{</p><p>for(int i=0;i<height;i++){<br />for(int j=0;j<width;j++){<br />if(i==0 || i==1 || i==height-1 || i==height-2<br />||j==0 || j==1 || j==width-1 || j==width-2){<br />filterData[i*width+j]=data[i*width+j];<br />}<br />else{<br />double average;<br />//中心的九個像素點<br />//average=data[i*width+j]-Math.sqrt(2)*data[i*width+j-1]+Math.sqrt(2)*data[i*width+j+1]<br />average=data[i*width+j]-sobelCoefficients*data[i*width+j-1]+sobelCoefficients*data[i*width+j+1]<br />-data[(i-1)*width+j-1]+data[(i-1)*width+j+1]<br />-data[(i+1)*width+j-1]+data[(i+1)*width+j+1];<br />filterData[i*width+j]=(int)(average);<br />}<br />if(filterData[i*width+j]<min)<br />min=filterData[i*width+j];<br />if(filterData[i*width+j]>max)<br />max=filterData[i*width+j];<br />}<br />}<br />for(int i=0;i<width*height;i++){<br />filterData[i]=(filterData[i]-min)*255/(max-min);<br />}</p><p>}<br />catch (Exception e)<br />{<br />e.printStackTrace();<br />throw new Exception(e);<br />} </p><p>return filterData;<br />}
九 映像平滑:3*3掩模處理(平均處理),降低雜訊
public int[] filter(int []data,int width,int height) throws Exception{</p><p>int filterData[]=new int[data.length];<br />int min=10000;<br />int max=-10000;<br />if(data.length!=width*height)<br />return filterData;</p><p>try{</p><p>for(int i=0;i<height;i++){<br />for(int j=0;j<width;j++){<br />if(i==0 || i==1 || i==height-1 || i==height-2<br />||j==0 || j==1 || j==width-1 || j==width-2){<br />filterData[i*width+j]=data[i*width+j];<br />}<br />else{<br />double average;<br />//中心的九個像素點<br />average=(data[i*width+j]+data[i*width+j-1]+data[i*width+j+1]<br />+data[(i-1)*width+j]+data[(i-1)*width+j-1]+data[(i-1)*width+j+1]<br />+data[(i+1)*width+j]+data[(i+1)*width+j-1]+data[(i+1)*width+j+1])/9;<br />filterData[i*width+j]=(int)(average);<br />}<br />if(filterData[i*width+j]<min)<br />min=filterData[i*width+j];<br />if(filterData[i*width+j]>max)<br />max=filterData[i*width+j];<br />}<br />}<br />for(int i=0;i<width*height;i++){<br />filterData[i]=(filterData[i]-min)*255/(max-min);<br />}</p><p>}<br />catch (Exception e)<br />{<br />e.printStackTrace();<br />throw new Exception(e);<br />} </p><p>return filterData;<br />}