碼農干貨系列【4】--圖像識別之矩形區域搜索


簡介

定位某個圖片的矩形區域是非常有用的,這個可以通過手動的選擇某個區域來實現定位,圖片相關的軟件都提供了這個功能;也可以像本篇一個通過程序來實現智能定位。前者會有誤差,效率低下;后者選區精度高,效率高。

應用場景

1.精靈編輯器或者css sprites輔助工具(當我們需要逆着TexturePacker行事的時候),如下圖所示:

image

2.手寫識別輸入

image image

因為我們不能保證用戶輸入的區域,所以必須定位到用戶輸入的區域,再去識別用戶的輸入的內容。

3.魔法畫板程序

比如馬良神筆,要對用戶繪制的火柴人進行一些上下左右移動、扭曲等效果:

image

矩形區域識別

廢話一萬句,不如一張圖。看下面這張圖:

image

這就是識別的關鍵。任意取圖像上的一點,然后通過這點開始擴張。一般情況下,該點取的是軟件使用者鼠標點擊的那一點。如圖是移動中的四個點:

image

可以看到,移動后的四個點可以確定一個矩形區域。哪條邊下的所有像素為透明(即0,0,0,0),則該點不移動,等待其他點移動完成。當所有邊下面的像素都為透明,則得到了我們想要的區域。我們根據移動的距離可以很方便的找到四個頂點:

image

所以一個遞歸就可以幫我們實現(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;
}

多矩形區域識別策略

多矩形區域識別是沒有擴張點,需要從用戶輸入中隨機產生一個目標點,然后使用兩層遞歸(上面的代碼之外再嵌套一層)實現所有矩形區域的遍歷。

image

思路有了,是不是有想法把上面的手寫輸入改成支持多個文字?這個對於聰明的你,明顯不是問題。

在線演示

傳送門:http://www.spritecow.com/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM