利用marching square algorithm獲取圖形輪廓
影象輪廓獲取方法,英文名叫 contour tracing ,或者叫 border following,常見的方法有:
Square Tracing Algorithm ,Moore-Neighbor Tracing ,Radial Sweep , Theo Pavlidis' Algorithm 。
參考:http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/alg.html
下面主要講講marching square algorithm,marching square algorithm的設計思路是:先找一起始點,該點與它的上,左,左上四點組成一個“square”,該square可能有16種狀態,演算法設計了每種狀態下,這個square下一步的移動方向,當順著輪廓走一圈回到起始點時,演算法結束。參考狀態圖:
Square Tracing Algorithm ,Moore-Neighbor Tracing ,Radial Sweep , Theo Pavlidis' Algorithm 。
參考:http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/alg.html
下面主要講講marching square algorithm,marching square algorithm的設計思路是:先找一起始點,該點與它的上,左,左上四點組成一個“square”,該square可能有16種狀態,演算法設計了每種狀態下,這個square下一步的移動方向,當順著輪廓走一圈回到起始點時,演算法結束。參考狀態圖:
Emanuele Feronato給出了一種程式碼實現:
package {
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Matrix;
import flash.geom.Point;
public class Main extends Sprite {
private var bitmapData:BitmapData=new BitmapData(640,480,true,0x00000000);
// tolerance is the amount of alpha for a pixel to be considered solid
private var tolerance:Number=0x01;
public function Main() {
// adding a png image with transparency
bitmapData.draw(new Logo(278,429),new Matrix(1,0,0,1,100,40));
var bitmap:Bitmap=new Bitmap(bitmapData);
addChild(bitmap);
// at the end of this function, marchingVector will contain the points tracing the contour
var marchingVector:Vector.<Point>=marchingSquares(bitmapData);
}
public function marchingSquares(bitmapData:BitmapData):Vector.<Point> {
var contourVector:Vector.<Point> = new Vector.<Point>();
// this is the canvas we'll use to draw the contour
var canvas:Sprite=new Sprite();
addChild(canvas);
canvas.graphics.lineStyle(2,0x00ff00);
// getting the starting pixel
var startPoint:Point=getStartingPixel(bitmapData);
// if we found a starting pixel we can begin
if (startPoint!=null) {
// moving the graphic pen to the starting pixel
canvas.graphics.moveTo(startPoint.x,startPoint.y);
// pX and pY are the coordinates of the starting point
var pX:Number=startPoint.x;
var pY:Number=startPoint.y;
// stepX and stepY can be -1, 0 or 1 and represent the step in pixels to reach
// next contour point
var stepX:Number;
var stepY:Number;
// we also need to save the previous step, that's why we use prevX and prevY
var prevX:Number;
var prevY:Number;
// closedLoop will be true once we traced the full contour
var closedLoop:Boolean=false;
while (!closedLoop) {
// the core of the script is getting the 2x2 square value of each pixel
var squareValue:Number=getSquareValue(pX,pY);
switch (squareValue) {
/* going UP with these cases:
+---+---+ +---+---+ +---+---+
| 1 | | | 1 | | | 1 | |
+---+---+ +---+---+ +---+---+
| | | | 4 | | | 4 | 8 |
+---+---+ +---+---+ +---+---+
*/
case 1 :
case 5 :
case 13 :
stepX=0;
stepY=-1;
break;
/* going DOWN with these cases:
+---+---+ +---+---+ +---+---+
| | | | | 2 | | 1 | 2 |
+---+---+ +---+---+ +---+---+
| | 8 | | | 8 | | | 8 |
+---+---+ +---+---+ +---+---+
*/
case 8 :
case 10 :
case 11 :
stepX=0;
stepY=1;
break;
/* going LEFT with these cases:
+---+---+ +---+---+ +---+---+
| | | | | | | | 2 |
+---+---+ +---+---+ +---+---+
| 4 | | | 4 | 8 | | 4 | 8 |
+---+---+ +---+---+ +---+---+
*/
case 4 :
case 12 :
case 14 :
stepX=-1;
stepY=0;
break;
/* going RIGHT with these cases:
+---+---+ +---+---+ +---+---+
| | 2 | | 1 | 2 | | 1 | 2 |
+---+---+ +---+---+ +---+---+
| | | | | | | 4 | |
+---+---+ +---+---+ +---+---+
*/
case 2 :
case 3 :
case 7 :
stepX=1;
stepY=0;
break;
case 6 :
/* special saddle point case 1:
+---+---+
| | 2 |
+---+---+
| 4 | |
+---+---+
going LEFT if coming from UP
else going RIGHT
*/
if (prevX==0&&prevY==-1) {
stepX=-1;
stepY=0;
}
else {
stepX=1;
stepY=0;
}
break;
case 9 :
/* special saddle point case 2:
+---+---+
| 1 | |
+---+---+
| | 8 |
+---+---+
going UP if coming from RIGHT
else going DOWN
*/
if (prevX==1&&prevY==0) {
stepX=0;
stepY=-1;
}
else {
stepX=0;
stepY=1;
}
break;
}
// moving onto next point
pX+=stepX;
pY+=stepY;
// saving contour point
contourVector.push(new Point(pX, pY));
prevX=stepX;
prevY=stepY;
// drawing the line
canvas.graphics.lineTo(pX,pY);
// if we returned to the first point visited, the loop has finished
if (pX==startPoint.x&&pY==startPoint.y) {
closedLoop=true;
}
}
}
return contourVector;
}
private function getStartingPixel(bitmapData:BitmapData):Point {
// finding the starting pixel is a matter of brute force, we need to scan
// the image pixel by pixel until we find a non-transparent pixel
var zeroPoint:Point=new Point(0,0);
var offsetPoint:Point=new Point(0,0);
for (var i:Number=0; i<bitmapData.height; i++) {
for (var j:Number=0; j<bitmapData.width; j++) {
offsetPoint.x=j;
offsetPoint.y=i;
if (bitmapData.hitTest(zeroPoint,tolerance,offsetPoint)) {
return offsetPoint;
}
}
}
return null;
}
private function getSquareValue(pX:Number,pY:Number):Number {
/*
checking the 2x2 pixel grid, assigning these values to each pixel, if not transparent
+---+---+
| 1 | 2 |
+---+---+
| 4 | 8 | <- current pixel (pX,pY)
+---+---+
*/
var squareValue:Number=0;
// checking upper left pixel
if (getAlphaValue(bitmapData.getPixel32(pX-1,pY-1))>=tolerance) {
squareValue+=1;
}
// checking upper pixel
if (getAlphaValue(bitmapData.getPixel32(pX,pY-1))>tolerance) {
squareValue+=2;
}
// checking left pixel
if (getAlphaValue(bitmapData.getPixel32(pX-1,pY))>tolerance) {
squareValue+=4;
}
// checking the pixel itself
if (getAlphaValue(bitmapData.getPixel32(pX,pY))>tolerance) {
squareValue+=8;
}
return squareValue;
}
private function getAlphaValue(n:Number):Number {
// given an ARGB color value, returns the alpha 0 -> 255
return n >> 24 & 0xFF;
}
}
}
我利用這個得到的結果為:
相關文章
- python如何獲取最優輪廓係數Python
- OpenCV計算機視覺學習(8)——影像輪廓處理(輪廓繪製,輪廓檢索,輪廓填充,輪廓近似)OpenCV計算機視覺
- OpenCV 形狀分析(上):計算輪廓中心OpenCV
- zabbix api 獲取圖形API
- opencv——輪廓發現與輪廓(二值影像)分析OpenCV
- 怎樣用好CorelDRAW中輪廓圖工具
- OpenCV 查詢輪廓OpenCV
- 影像輪廓處理
- 地圖小區景點邊界輪廓實現地圖
- 如何利用框選工具獲取多邊形範圍?
- CSS outline輪廓CSS
- CorelDRAW輪廓描摹點陣圖結合案例詳解
- answerOpenCV輪廓類問題解析OpenCV
- 利用API獲取金融資料並畫圖API
- 二值影象分析之輪廓分析
- AsyncDisplayKit原始碼分析(一)輪廓梳理原始碼
- 【OpenCV教程】輪廓檢測過程OpenCV
- 字的研究(3)fontTools-TrueType輪廓座標的獲取以及基於TrueType的Glyph例項的構建
- 利用javascript獲取圖片的top N主色值JavaScript
- WPS演示教程:妙用自定義動畫輕鬆繪製城市輪廓圖動畫
- React 用axios 獲取遍歷json 引入swiper輪播圖ReactiOSJSON
- Python 影像處理 OpenCV (15):影像輪廓PythonOpenCV
- CSS 不規則的輪廓-outlineCSS
- 邊框(Border) 和 輪廓(Outline) 屬性
- opencv使用convexityDefects計算輪廓凸缺陷OpenCV
- opencv查詢輪廓---cvFindContours && cvDrawCountours 用法及例子OpenCV
- 分割結果視覺化,把標籤mask輪廓顯示在原圖上視覺化
- 利用js獲取IP,所在城市JS
- 獲取app 圖片APP
- 刪除按鈕點選後的虛線輪廓
- OpenCv查詢輪廓-cv2.findContours()函式OpenCV函式
- OpenCV7影像金字塔與輪廓檢測OpenCV
- 利用CSS中input製作開關、輪播圖CSS
- 獲取javascript函式形參的數目JavaScript函式
- 利用 Matplotlib 繪製資料圖形(一)
- 利用 Matplotlib 繪製資料圖形(二)
- 利用噪聲構建美妙的 CSS 圖形CSS
- 【輪子】可能是比較好用獲取 AppStore 資訊的輪子APP