簡介
定位某個圖片的矩形區域是非常有用的,這個可以通過手動的選擇某個區域來實現定位,圖片相關的軟件都提供了這個功能;也可以像本篇一個通過程序來實現智能定位。前者會有誤差,效率低下;后者選區精度高,效率高。
應用場景
1.精靈編輯器或者css sprites輔助工具(當我們需要逆着TexturePacker行事的時候),如下圖所示:
2.手寫識別輸入
因為我們不能保證用戶輸入的區域,所以必須定位到用戶輸入的區域,再去識別用戶的輸入的內容。
3.魔法畫板程序
比如馬良神筆,要對用戶繪制的火柴人進行一些上下左右移動、扭曲等效果:
矩形區域識別
廢話一萬句,不如一張圖。看下面這張圖:
這就是識別的關鍵。任意取圖像上的一點,然后通過這點開始擴張。一般情況下,該點取的是軟件使用者鼠標點擊的那一點。如圖是移動中的四個點:
可以看到,移動后的四個點可以確定一個矩形區域。哪條邊下的所有像素為透明(即0,0,0,0),則該點不移動,等待其他點移動完成。當所有邊下面的像素都為透明,則得到了我們想要的區域。我們根據移動的距離可以很方便的找到四個頂點:
所以一個遞歸就可以幫我們實現(js Canvas版):
var increasePixel = 1, leftIncreasePixel = 2, rightIncreasePixel = 2, upIncreasePixel = 2, downIncreasePixel = 2;
function searchTransparentRectByTargetPoint(p) {
var p1 = { x: p.x - leftIncreasePixel, y: p.y - upIncreasePixel };
var p2 = { x: p.x + rightIncreasePixel, y: p.y - upIncreasePixel };
var p3 = { x: p.x + rightIncreasePixel, y: p.y + downIncreasePixel };
var p4 = { x: p.x - leftIncreasePixel, y: p.y + downIncreasePixel };
var breakTag = true;
if (!isXLineTransparent(p1, p2)) {
upIncreasePixel += increasePixel;
breakTag = false;
}
if (!isYLineTransparent(p2, p3)) {
breakTag = false;
rightIncreasePixel += increasePixel;
}
if (!isXLineTransparent(p4, p3)) {
breakTag = false;
downIncreasePixel += increasePixel;
}
if (!isYLineTransparent(p1, p4)) {
breakTag = false;
leftIncreasePixel += increasePixel;
}
if (breakTag) {
return [p1.x, p1.y, p3.x - p1.x, p3.y - p1.y];
} else {
return searchTransparentRectByCenterPoint(p);
}
}
其中isXLineTransparent和isYLineTransparent是獲取該線段下面是否全透明。
function isXLineTransparent(p1, p2) {
var _y = p2.y;
for (var i = p1.x; i < p2.x + 1; i++) {
var startIndex = this.getImageDataStartIndexByPosition({ x: i, y: _y });
var totalPixel = this.imageData.data[startIndex] + this.imageData.data[startIndex + 1] + this.imageData.data[startIndex + 2] + this.imageData.data[startIndex + 3];
if (totalPixel !== 0) {
return false;
}
}
return true;
}
function isYLineTransparent(p1, p2) {
var _x = p2.x;
for (var i = p1.y; i < p2.y + 1; i++) {
var startIndex = this.getImageDataStartIndexByPosition({ x: _x, y: i });
var totalPixel = this.imageData.data[startIndex] + this.imageData.data[startIndex + 1] + this.imageData.data[startIndex + 2] + this.imageData.data[startIndex + 3];
if (totalPixel !== 0) {
return false;
}
}
return true;
}
多矩形區域識別策略
多矩形區域識別是沒有擴張點,需要從用戶輸入中隨機產生一個目標點,然后使用兩層遞歸(上面的代碼之外再嵌套一層)實現所有矩形區域的遍歷。
思路有了,是不是有想法把上面的手寫輸入改成支持多個文字?這個對於聰明的你,明顯不是問題。