add test case
This commit is contained in:
parent
2afcdd59b1
commit
b4cc9180de
6
demo/data/image-contours5.js
Normal file
6
demo/data/image-contours5.js
Normal file
File diff suppressed because one or more lines are too long
6
demo/data/image-contours6.js
Normal file
6
demo/data/image-contours6.js
Normal file
File diff suppressed because one or more lines are too long
6
demo/data/image-contours7.js
Normal file
6
demo/data/image-contours7.js
Normal file
File diff suppressed because one or more lines are too long
@ -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++) {
|
||||
|
@ -128,7 +128,7 @@ define(
|
||||
curImage = img;
|
||||
refresh();
|
||||
};
|
||||
img.src = '../test/qg.gif';
|
||||
img.src = '../test/qg.jpg';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
});
|
||||
|
153
src/graphics/image/contour/findBreakPoints1111.js
Normal file
153
src/graphics/image/contour/findBreakPoints1111.js
Normal 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;
|
||||
}
|
||||
);
|
148
src/graphics/image/contour/findCornerPoints.js
Normal file
148
src/graphics/image/contour/findCornerPoints.js
Normal 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;
|
||||
}
|
||||
);
|
149
src/graphics/image/contour/findStraightLinePoints.js
Normal file
149
src/graphics/image/contour/findStraightLinePoints.js
Normal 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;
|
||||
}
|
||||
);
|
@ -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
|
||||
|
54
src/graphics/image/contour/isSegmentLine.js
Normal file
54
src/graphics/image/contour/isSegmentLine.js
Normal 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;
|
||||
}
|
||||
);
|
49
src/graphics/image/contour/markVisited.js
Normal file
49
src/graphics/image/contour/markVisited.js
Normal 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
BIN
test/circle.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
test/cur.jpg
Normal file
BIN
test/cur.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Loading…
x
Reference in New Issue
Block a user