圖像處理之距離變換

圖像處理之距離變換java

概述算法

距離變換是二值圖像處理與操做中經常使用手段,在骨架提取,圖像窄化中常有應用。距離ide

變換的結果是獲得一張與輸入圖像相似的灰度圖像,可是灰度值只出如今前景區域。並oop

且越遠離背景邊緣的像素灰度值越大。ui

基本思想this

根據度量距離的方法不一樣,距離變換有幾種不一樣的方法,假設像素點p1(x1, y1), spa

p2(x2, y2)計算距離的方法常見的有:code

1.      歐幾里德距離,Distance =orm

2.      曼哈頓距離(City Block Distance),公式以下:Distance = |x2-x1|+|y2-y1|get

3.      象棋格距離(Chessboard Distance),公式以下:Distance = max(|x2-x1|,|y2-y1|)

一旦距離度量公式選擇,就能夠在二值圖像的距離變換中使用。一個最多見的距離變換

算法就是經過連續的腐蝕操做來實現,腐蝕操做的中止條件是全部前景像素都被徹底

腐蝕。這樣根據腐蝕的前後順序,咱們就獲得各個前景像素點到前景中心骨架像素點的

距離。根據各個像素點的距離值,設置爲不一樣的灰度值。這樣就完成了二值圖像的距離

變換。

注意點:

腐蝕操做結構體的選取會影響距離變換的效果,例子使用3*3的矩陣完成。有不少快速

的距離變換算法,感興趣的能夠本身研究。

運行結果:


關鍵代碼解析:

初始化二值圖像,讀取像素,獲取前景邊緣像素與背景邊緣像素

	public DistanceTransform(float scaleValue, float offsetValue, BufferedImage src) 	{ 		this.scaleValue = scaleValue; 		this.offsetValue = offsetValue; 		this.inputImage = src; 		this.width = src.getWidth(); 		this.height = src.getHeight();         int[] inPixels = new int[width*height];         getRGB( src, 0, 0, width, height, inPixels );         int index = 0;         pixels2D = new int[height][width]; // row, column         greyLevel = new int[height][width];         for(int row=0; row < height; row++)         {         	for(int col=0; col<width; col++)          	{         		index = row * width + col;         		int grayValue = (inPixels[index] >> 16) & 0xff;         		pixels2D[row][col] = grayValue;         		greyLevel[row][col] = 0;         	}         }                  generateForegroundEdge();         generateBackgroundEdgeFromForegroundEdge();          	}
現實距離變換的代碼以下:

@Override public BufferedImage filter(BufferedImage src, BufferedImage dest) { 	 	// calculate the distance here!! 	int index = 1;     while (foregroundEdgePixels.size() > 0) {     	distanceSingleIteration(index);         ++index;     }          // loop the each pixel and assign the color value according to distance value 	for (int row = 0; row < inputImage.getHeight(); row++) { 	      for (int col = 0; col < inputImage.getWidth(); col++) { 	    	  if(greyLevel[row][col] > 0) { 		    	  int colorValue = (int)Math.round(greyLevel[row][col] * scaleValue + offsetValue); 		    	  colorValue = colorValue > 255 ? 255 : ((colorValue < 0) ? 0 : colorValue); 		    	  this.pixels2D[row][col] = colorValue; 	    	  } 	    	   	      } 	} 	 	// build the result pixel data at here !!!     if ( dest == null )         dest = createCompatibleDestImage(inputImage, null );          index = 0;     int[] outPixels = new int[width*height];     for(int row=0; row<height; row++) {     	int ta = 0, tr = 0, tg = 0, tb = 0;     	for(int col=0; col<width; col++) {     		if(row == 75 && col > 60) {     			System.out.println("ddddd");     		}     		index = row * width + col;     		tr = tg = tb = this.pixels2D[row][col];     		ta = 255;     		outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;     	}     }     setRGB( dest, 0, 0, width, height, outPixels ); 	return dest; }
生成前景邊緣像素與背景邊緣像素的代碼以下:

  private void generateForegroundEdge()   {     foregroundEdgePixels.clear();      for (int row = 0; row < height; row++)       for (int col = 0; col < width; col++)         if (this.pixels2D[row][col] == foreground) {           Point localPoint = new Point(col, row);           for (int k = -1; k < 2; ++k) // 3*3 matrix         	  for (int l = -1; l < 2; ++l) {               if ((localPoint.x + l < 0) || (localPoint.x + l >= this.width) || (localPoint.y + k < 0) || (localPoint.y + k >= this.height) ||                  (this.pixels2D[(localPoint.y + k)][(localPoint.x + l)] != background) || (this.foregroundEdgePixels.contains(localPoint)))                 continue;               this.foregroundEdgePixels.add(localPoint);             }         }   }      private void generateBackgroundEdgeFromForegroundEdge()   {     this.backgroundEdgePixels.clear();      Iterator<Point> localIterator = this.foregroundEdgePixels.iterator();     while (localIterator.hasNext()) {       Point localPoint1 = new Point((Point)localIterator.next());       for (int i = -1; i < 2; ++i)         for (int j = -1; j < 2; ++j)           if ((localPoint1.x + j >= 0) && (localPoint1.x + j < this.width) && (localPoint1.y + i >= 0) && (localPoint1.y + i < this.height)) {             Point localPoint2 = new Point(localPoint1.x + j, localPoint1.y + i);             if (this.pixels2D[localPoint2.y][localPoint2.x] == background)               this.backgroundEdgePixels.add(localPoint2);           }     }   }
相關文章
相關標籤/搜索