New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

contours.ts

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

contours.ts - npm Package Compare versions

Comparing version 0.1.4 to 0.1.5

dist/utilities.d.ts

12

dist/contours.d.ts
import { ImageDataLike } from './types/ImageDataLike';
import { Point } from './types/Point';
import { Circle, Rectangle } from './types/ShapeType';
import { Point, Polygon, ShapeCollection } from './types/ShapeType';
interface ContourFinderOptions {
blur: boolean;
threshold: number;
blur?: boolean;
threshold?: number;
}

@@ -12,3 +11,2 @@ /**

export declare class ContourFinder {
private static readonly THRESHOLD;
private data;

@@ -18,3 +16,3 @@ private readonly width;

private readonly channels;
readonly contours: Point[][];
readonly contours: Polygon[];
private isSimplified;

@@ -72,4 +70,4 @@ /**

*/
approximate(): Array<Rectangle | Circle | Point[]>;
approximate(): ShapeCollection;
}
export {};

@@ -23,6 +23,9 @@ 'use strict';

var THRESHOLD = 6.25; // distance between two points
function distance(p1, p2) {
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
} // perpendicular distance of a point from a line
function perpendicularDistance(point, start, end) {

@@ -34,3 +37,93 @@ if (start.x === end.x && start.y === end.y) {

return Math.abs((start.y - end.y) * point.x + (end.x - start.x) * point.y + start.x * end.y - end.x * start.y) / distance(start, end);
} // gets angle of a line
function getLineAngle(p0, p1) {
return Math.atan2(p1.y - p0.y, p1.x - p0.x);
} // gets length of a line
function getLineLength(p0, p1) {
return Math.sqrt(Math.pow(p1.y - p0.y, 2) + Math.pow(p1.x - p0.x, 2));
} // angle between two lines
function getLinesAngle(line1, line2) {
var p0 = line1[0],
p1 = line1[1];
var p2 = line2[0],
p3 = line2[1];
var theta1 = getLineAngle(p0, p1);
var theta2 = getLineAngle(p2, p3); // differenc of angle of two lines is angle between those lines
return Math.abs(theta1 - theta2) * (180 / Math.PI);
} // returns diffrnce in length between two lines
function getLinesDifference(line1, line2) {
var p0 = line1[0],
p1 = line1[1];
var p2 = line2[0],
p3 = line2[1];
var length1 = getLineLength(p0, p1);
var length2 = getLineLength(p2, p3);
return Math.abs(length1 - length2);
} // checks if two opposite vertex have right:90 angle
function isRectangle(contour) {
var p0 = contour[0],
p1 = contour[1],
p2 = contour[2],
p3 = contour[3];
var angle1 = getLinesAngle([p0, p1], [p1, p2]);
var angle2 = getLinesAngle([p0, p3], [p3, p2]);
var diff = Math.abs(angle2 - angle1);
return diff <= THRESHOLD;
} // check if two adjacent sides are same of same length
function isSquare(contour) {
var p0 = contour[0],
p1 = contour[1],
p2 = contour[2];
var edgeLength = getLineLength(p0, p1);
var diff = getLinesDifference([p0, p1], [p1, p2]);
return diff <= edgeLength * (THRESHOLD / 100);
} // check if polygon is a circle
function isCircle(contour) {
// polygon has too few points
if (contour.length < 16) return false; // find a circle equation from 3 distinct points
var total = contour.length;
var circle = circleFromThreePoints(contour[Math.floor(total * 0.25)], contour[Math.floor(total * 0.5)], contour[Math.floor(total * 0.75)]); // determine if all points in polygon fulfull this circle equation
for (var i = 0; i < contour.length; i += 1) {
var p = contour[i];
var r = Math.sqrt(Math.pow(p.x - circle.x, 2) + Math.pow(p.y - circle.y, 2));
if (circle.r - r > circle.r * THRESHOLD / 100) {
return false;
}
}
return true;
} // gets a circle from 3 points
function circleFromThreePoints(p0, p1, p2) {
var x1 = p0.x;
var y1 = p0.y;
var x2 = p1.x;
var y2 = p1.y;
var x3 = p2.x;
var y3 = p2.y;
var a = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - x3 * y2;
var b = (x1 * x1 + y1 * y1) * (y3 - y2) + (x2 * x2 + y2 * y2) * (y1 - y3) + (x3 * x3 + y3 * y3) * (y2 - y1);
var c = (x1 * x1 + y1 * y1) * (x2 - x3) + (x2 * x2 + y2 * y2) * (x3 - x1) + (x3 * x3 + y3 * y3) * (x1 - x2);
var x = -b / (2 * a);
var y = -c / (2 * a);
return {
x: x,
y: y,
r: Math.hypot(x - x1, y - y1)
};
}
/*

@@ -91,7 +184,7 @@

for (var i = 1; i < endIndex; i += 1) {
var _distance = perpendicularDistance(contour[i], contour[0], contour[endIndex]);
var distance = perpendicularDistance(contour[i], contour[0], contour[endIndex]);
if (_distance > maxDistance) {
if (distance > maxDistance) {
index = i;
maxDistance = _distance;
maxDistance = distance;
}

@@ -153,2 +246,4 @@ }

function ContourFinder(imageData, options) {
var _options$blur, _options$threshold;
if (options === void 0) {

@@ -171,9 +266,11 @@ options = {

this.height = imageData.height;
this.channels = this.data.length / (this.width * this.height); // preprocess image if multi channel
this.channels = this.data.length / (this.width * this.height);
var blur = (_options$blur = options.blur) != null ? _options$blur : false;
var threshold = (_options$threshold = options.threshold) != null ? _options$threshold : 85; // preprocess image if multi channel
if (this.channels > 1) {
// blurs the image for better edge detection
if (options.blur) this.blur(); // threshold image to get bit data
if (blur) this.blur(); // threshold image to get bit data
if (options.threshold > 0) this.toBitData(options.threshold);
this.toBitData(threshold);
} // perform contour detection

@@ -212,3 +309,3 @@

var _loop3 = function _loop3(c) {
_this.data[i + c] = Object.values(clockwiseOffset).reduce(function (prev, curr) {
var avg = Object.values(clockwiseOffset).reduce(function (prev, curr) {
prev += _this.data[_this.pointToIndex({

@@ -220,2 +317,3 @@ x: x + curr.x,

}, _this.data[i + c]) / 9;
_this.data[i + c] = avg;
};

@@ -292,9 +390,9 @@

};
} else {
return this.nextClockwise({
previous: nextPoint,
boundary: boundary,
start: start
});
}
return this.nextClockwise({
previous: nextPoint,
boundary: boundary,
start: start
});
}

@@ -436,5 +534,34 @@ /*

_proto.approximate = function approximate() {
if (!this.isSimplified) this.simplify(); // TODO: approximate contours
var collection = {
points: [],
lines: [],
triangles: [],
squares: [],
recangles: [],
circles: [],
polygons: []
};
if (!this.isSimplified) this.simplify();
this.contours.forEach(function (contour) {
var length = contour.length;
return [];
if (length === 1) {
collection.points.push(contour[0]);
} else if (length === 2) {
collection.lines.push(contour);
} else if (length === 3) {
collection.triangles.push(contour);
} else if (length === 4 && isRectangle(contour)) {
if (isSquare(contour)) {
collection.squares.push(contour);
} else {
collection.recangles.push(contour);
}
} else if (isCircle(contour)) {
collection.circles.push(contour);
} else {
collection.polygons.push(contour);
}
});
return collection;
};

@@ -444,5 +571,4 @@

}();
ContourFinder.THRESHOLD = 85;
exports.ContourFinder = ContourFinder;
//# sourceMappingURL=contours.ts.cjs.development.js.map

@@ -1,2 +0,2 @@

"use strict";function t(){return(t=Object.assign||function(t){for(var i=1;i<arguments.length;i++){var r=arguments[i];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(t[n]=r[n])}return t}).apply(this,arguments)}function i(t,i){return Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2))}Object.defineProperty(exports,"__esModule",{value:!0});var r={"1,0":{x:1,y:1},"1,1":{x:0,y:1},"0,1":{x:-1,y:1},"-1,1":{x:-1,y:0},"-1,0":{x:-1,y:-1},"-1,-1":{x:0,y:-1},"0,-1":{x:1,y:-1},"1,-1":{x:1,y:0}},n=function(){function n(t,i){void 0===i&&(i={blur:!1,threshold:85}),this.contours=[],this.isSimplified=!1,this.visited={},this.data=t.data,this.width=t.width,this.height=t.height,this.channels=this.data.length/(this.width*this.height),this.channels>1&&(i.blur&&this.blur(),i.threshold>0&&this.toBitData(i.threshold)),this.extract()}var s=n.prototype;return s.pointToIndex=function(t){return t.y*this.width+t.x},s.blur=function(){for(var t=this,i=function(i){for(var n=function(n){for(var s=t.pointToIndex({x:i,y:n}),o=function(o){t.data[s+o]=Object.values(r).reduce((function(r,s){return r+(t.data[t.pointToIndex({x:i+s.x,y:n+s.y})]+o)}),t.data[s+o])/9},h=0;h<t.channels;h+=1)o(h)},s=0;s<t.height;s+=1)n(s)},n=0;n<this.width;n+=1)i(n)},s.toBitData=function(t){for(var i=[],r=0;r<this.data.length;r+=this.channels)i.push(.2126*this.data[r]+.7152*this.data[r+1]+.0722*this.data[r+2]>=t?255:0);this.data=i},s.nextClockwise=function(t){var i=t.previous,n=t.boundary,s=t.start,o=void 0===s?i:s,h=r[i.x-n.x+","+(i.y-n.y)],e={x:n.x+h.x,y:n.y+h.y};return e.x<0||e.y<0||e.x>=this.width||e.y>=this.height?this.nextClockwise({previous:e,boundary:n,start:o}):e.x===o.x&&e.y===o.y?{previous:e,boundary:n}:0===this.data[this.pointToIndex(e)]?{previous:i,boundary:e}:this.nextClockwise({previous:e,boundary:n,start:o})},s.traceContour=function(i){var r=[t({},i)],n={x:i.x,y:i.y+1},s=t({},i),o=t({},n);do{var h=this.nextClockwise({previous:o,boundary:s});o=h.previous;var e=this.pointToIndex(s=h.boundary);this.visited[e]||(r.push(s),this.visited[e]=!0)}while(o.x!==n.x||o.y!==n.y||s.x!==i.x||s.y!==i.y);return r},s.extract=function(){for(var t=!1,i=0;i<this.width;i+=1)for(var r=this.height-1;r>=0;r-=1){var n=this.pointToIndex({x:i,y:r});0===this.data[n]?this.visited[n]||t?t=!0:(this.visited[n]=!0,this.contours.push(this.traceContour({x:i,y:r}))):t=!1}},s.simplify=function(t){var r=this;return void 0===t&&(t=1),this.contours.forEach((function(n,s){r.contours[s]=function t(r,n){void 0===n&&(n=1);var s,o,h,e=r.length-1,a=0,u=0;if(r.length<=2)return r;for(var d=1;d<e;d+=1){var x=(s=r[d],(o=r[0]).x===(h=r[e]).x&&o.y===h.y?i(s,o):Math.abs((o.y-h.y)*s.x+(h.x-o.x)*s.y+o.x*h.y-h.x*o.y)/i(o,h));x>a&&(u=d,a=x)}return a>n?[].concat(t(r.slice(0,u),n),t(r.slice(u,e),n)):[r[0],r[e]]}(n,t)})),this.isSimplified=!0,this},s.approximate=function(){return this.isSimplified||this.simplify(),[]},n}();n.THRESHOLD=85,exports.ContourFinder=n;
"use strict";function t(){return(t=Object.assign||function(t){for(var i=1;i<arguments.length;i++){var r=arguments[i];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(t[n]=r[n])}return t}).apply(this,arguments)}function i(t,i){return Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2))}function r(t,r,n){return r.x===n.x&&r.y===n.y?i(t,r):Math.abs((r.y-n.y)*t.x+(n.x-r.x)*t.y+r.x*n.y-n.x*r.y)/i(r,n)}function n(t,i){return Math.atan2(i.y-t.y,i.x-t.x)}function s(t,i){return Math.sqrt(Math.pow(i.y-t.y,2)+Math.pow(i.x-t.x,2))}function o(t,i){var r=i[0],s=i[1],o=n(t[0],t[1]),a=n(r,s);return Math.abs(o-a)*(180/Math.PI)}Object.defineProperty(exports,"__esModule",{value:!0});var a={"1,0":{x:1,y:1},"1,1":{x:0,y:1},"0,1":{x:-1,y:1},"-1,1":{x:-1,y:0},"-1,0":{x:-1,y:-1},"-1,-1":{x:0,y:-1},"0,-1":{x:1,y:-1},"1,-1":{x:1,y:0}};exports.ContourFinder=function(){function i(t,i){var r,n;void 0===i&&(i={blur:!1,threshold:85}),this.contours=[],this.isSimplified=!1,this.visited={},this.data=t.data,this.width=t.width,this.height=t.height,this.channels=this.data.length/(this.width*this.height);var s=null!=(r=i.blur)&&r,o=null!=(n=i.threshold)?n:85;this.channels>1&&(s&&this.blur(),this.toBitData(o)),this.extract()}var n=i.prototype;return n.pointToIndex=function(t){return t.y*this.width+t.x},n.blur=function(){for(var t=this,i=function(i){for(var r=function(r){for(var n=t.pointToIndex({x:i,y:r}),s=function(s){var o=Object.values(a).reduce((function(n,o){return n+(t.data[t.pointToIndex({x:i+o.x,y:r+o.y})]+s)}),t.data[n+s])/9;t.data[n+s]=o},o=0;o<t.channels;o+=1)s(o)},n=0;n<t.height;n+=1)r(n)},r=0;r<this.width;r+=1)i(r)},n.toBitData=function(t){for(var i=[],r=0;r<this.data.length;r+=this.channels)i.push(.2126*this.data[r]+.7152*this.data[r+1]+.0722*this.data[r+2]>=t?255:0);this.data=i},n.nextClockwise=function(t){var i=t.previous,r=t.boundary,n=t.start,s=void 0===n?i:n,o=a[i.x-r.x+","+(i.y-r.y)],h={x:r.x+o.x,y:r.y+o.y};return h.x<0||h.y<0||h.x>=this.width||h.y>=this.height?this.nextClockwise({previous:h,boundary:r,start:s}):h.x===s.x&&h.y===s.y?{previous:h,boundary:r}:0===this.data[this.pointToIndex(h)]?{previous:i,boundary:h}:this.nextClockwise({previous:h,boundary:r,start:s})},n.traceContour=function(i){var r=[t({},i)],n={x:i.x,y:i.y+1},s=t({},i),o=t({},n);do{var a=this.nextClockwise({previous:o,boundary:s});o=a.previous;var h=this.pointToIndex(s=a.boundary);this.visited[h]||(r.push(s),this.visited[h]=!0)}while(o.x!==n.x||o.y!==n.y||s.x!==i.x||s.y!==i.y);return r},n.extract=function(){for(var t=!1,i=0;i<this.width;i+=1)for(var r=this.height-1;r>=0;r-=1){var n=this.pointToIndex({x:i,y:r});0===this.data[n]?this.visited[n]||t?t=!0:(this.visited[n]=!0,this.contours.push(this.traceContour({x:i,y:r}))):t=!1}},n.simplify=function(t){var i=this;return void 0===t&&(t=1),this.contours.forEach((function(n,s){i.contours[s]=function t(i,n){void 0===n&&(n=1);var s=i.length-1,o=0,a=0;if(i.length<=2)return i;for(var h=1;h<s;h+=1){var e=r(i[h],i[0],i[s]);e>o&&(a=h,o=e)}return o>n?[].concat(t(i.slice(0,a),n),t(i.slice(a,s),n)):[i[0],i[s]]}(n,t)})),this.isSimplified=!0,this},n.approximate=function(){var t={points:[],lines:[],triangles:[],squares:[],recangles:[],circles:[],polygons:[]};return this.isSimplified||this.simplify(),this.contours.forEach((function(i){var r=i.length;1===r?t.points.push(i[0]):2===r?t.lines.push(i):3===r?t.triangles.push(i):4===r&&function(t){var i=t[0],r=t[1],n=t[2],s=t[3],a=o([i,r],[r,n]),h=o([i,s],[s,n]);return Math.abs(h-a)<=6.25}(i)?function(t){var i=t[0],r=t[1],n=t[2],o=s(i,r);return function(t,i){var r=i[0],n=i[1],o=s(t[0],t[1]),a=s(r,n);return Math.abs(o-a)}([i,r],[r,n])<=.0625*o}(i)?t.squares.push(i):t.recangles.push(i):function(t){if(t.length<16)return!1;for(var i,r,n,s,o,a,h,e,u,y,c,x,l=t.length,d=(i=t[Math.floor(.25*l)],r=t[Math.floor(.5*l)],n=t[Math.floor(.75*l)],{x:c=-(((s=i.x)*s+(o=i.y)*o)*((u=n.y)-(h=r.y))+((a=r.x)*a+h*h)*(o-u)+((e=n.x)*e+u*u)*(h-o))/(2*(y=s*(h-u)-o*(a-e)+a*u-e*h)),y:x=-((s*s+o*o)*(a-e)+(a*a+h*h)*(e-s)+(e*e+u*u)*(s-a))/(2*y),r:Math.hypot(c-s,x-o)}),f=0;f<t.length;f+=1){var p=t[f],v=Math.sqrt(Math.pow(p.x-d.x,2)+Math.pow(p.y-d.y,2));if(d.r-v>6.25*d.r/100)return!1}return!0}(i)?t.circles.push(i):t.polygons.push(i)})),t},i}();
//# sourceMappingURL=contours.ts.cjs.production.min.js.map

@@ -19,6 +19,9 @@ function _extends() {

var THRESHOLD = 6.25; // distance between two points
function distance(p1, p2) {
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
} // perpendicular distance of a point from a line
function perpendicularDistance(point, start, end) {

@@ -30,3 +33,93 @@ if (start.x === end.x && start.y === end.y) {

return Math.abs((start.y - end.y) * point.x + (end.x - start.x) * point.y + start.x * end.y - end.x * start.y) / distance(start, end);
} // gets angle of a line
function getLineAngle(p0, p1) {
return Math.atan2(p1.y - p0.y, p1.x - p0.x);
} // gets length of a line
function getLineLength(p0, p1) {
return Math.sqrt(Math.pow(p1.y - p0.y, 2) + Math.pow(p1.x - p0.x, 2));
} // angle between two lines
function getLinesAngle(line1, line2) {
var p0 = line1[0],
p1 = line1[1];
var p2 = line2[0],
p3 = line2[1];
var theta1 = getLineAngle(p0, p1);
var theta2 = getLineAngle(p2, p3); // differenc of angle of two lines is angle between those lines
return Math.abs(theta1 - theta2) * (180 / Math.PI);
} // returns diffrnce in length between two lines
function getLinesDifference(line1, line2) {
var p0 = line1[0],
p1 = line1[1];
var p2 = line2[0],
p3 = line2[1];
var length1 = getLineLength(p0, p1);
var length2 = getLineLength(p2, p3);
return Math.abs(length1 - length2);
} // checks if two opposite vertex have right:90 angle
function isRectangle(contour) {
var p0 = contour[0],
p1 = contour[1],
p2 = contour[2],
p3 = contour[3];
var angle1 = getLinesAngle([p0, p1], [p1, p2]);
var angle2 = getLinesAngle([p0, p3], [p3, p2]);
var diff = Math.abs(angle2 - angle1);
return diff <= THRESHOLD;
} // check if two adjacent sides are same of same length
function isSquare(contour) {
var p0 = contour[0],
p1 = contour[1],
p2 = contour[2];
var edgeLength = getLineLength(p0, p1);
var diff = getLinesDifference([p0, p1], [p1, p2]);
return diff <= edgeLength * (THRESHOLD / 100);
} // check if polygon is a circle
function isCircle(contour) {
// polygon has too few points
if (contour.length < 16) return false; // find a circle equation from 3 distinct points
var total = contour.length;
var circle = circleFromThreePoints(contour[Math.floor(total * 0.25)], contour[Math.floor(total * 0.5)], contour[Math.floor(total * 0.75)]); // determine if all points in polygon fulfull this circle equation
for (var i = 0; i < contour.length; i += 1) {
var p = contour[i];
var r = Math.sqrt(Math.pow(p.x - circle.x, 2) + Math.pow(p.y - circle.y, 2));
if (circle.r - r > circle.r * THRESHOLD / 100) {
return false;
}
}
return true;
} // gets a circle from 3 points
function circleFromThreePoints(p0, p1, p2) {
var x1 = p0.x;
var y1 = p0.y;
var x2 = p1.x;
var y2 = p1.y;
var x3 = p2.x;
var y3 = p2.y;
var a = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - x3 * y2;
var b = (x1 * x1 + y1 * y1) * (y3 - y2) + (x2 * x2 + y2 * y2) * (y1 - y3) + (x3 * x3 + y3 * y3) * (y2 - y1);
var c = (x1 * x1 + y1 * y1) * (x2 - x3) + (x2 * x2 + y2 * y2) * (x3 - x1) + (x3 * x3 + y3 * y3) * (x1 - x2);
var x = -b / (2 * a);
var y = -c / (2 * a);
return {
x: x,
y: y,
r: Math.hypot(x - x1, y - y1)
};
}
/*

@@ -87,7 +180,7 @@

for (var i = 1; i < endIndex; i += 1) {
var _distance = perpendicularDistance(contour[i], contour[0], contour[endIndex]);
var distance = perpendicularDistance(contour[i], contour[0], contour[endIndex]);
if (_distance > maxDistance) {
if (distance > maxDistance) {
index = i;
maxDistance = _distance;
maxDistance = distance;
}

@@ -149,2 +242,4 @@ }

function ContourFinder(imageData, options) {
var _options$blur, _options$threshold;
if (options === void 0) {

@@ -167,9 +262,11 @@ options = {

this.height = imageData.height;
this.channels = this.data.length / (this.width * this.height); // preprocess image if multi channel
this.channels = this.data.length / (this.width * this.height);
var blur = (_options$blur = options.blur) != null ? _options$blur : false;
var threshold = (_options$threshold = options.threshold) != null ? _options$threshold : 85; // preprocess image if multi channel
if (this.channels > 1) {
// blurs the image for better edge detection
if (options.blur) this.blur(); // threshold image to get bit data
if (blur) this.blur(); // threshold image to get bit data
if (options.threshold > 0) this.toBitData(options.threshold);
this.toBitData(threshold);
} // perform contour detection

@@ -208,3 +305,3 @@

var _loop3 = function _loop3(c) {
_this.data[i + c] = Object.values(clockwiseOffset).reduce(function (prev, curr) {
var avg = Object.values(clockwiseOffset).reduce(function (prev, curr) {
prev += _this.data[_this.pointToIndex({

@@ -216,2 +313,3 @@ x: x + curr.x,

}, _this.data[i + c]) / 9;
_this.data[i + c] = avg;
};

@@ -288,9 +386,9 @@

};
} else {
return this.nextClockwise({
previous: nextPoint,
boundary: boundary,
start: start
});
}
return this.nextClockwise({
previous: nextPoint,
boundary: boundary,
start: start
});
}

@@ -432,5 +530,34 @@ /*

_proto.approximate = function approximate() {
if (!this.isSimplified) this.simplify(); // TODO: approximate contours
var collection = {
points: [],
lines: [],
triangles: [],
squares: [],
recangles: [],
circles: [],
polygons: []
};
if (!this.isSimplified) this.simplify();
this.contours.forEach(function (contour) {
var length = contour.length;
return [];
if (length === 1) {
collection.points.push(contour[0]);
} else if (length === 2) {
collection.lines.push(contour);
} else if (length === 3) {
collection.triangles.push(contour);
} else if (length === 4 && isRectangle(contour)) {
if (isSquare(contour)) {
collection.squares.push(contour);
} else {
collection.recangles.push(contour);
}
} else if (isCircle(contour)) {
collection.circles.push(contour);
} else {
collection.polygons.push(contour);
}
});
return collection;
};

@@ -440,5 +567,4 @@

}();
ContourFinder.THRESHOLD = 85;
export { ContourFinder };
//# sourceMappingURL=contours.ts.esm.js.map

@@ -1,3 +0,2 @@

import { Point } from './types/Point';
export declare function perpendicularDistance(point: Point, start: Point, end: Point): number;
import { Polygon } from './types/ShapeType';
/**

@@ -10,2 +9,2 @@ *

*/
export declare function RDP(contour: Point[], epsilon?: number): Point[];
export declare function RDP(contour: Polygon, epsilon?: number): Polygon;

@@ -1,15 +0,15 @@

export declare enum ShapeTypes {
Rectangle = 0,
Circle = 1
}
export interface Rectangle {
export interface Point {
x: number;
y: number;
width: number;
height: number;
}
export interface Circle {
x: number;
y: number;
radius: number;
export interface Polygon extends Array<Point> {
}
export interface ShapeCollection {
points: Point[];
lines: Polygon[];
triangles: Polygon[];
squares: Polygon[];
recangles: Polygon[];
circles: Polygon[];
polygons: Polygon[];
}

@@ -10,7 +10,8 @@ {

"@types/jest": "^26.0.19",
"@typescript-eslint/eslint-plugin": "^4.9.1",
"@typescript-eslint/parser": "^4.9.1",
"@types/prettier": "^2.1.6",
"@typescript-eslint/eslint-plugin": "^4.11.0",
"@typescript-eslint/parser": "^4.11.0",
"babel-eslint": "^10.1.0",
"eslint": "^7.15.0",
"eslint-config-prettier": "^7.0.0",
"eslint": "^7.16.0",
"eslint-config-prettier": "^7.1.0",
"eslint-config-react-app": "^6.0.0",

@@ -24,3 +25,3 @@ "eslint-config-standard": "^16.0.2",

"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.2.0",
"eslint-plugin-prettier": "^3.3.0",
"eslint-plugin-promise": "^4.2.1",

@@ -30,3 +31,3 @@ "eslint-plugin-react": "^7.21.5",

"eslint-plugin-standard": "^4.1.0",
"husky": "^4.3.5",
"husky": "^4.3.6",
"jest": "^26.6.3",

@@ -65,8 +66,2 @@ "prettier": "^2.2.1",

"peerDependencies": {},
"prettier": {
"printWidth": 80,
"semi": false,
"singleQuote": true,
"trailingComma": "es5"
},
"repository": {

@@ -97,3 +92,3 @@ "type": "git",

"typings": "dist/index.d.ts",
"version": "0.1.4"
"version": "0.1.5"
}

@@ -21,3 +21,3 @@ # Contours.ts

### Approximate Contours to Shapes
### Approximate Contours to Common Shapes (Triangle, Rectangle, Square, Circle)

@@ -73,4 +73,4 @@ ## How to use

const { contours } = new ContourFinder(imageData, {
blur: true // blurs the image data
threshold: 85 // threshold image data
blur: true, // blurs the image data
threshold: 85, // threshold image data
})

@@ -119,5 +119,16 @@

[
{x: 0, y: 0, width: 1, height: 1}, // Rect
{x: 1, y: 1, radius: 1}, // Circle
[{x: 0, y: 0}, {x: 3, y: 3}] // Polygon
{
points: [[{x: 0, y: 0}]],
lines: [[{x: 0, y: 0}, {x: 3, y: 3}]],
triangles: [],
squares: [
[{ x: 0, y: 0 },
{ x: 5, y: 0 },
{ x: 5, y: 5 },
{ x: 0, y: 5 },]
],
recangles: [],
circles: [],
polygons: [],
}
]

@@ -124,0 +135,0 @@ */

import { RDP } from './rdp'
import { ImageDataLike } from './types/ImageDataLike'
import { Point } from './types/Point'
import { Circle, Rectangle } from './types/ShapeType'
import { Point, Polygon, ShapeCollection } from './types/ShapeType'
import { isCircle, isRectangle, isSquare } from './utilities'

@@ -26,4 +26,4 @@ /**

interface ContourFinderOptions {
blur: boolean
threshold: number
blur?: boolean
threshold?: number
}

@@ -35,4 +35,2 @@

export class ContourFinder {
private static readonly THRESHOLD = 85
private data: Uint8ClampedArray | number[]

@@ -43,3 +41,3 @@ private readonly width: number

public readonly contours: Point[][] = []
public readonly contours: Polygon[] = []

@@ -65,9 +63,12 @@ private isSimplified = false

const blur = options.blur ?? false
const threshold = options.threshold ?? 85
// preprocess image if multi channel
if (this.channels > 1) {
// blurs the image for better edge detection
if (options.blur) this.blur()
if (blur) this.blur()
// threshold image to get bit data
if (options.threshold > 0) this.toBitData(options.threshold)
this.toBitData(threshold)
}

@@ -100,3 +101,3 @@

for (let c = 0; c < this.channels; c += 1) {
this.data[i + c] =
const avg =
Object.values(clockwiseOffset).reduce((prev, curr) => {

@@ -113,2 +114,4 @@ prev +=

}, this.data[i + c]) / 9
this.data[i + c] = avg
}

@@ -190,5 +193,5 @@ }

}
} else {
return this.nextClockwise({ previous: nextPoint, boundary, start })
}
return this.nextClockwise({ previous: nextPoint, boundary, start })
}

@@ -236,4 +239,4 @@

*/
private traceContour(first: Point): Point[] {
const contour: Point[] = [{ ...first }]
private traceContour(first: Point): Polygon {
const contour: Polygon = [{ ...first }]
// the point we entered first from

@@ -331,8 +334,39 @@ const firstPrevious = {

*/
public approximate(): Array<Rectangle | Circle | Point[]> {
public approximate(): ShapeCollection {
const collection: ShapeCollection = {
points: [],
lines: [],
triangles: [],
squares: [],
recangles: [],
circles: [],
polygons: [],
}
if (!this.isSimplified) this.simplify()
// TODO: approximate contours
return []
this.contours.forEach((contour) => {
const { length } = contour
if (length === 1) {
collection.points.push(contour[0])
} else if (length === 2) {
collection.lines.push(contour)
} else if (length === 3) {
collection.triangles.push(contour)
} else if (length === 4 && isRectangle(contour)) {
if (isSquare(contour)) {
collection.squares.push(contour)
} else {
collection.recangles.push(contour)
}
} else if (isCircle(contour)) {
collection.circles.push(contour)
} else {
collection.polygons.push(contour)
}
})
return collection
}
}

@@ -1,26 +0,4 @@

import { Point } from './types/Point'
import { Polygon } from './types/ShapeType'
import { perpendicularDistance } from './utilities'
function distance(p1: Point, p2: Point): number {
return Math.sqrt((p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2)
}
export function perpendicularDistance(
point: Point,
start: Point,
end: Point
): number {
if (start.x === end.x && start.y === end.y) {
return distance(point, start)
}
return (
Math.abs(
(start.y - end.y) * point.x +
(end.x - start.x) * point.y +
start.x * end.y -
end.x * start.y
) / distance(start, end)
)
}
/*

@@ -67,5 +45,5 @@

*/
export function RDP(contour: Point[], epsilon = 1): Point[] {
export function RDP(contour: Polygon, epsilon = 1): Polygon {
const endIndex = contour.length - 1
let collection: Point[] = []
let collection: Polygon = []
let maxDistance = 0

@@ -72,0 +50,0 @@ let index = 0

@@ -1,17 +0,16 @@

export enum ShapeTypes {
Rectangle,
Circle,
}
export interface Rectangle {
export interface Point {
x: number
y: number
width: number
height: number
}
export interface Circle {
x: number
y: number
radius: number
export interface Polygon extends Array<Point> {}
export interface ShapeCollection {
points: Point[]
lines: Polygon[]
triangles: Polygon[]
squares: Polygon[]
recangles: Polygon[]
circles: Polygon[]
polygons: Polygon[]
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc