add test case

This commit is contained in:
kekee000 2015-04-04 21:53:50 +08:00
parent 2afcdd59b1
commit b4cc9180de
14 changed files with 581 additions and 46 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,11 +5,11 @@
define(
function (require) {
var fitBezier = require('graphics/image/contour/fitBezier');
//var fitBezier = require('graphics/image/contour/fitBezier');
var findBreakPoints = require('graphics/image/contour/findBreakPoints');
var pathUtil = require('graphics/pathUtil');
var data = require('demo/../data/image-contours3');
var drawPath = require('render/util/drawPath');
var data = require('demo/../data/image-contours5');
//var drawPath = require('render/util/drawPath');
var entry = {
@ -24,7 +24,6 @@ define(
c.splice(c.length - 1, 1);
});
data.forEach(function (contour) {
contour.forEach(function(p) {
html += '<i style="left:'+p.x+'px;top:'+p.y+'px;"></i>';
@ -34,19 +33,16 @@ define(
$('#points').html(html);
data.forEach(function (contour) {
contour = pathUtil.scale(contour, 10);
pathUtil.scale(contour, 10);
var points = findBreakPoints(contour, 10);
if (points) {
points.forEach(function (p) {
breakPoints.push(p);
});
}
contour = pathUtil.scale(contour, 0.1);
pathUtil.scale(contour, 0.1);
});
breakPoints.forEach(function (p) {
console.log(p.right);
});
html = '';
for (var i = 0, l = breakPoints.length; i < l; i++) {

View File

@ -128,7 +128,7 @@ define(
curImage = img;
refresh();
};
img.src = '../test/qg.gif';
img.src = '../test/qg.jpg';
}
};

View File

@ -19,6 +19,9 @@ define(
var makeLink = require('graphics/pathUtil').makeLink;
var vector = require('graphics/vector');
var markVisited = require('./markVisited');
var getCos = vector.getCos;
var getDist = vector.getDist;
@ -118,23 +121,6 @@ define(
return 0;
}
/**
* 标记点的左右已经被访问过了
*
* @param {Object} p
* @param {number} r 半径
*/
function markVisited(p, r) {
var j = 0;
var left = p;
var right = p;
p.visited = true;
while (j++ < r) {
left = left.prev;
right = right.next;
left.visited = right.visited = true;
}
}
/**
* 查找和标记直线点
@ -170,21 +156,6 @@ define(
return breakPoints;
}
/**
* 查找和标记切线点
*
* @param {Array} contour 轮廓
* @param {Array} breakPoints 关键点
* @param {number} r 查找范围
* @return {Array} 关键点
*/
function findTangencyPoints(contour, breakPoints, r) {
return breakPoints;
}
/**
* 查找和标记拐点
*
@ -287,9 +258,6 @@ define(
// 查找直线点
breakPoints = findLinePoints(contour, breakPoints, r, scale);
breakPoints = findTangencyPoints(contour, breakPoints, r, scale);
breakPoints.sort(function (a, b) {
return a.index - b.index;
});

View File

@ -0,0 +1,153 @@
/**
* @file 查找轮廓中的关键点
* @author mengke01(kekee000@gmail.com)
*
* 查找方法为此处文章的方法
* http://wenku.baidu.com/link?url=Sz1BbYjfA7IeHAMVJ1TPlXiMhACc6sWhHliPJqAUxxtC5K9PYf4j3ile6patUEUMOE_9uJdsS1EGJBFLVbhXcn7Qe8l_FxuT3QVI8nm1aZG
*
* 关键点标记定义
*
* p.left 左侧类型
* p.right: 右侧类型
* 直线为1
* 曲线为2
*/
define(
function (require) {
var makeLink = require('graphics/pathUtil').makeLink;
var vector = require('graphics/vector');
var markVisited = require('./markVisited');
var findStraightLinePoints = require('./findStraightLinePoints');
var findCornerPoints = require('./findCornerPoints');
/**
* 查找和标记直线点
*
* @param {Array} contour 轮廓
* @param {Array} breakPoints 关键点
* @param {number} r 查找范围
* @return {Array} 关键点
*/
function findLinePoints(contour, breakPoints, r, scale) {
// 根据角点判断是否直线点
var contourSize = contour.length;
for (var i = 0, l = breakPoints.length; i < l; i++) {
var isLast = i === l - 1;
var start = breakPoints[i];
var end = isLast ? breakPoints[0] : breakPoints[i + 1];
var j = 1;
var cur = start.next;
var lineFlag = true;
var maxDist = 0;
while (cur !== end) {
if (0 === j++ % r) {
var dist = getDist(start, end, cur) / scale;
if (dist > 2) {
lineFlag = false;
break;
}
else if (dist > maxDist) {
maxDist = dist;
}
}
cur = cur.next;
}
if (j > r && lineFlag) {
if (maxDist <= 1 || j > 40) {
start.right = 1;
}
}
}
return breakPoints;
}
/*
*
* @param {Array} contour 轮廓点集合
* @return {Array} 轮廓点集合
*/
function getBreakPoints(contour, scale) {
scale = scale || 1;
var contourSize = contour.length;
// 如果小于指定的点数,返回中间点
if (contourSize < 36) {
return [
contour[0],
contour[Math.floor(contourSize / 2)]
]
}
contour = makeLink(contour);
var p;
var next;
var range;
var isLast;
var linePoints = findStraightLinePoints(contour, scale);
var breakPoints = [];
if (linePoints.length >= 2) {
for (var i = 0, l = linePoints.length; i < l; i++) {
p = linePoints[i];
if (p.right) {
continue;
}
isLast = i === l - 1;
next = linePoints[isLast ? 0 : i + 1];
range = isLast ? contourSize - p.index + next.index : next.index - p.index;
if (range > 50) {
var points = findCornerPoints(contour, p.next, next.prev, scale);
breakPoints = breakPoints.concat(points);
}
}
}
else {
breakPoints = findCornerPoints(contour, contour[0], contour[contourSize - 1], scale);
}
breakPoints = breakPoints.concat(linePoints);
// 没有找到拐点说明拐点不明显或者为连续曲线这里采用4等分
if (breakPoints.length < 2) {
if (contourSize < 100) {
var step = Math.floor(contourSize / 2) + 1;
}
else {
var step = Math.floor(contourSize / 4) + 1;
}
var startIndex = breakPoints[0] ? breakPoints[0].index : 0;
for (var i = step; i < contourSize; i += step) {
breakPoints.push(contour[(startIndex + i) % contourSize]);
}
}
return breakPoints.sort(function (a, b) {
return a.index - b.index;
});
}
return getBreakPoints;
}
);

View File

@ -0,0 +1,148 @@
/**
* @file 查找角点
* @author mengke01(kekee000@gmail.com)
*/
define(
function (require) {
var vector = require('graphics/vector');
var markVisited = require('./markVisited');
var SEARCH_RANGE = 14; // 查找的范围
var THETA_CORNER = 0.4; // 拐点抑制
var THETA_DIST_TANGENCY = 1; // 相切抑制
var THETA_DIST = 5; // 距离抑制
var getCos = vector.getCos;
var getDist = vector.getDist;
/**
* 计算theta夹角
*
* @param {Object} p 当前点
* @param {Object} left 左侧点
* @param {Object} right 右侧点
* @return {number} theta角
*/
function computeTheta(p, left, right) {
var leftX = p.x - left.x;
var leftY = p.y - left.y;
var rightX = right.x - p.x;
var rightY = right.y - p.y;
var cos = getCos(leftX, leftY, rightX, rightY);
var theta = Math.acos(cos > 1 ? 1 : cos);
// 计算theta的顺时针或逆时针
return theta;
}
/**
* 查找和标记真正的角点
*
* @param {Array} contour 轮廓
* @param {Array} breakPoints 关键点
* @param {number} r 查找范围
* @return {Array} 关键点
*/
function findCorner(contour, breakPoints, r) {
var j;
var left;
var right;
var max;
var min;
contour.forEach(function (p) {
if (!p.visited && (p.markBreak || p.markInflexion)) {
j = 0;
left = p;
right = p;
max = p.absTheta;
while (j++ < r) {
left = left.prev;
right = right.next;
if (left.absTheta > max) {
max = left.absTheta;
}
if (right.absTheta > max) {
max = right.absTheta;
}
}
if (max === p.absTheta) {
if (p.markBreak) {
p.breakPoint = true;
}
else if (p.markInflexion) {
p.inflexion = true;
}
breakPoints.push(p);
markVisited(p, r);
}
}
});
return breakPoints;
}
/**
* 查找角点
* @param {Array} contour 轮廓点集
* @param {number} startIndex 开始点
* @param {number} endIndex 结束点
* @return {Array} 角点集合
*/
function findCornerPoints(contour, start, end, scale) {
var r = SEARCH_RANGE;
var breakPoints = [];
var p = start;
var left = p;
var right = p;
var j = 0;
while (j++ < r) {
left = left.prev;
right = right.next;
}
while (p !== end) {
if (!p.visited) {
p.theta = computeTheta(p, left, right);
p.absTheta = Math.abs(p.theta);
p.dist = getDist(p, left, right) / scale;
if (p.absTheta > THETA_CORNER && !p.visited) {
p.markBreak = true;
}
else if (p.dist > THETA_DIST && !p.visited) {
p.markInflexion = true;
}
}
left = left.next;
right = right.next;
p = p.next;
}
// 计算相切点
findCorner(contour, breakPoints, r);
return breakPoints;
}
return findCornerPoints;
}
);

View File

@ -0,0 +1,149 @@
/**
* @file 查找直线点
* @author mengke01(kekee000@gmail.com)
*/
define(
function (require) {
var markVisited = require('./markVisited');
var STRAIGHT_LINE_POINTS = 20; // 直线点过滤计数
/**
/**
* 查找和标记直线点
*
* @param {Array} contour 轮廓
* @param {Array} breakPoints 关键点
* @param {number} r 查找范围
* @return {Array} 关键点
*/
function findStraightLinePoints(contour, scale) {
var linePoints = [];
var contourSize = contour.length;
// 查找首个节点的水平延伸
var start = contour[0];
var cur = start;
while (cur.x === cur.prev.x) {
cur = cur.prev;
}
start = cur;
// 查找直线
var p;
var count;
cur = start.next;
while(cur !== start) {
// 查找竖直直线点
if (cur.x === cur.next.x) {
count = 1;
p = cur;
cur = cur.next;
while (cur !== start && cur.x === cur.next.x) {
cur = cur.next;
count++;
}
if (count > STRAIGHT_LINE_POINTS) {
p.start = 1;
p.vertical = 1;
cur.vertical = 1;
linePoints.push(p);
linePoints.push(cur);
markVisited(p, 15, count);
}
}
// 查找水平直线点
else if (cur.y === cur.next.y) {
count = 1;
p = cur;
cur = cur.next;
while (cur !== start && cur.y === cur.next.y) {
cur = cur.next;
count++;
}
if (count > STRAIGHT_LINE_POINTS) {
p.start = 1;
p.hoz = 1;
cur.hoz = 1;
linePoints.push(p);
linePoints.push(cur);
markVisited(p, 15, count);
}
}
else {
cur = cur.next;
}
}
var next;
var newLinePoints = [];
var i;
var l;
for (i = 0, l = linePoints.length; i < l; i++) {
p = linePoints[i];
next = linePoints[i === l - 1 ? 0 : i + 1];
if (p.x === next.x && p.y === next.y) {
continue;
}
else if (Math.abs(p.x - next.x) / scale <= 2 && Math.abs(p.y - next.y) / scale <= 2) {
// 如果连续但是接近直线,则去除这两个点
if (p.vertical && next.vertical || p.hoz && next.hoz) {
i++;
continue;
}
// 否则修正直线夹角
else {
// p是最后一个点则修正第一个点
if (i === l - 1) {
next.x = p.vertical ? p.x : next.x;
next.y = p.hoz ? p.y : next.y;
}
else {
p.right = 1;
p.x = p.vertical ? p.x : next.x;
p.y = p.hoz ? p.y : next.y;
newLinePoints.push(p);
}
i++;
}
}
else {
newLinePoints.push(p);
}
}
for (i = 0, l = newLinePoints.length; i < l; i++) {
p = newLinePoints[i];
next = newLinePoints[i === l - 1 ? 0 : i + 1];
p.breakPoints = 1;
if (p.start && (p.hoz && p.y === next.y || p.vertical && p.x === next.x)) {
p.right = 1;
}
}
newLinePoints.sort(function (a, b) {
return a.index - b.index;
});
return newLinePoints;
}
return findStraightLinePoints;
}
);

View File

@ -90,7 +90,7 @@ define(
continue;
}
if (start.tangency && tHat1Point) {
if (start.inflexion && tHat1Point) {
tHat1 = vector.normalize({
x: start.x - tHat1Point.x,
y: start.y - tHat1Point.y

View File

@ -0,0 +1,54 @@
/**
* @file 判断线段是否直线点
* @author mengke01(kekee000@gmail.com)
*/
define(
function (require) {
var getDist = require('graphics/vector').getDist;
function isSegmentLine(contour, start, end, isLast) {
var contourSize = contour.length;
var mid;
var thetaDistance = 1; // 判断直线点距离
// 随机选取 几个点进行直线判断
var startIndex = start.index;
var endIndex = end.index;
if (isLast) {
startIndex = start.index;
endIndex = contourSize + end.index;
}
mid = contour[Math.floor(startIndex / 2 + endIndex / 2) % contourSize];
if (getDist(start, end, mid) > thetaDistance) {
return false;
}
// 距离比较长的话可以适当放大
if (endIndex - startIndex > 40) {
thetaDistance = 2;
}
var step = Math.floor(Math.max((endIndex - startIndex) / 10, 4));
var lineFlag = true;
for (var j = startIndex + step; j < endIndex; j += step) {
var dist = getDist(start, end, contour[j % contourSize]);
if (dist > thetaDistance) {
lineFlag = false;
break;
}
}
return lineFlag;
}
return isSegmentLine;
}
);

View File

@ -0,0 +1,49 @@
/**
* @file 标记点集访问过
* @author mengke01(kekee000@gmail.com)
*/
define(
function (require) {
/**
* 标记点的左右已经被访问过了
*
* @param {Object} p
* @param {number} rl 左半径
* @param {number} rr 右半径
*/
function markVisited(p, rl, rr) {
var j;
var left = p;
var right = p;
p.visited = true;
if (undefined === rr || rr === rl) {
j = 0;
while (j++ < rl) {
left = left.prev;
right = right.next;
left.visited = right.visited = true;
}
}
else {
j = 0;
while (j++ < rl) {
left = left.prev;
left.visited = true;
}
j = 0;
while (j++ < rr) {
right = right.next;
right.visited = true;
}
}
}
return markVisited;
}
);

BIN
test/circle.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
test/cur.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB