refactor and remove hysteresis (#327)

* refactor and remove hysteresis

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>

* fixes #323

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>

* bump version #
This commit is contained in:
Varun Gupta
2018-09-06 02:09:13 +05:30
committed by Jeffrey Warren
parent 6106e5ee0c
commit 0638a1c68c
5 changed files with 366 additions and 373 deletions

View File

@@ -48456,14 +48456,13 @@ module.exports={
},{}],152:[function(require,module,exports){
module.exports = exports = function(pixels, blur) {
let kernel = kernelGenerator(blur,1)
kernel = flipKernel(kernel)
var oldpix = pixels
let kernel = kernelGenerator(blur, 1), oldpix = pixels;
kernel = flipKernel(kernel);
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let neighboutPos = getNeighbouringPixelPositions([i,j])
let acc = [0.0,0.0,0.0,0.0]
let neighboutPos = getNeighbouringPixelPositions([i, j]);
let acc = [0.0, 0.0, 0.0, 0.0];
for (let a = 0; a < kernel.length; a++) {
for (let b = 0; b < kernel.length; b++) {
acc[0] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 0) * kernel[a][b]);
@@ -48472,12 +48471,12 @@ module.exports = exports = function(pixels,blur){
acc[3] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 3) * kernel[a][b]);
}
}
pixels.set(i,j,0,acc[0])
pixels.set(i,j,1,acc[1])
pixels.set(i,j,2,acc[2])
pixels.set(i, j, 0, acc[0]);
pixels.set(i, j, 1, acc[1]);
pixels.set(i, j, 2, acc[2]);
}
}
return pixels
return pixels;
@@ -48513,31 +48512,31 @@ module.exports = exports = function(pixels,blur){
[5.0 / 159.0, 12.0 / 159.0, 15.0 / 159.0, 12.0 / 159.0, 5.0 / 159.0],
[4.0 / 159.0, 9.0 / 159.0, 12.0 / 159.0, 9.0 / 159.0, 4.0 / 159.0],
[2.0 / 159.0, 4.0 / 159.0, 5.0 / 159.0, 4.0 / 159.0, 2.0 / 159.0]
]
];
}
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0],y=pixelPosition[1]
let result = []
let x = pixelPosition[0], y = pixelPosition[1], result = [];
for (let i = -2; i <= 2; i++) {
let arr = []
for(let j=-2;j<=2;j++){
arr.push([x + i,y + j])
let arr = [];
for (let j = -2; j <= 2; j++)
arr.push([x + i, y + j]);
result.push(arr);
}
result.push(arr)
}
return result
return result;
}
function flipKernel(kernel) {
let result = []
let result = [];
for (let i = kernel.length - 1; i >= 0; i--) {
let arr = []
let arr = [];
for (let j = kernel[i].length - 1; j >= 0; j--) {
arr.push(kernel[i][j])
arr.push(kernel[i][j]);
}
result.push(arr)
result.push(arr);
}
return result
return result;
}
}
},{}],153:[function(require,module,exports){
@@ -49369,18 +49368,14 @@ const _ = require('lodash')
//define kernels for the sobel filter
const kernelx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]],
kernely = [[-1,-2,-1],[0,0,0],[1,2,1]]
kernely = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]];
let angles = []
let mags = []
let strongEdgePixels = []
let weakEdgePixels = []
let notInUI
module.exports = exports = function(pixels,highThresholdRatio,lowThresholdRatio,inBrowser){
notInUI = !inBrowser
let angles = [], mags = [], strongEdgePixels = [], weakEdgePixels = [], notInUI;
module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, inBrowser) {
notInUI = !inBrowser;
for (var x = 0; x < pixels.shape[0]; x++) {
angles.push([])
mags.push([])
angles.push([]);
mags.push([]);
for (var y = 0; y < pixels.shape[1]; y++) {
var result = changePixel(
pixels,
@@ -49388,25 +49383,25 @@ module.exports = exports = function(pixels,highThresholdRatio,lowThresholdRatio
pixels.get(x, y, 3),
x,
y
)
let pixel = result.pixel
);
let pixel = result.pixel;
pixels.set(x, y, 0, pixel[0]);
pixels.set(x, y, 1, pixel[1]);
pixels.set(x, y, 2, pixel[2]);
pixels.set(x, y, 3, pixel[3]);
mags.slice(-1)[0].push(pixel[3])
angles.slice(-1)[0].push(result.angle)
mags.slice(-1)[0].push(pixel[3]);
angles.slice(-1)[0].push(result.angle);
}
}
return hysteresis(doubleThreshold(nonMaxSupress(pixels),highThresholdRatio,lowThresholdRatio))
return doubleThreshold(nonMaxSupress(pixels), highThresholdRatio, lowThresholdRatio);
}
//changepixel function that convolutes every pixel (sobel filter)
function changePixel(pixels, val, a, x, y) {
let magX = 0.0
let magX = 0.0;
for (let a = 0; a < 3; a++) {
for (let b = 0; b < 3; b++) {
@@ -49416,7 +49411,7 @@ function changePixel(pixels,val,a,x,y){
magX += pixels.get(xn, yn, 0) * kernelx[a][b];
}
}
let magY = 0.0
let magY = 0.0;
for (let a = 0; a < 3; a++) {
for (let b = 0; b < 3; b++) {
@@ -49426,95 +49421,97 @@ function changePixel(pixels,val,a,x,y){
magY += pixels.get(xn, yn, 0) * kernely[a][b];
}
}
let mag = Math.sqrt(Math.pow(magX,2) + Math.pow(magY,2))
let angle = Math.atan2(magY,magX)
let mag = Math.sqrt(Math.pow(magX, 2) + Math.pow(magY, 2));
let angle = Math.atan2(magY, magX);
return {
pixel:
[val, val, val, mag],
angle: angle
}
};
}
//Non Maximum Supression without interpolation
function nonMaxSupress(pixels) {
angles = angles.map((arr)=>arr.map(convertToDegrees))
angles = angles.map((arr) => arr.map(convertToDegrees));
for (let i = 1; i < pixels.shape[0] - 1; i++) {
for (let j = 1; j < pixels.shape[1] - 1; j++) {
let angle = angles[i][j]
let pixel = pixels.get(i,j)
let angle = angles[i][j];
let pixel = pixels.get(i, j);
if ((angle >= -22.5 && angle <= 22.5) ||
(angle < -157.5 && angle >= -180))
if ((mags[i][j] >= mags[i][j + 1]) &&
(mags[i][j] >= mags[i][j - 1]))
pixels.set(i,j,3,mags[i][j])
pixels.set(i, j, 3, mags[i][j]);
else
pixels.set(i,j,3,0)
pixels.set(i, j, 3, 0);
else if ((angle >= 22.5 && angle <= 67.5) ||
(angle < -112.5 && angle >= -157.5))
if ((mags[i][j] >= mags[i + 1][j + 1]) &&
(mags[i][j] >= mags[i - 1][j - 1]))
pixels.set(i,j,3,mags[i][j])
pixels.set(i, j, 3, mags[i][j]);
else
pixels.set(i,j,3,0)
pixels.set(i, j, 3, 0);
else if ((angle >= 67.5 && angle <= 112.5) ||
(angle < -67.5 && angle >= -112.5))
if ((mags[i][i] >= mags[i + 1][j]) &&
(mags[i][j] >= mags[i][j]))
pixels.set(i,j,3,mags[i][j])
pixels.set(i, j, 3, mags[i][j]);
else
pixels.set(i,j,3,0)
pixels.set(i, j, 3, 0);
else if ((angle >= 112.5 && angle <= 157.5) ||
(angle < -22.5 && angle >= -67.5))
if ((mags[i][j] >= mags[i + 1][j - 1]) &&
(mags[i][j] >= mags[i - 1][j + 1]))
pixels.set(i,j,3,mags[i][j])
pixels.set(i, j, 3, mags[i][j]);
else
pixels.set(i,j,3,0)
pixels.set(i, j, 3, 0);
}
}
return pixels
return pixels;
}
//Converts radians to degrees
var convertToDegrees = radians => (radians * 180)/Math.PI
var convertToDegrees = radians => (radians * 180) / Math.PI;
//Finds the max value in a 2d array like mags
var findMaxInMatrix = arr => Math.max(...arr.map(el=>el.map(val=>!!val?val:0)).map(el=>Math.max(...el)))
var findMaxInMatrix = arr => Math.max(...arr.map(el => el.map(val => !!val ? val : 0)).map(el => Math.max(...el)));
//Applies the double threshold to the image
function doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio) {
const highThreshold = findMaxInMatrix(mags) * 0.2
const lowThreshold = highThreshold * lowThresholdRatio
const highThreshold = findMaxInMatrix(mags) * 0.2;
const lowThreshold = highThreshold * lowThresholdRatio;
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let pixelPos = [i,j]
let pixelPos = [i, j];
mags[i][j] > lowThreshold
? mags[i][j] > highThreshold
? strongEdgePixels.push(pixelPos)
: weakEdgePixels.push(pixelPos)
:pixels.set(i,j,3,0)
: pixels.set(i, j, 3, 0);
}
}
strongEdgePixels.forEach(pix=>pixels.set(pix[0],pix[1],3,255))
strongEdgePixels.forEach(pix => pixels.set(pix[0], pix[1], 3, 255));
return pixels
return pixels;
}
// hysteresis edge tracking algorithm
function hysteresis(pixels){
// hysteresis edge tracking algorithm -- not working as of now
/* function hysteresis(pixels) {
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0], y = pixelPosition[1]
return [[x + 1, y + 1],
@@ -49540,7 +49537,7 @@ function hysteresis(pixels){
}
weakEdgePixels.forEach(pix => pixels.set(pix[0], pix[1], 3, 0))
return pixels
}
} */

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{
"name": "image-sequencer",
"version": "2.2.1",
"version": "2.2.2",
"description": "A modular JavaScript image manipulation library modeled on a storyboard.",
"main": "src/ImageSequencer.js",
"scripts": {
@@ -43,7 +43,6 @@
},
"devDependencies": {
"browserify": "13.0.0",
"data-uri-to-buffer": "^2.0.0",
"grunt": "^0.4.5",
"grunt-browser-sync": "^2.2.0",
"grunt-browserify": "^5.0.0",

View File

@@ -1,12 +1,11 @@
module.exports = exports = function(pixels, blur) {
let kernel = kernelGenerator(blur,1)
kernel = flipKernel(kernel)
var oldpix = pixels
let kernel = kernelGenerator(blur, 1), oldpix = pixels;
kernel = flipKernel(kernel);
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let neighboutPos = getNeighbouringPixelPositions([i,j])
let acc = [0.0,0.0,0.0,0.0]
let neighboutPos = getNeighbouringPixelPositions([i, j]);
let acc = [0.0, 0.0, 0.0, 0.0];
for (let a = 0; a < kernel.length; a++) {
for (let b = 0; b < kernel.length; b++) {
acc[0] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 0) * kernel[a][b]);
@@ -15,12 +14,12 @@ module.exports = exports = function(pixels,blur){
acc[3] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 3) * kernel[a][b]);
}
}
pixels.set(i,j,0,acc[0])
pixels.set(i,j,1,acc[1])
pixels.set(i,j,2,acc[2])
pixels.set(i, j, 0, acc[0]);
pixels.set(i, j, 1, acc[1]);
pixels.set(i, j, 2, acc[2]);
}
}
return pixels
return pixels;
@@ -56,30 +55,30 @@ module.exports = exports = function(pixels,blur){
[5.0 / 159.0, 12.0 / 159.0, 15.0 / 159.0, 12.0 / 159.0, 5.0 / 159.0],
[4.0 / 159.0, 9.0 / 159.0, 12.0 / 159.0, 9.0 / 159.0, 4.0 / 159.0],
[2.0 / 159.0, 4.0 / 159.0, 5.0 / 159.0, 4.0 / 159.0, 2.0 / 159.0]
]
];
}
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0],y=pixelPosition[1]
let result = []
let x = pixelPosition[0], y = pixelPosition[1], result = [];
for (let i = -2; i <= 2; i++) {
let arr = []
for(let j=-2;j<=2;j++){
arr.push([x + i,y + j])
let arr = [];
for (let j = -2; j <= 2; j++)
arr.push([x + i, y + j]);
result.push(arr);
}
result.push(arr)
}
return result
return result;
}
function flipKernel(kernel) {
let result = []
let result = [];
for (let i = kernel.length - 1; i >= 0; i--) {
let arr = []
let arr = [];
for (let j = kernel[i].length - 1; j >= 0; j--) {
arr.push(kernel[i][j])
arr.push(kernel[i][j]);
}
result.push(arr)
result.push(arr);
}
return result
return result;
}
}

View File

@@ -2,18 +2,14 @@ const _ = require('lodash')
//define kernels for the sobel filter
const kernelx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]],
kernely = [[-1,-2,-1],[0,0,0],[1,2,1]]
kernely = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]];
let angles = []
let mags = []
let strongEdgePixels = []
let weakEdgePixels = []
let notInUI
module.exports = exports = function(pixels,highThresholdRatio,lowThresholdRatio,inBrowser){
notInUI = !inBrowser
let angles = [], mags = [], strongEdgePixels = [], weakEdgePixels = [], notInUI;
module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, inBrowser) {
notInUI = !inBrowser;
for (var x = 0; x < pixels.shape[0]; x++) {
angles.push([])
mags.push([])
angles.push([]);
mags.push([]);
for (var y = 0; y < pixels.shape[1]; y++) {
var result = changePixel(
pixels,
@@ -21,25 +17,25 @@ module.exports = exports = function(pixels,highThresholdRatio,lowThresholdRatio
pixels.get(x, y, 3),
x,
y
)
let pixel = result.pixel
);
let pixel = result.pixel;
pixels.set(x, y, 0, pixel[0]);
pixels.set(x, y, 1, pixel[1]);
pixels.set(x, y, 2, pixel[2]);
pixels.set(x, y, 3, pixel[3]);
mags.slice(-1)[0].push(pixel[3])
angles.slice(-1)[0].push(result.angle)
mags.slice(-1)[0].push(pixel[3]);
angles.slice(-1)[0].push(result.angle);
}
}
return hysteresis(doubleThreshold(nonMaxSupress(pixels),highThresholdRatio,lowThresholdRatio))
return doubleThreshold(nonMaxSupress(pixels), highThresholdRatio, lowThresholdRatio);
}
//changepixel function that convolutes every pixel (sobel filter)
function changePixel(pixels, val, a, x, y) {
let magX = 0.0
let magX = 0.0;
for (let a = 0; a < 3; a++) {
for (let b = 0; b < 3; b++) {
@@ -49,7 +45,7 @@ function changePixel(pixels,val,a,x,y){
magX += pixels.get(xn, yn, 0) * kernelx[a][b];
}
}
let magY = 0.0
let magY = 0.0;
for (let a = 0; a < 3; a++) {
for (let b = 0; b < 3; b++) {
@@ -59,95 +55,97 @@ function changePixel(pixels,val,a,x,y){
magY += pixels.get(xn, yn, 0) * kernely[a][b];
}
}
let mag = Math.sqrt(Math.pow(magX,2) + Math.pow(magY,2))
let angle = Math.atan2(magY,magX)
let mag = Math.sqrt(Math.pow(magX, 2) + Math.pow(magY, 2));
let angle = Math.atan2(magY, magX);
return {
pixel:
[val, val, val, mag],
angle: angle
}
};
}
//Non Maximum Supression without interpolation
function nonMaxSupress(pixels) {
angles = angles.map((arr)=>arr.map(convertToDegrees))
angles = angles.map((arr) => arr.map(convertToDegrees));
for (let i = 1; i < pixels.shape[0] - 1; i++) {
for (let j = 1; j < pixels.shape[1] - 1; j++) {
let angle = angles[i][j]
let pixel = pixels.get(i,j)
let angle = angles[i][j];
let pixel = pixels.get(i, j);
if ((angle >= -22.5 && angle <= 22.5) ||
(angle < -157.5 && angle >= -180))
if ((mags[i][j] >= mags[i][j + 1]) &&
(mags[i][j] >= mags[i][j - 1]))
pixels.set(i,j,3,mags[i][j])
pixels.set(i, j, 3, mags[i][j]);
else
pixels.set(i,j,3,0)
pixels.set(i, j, 3, 0);
else if ((angle >= 22.5 && angle <= 67.5) ||
(angle < -112.5 && angle >= -157.5))
if ((mags[i][j] >= mags[i + 1][j + 1]) &&
(mags[i][j] >= mags[i - 1][j - 1]))
pixels.set(i,j,3,mags[i][j])
pixels.set(i, j, 3, mags[i][j]);
else
pixels.set(i,j,3,0)
pixels.set(i, j, 3, 0);
else if ((angle >= 67.5 && angle <= 112.5) ||
(angle < -67.5 && angle >= -112.5))
if ((mags[i][i] >= mags[i + 1][j]) &&
(mags[i][j] >= mags[i][j]))
pixels.set(i,j,3,mags[i][j])
pixels.set(i, j, 3, mags[i][j]);
else
pixels.set(i,j,3,0)
pixels.set(i, j, 3, 0);
else if ((angle >= 112.5 && angle <= 157.5) ||
(angle < -22.5 && angle >= -67.5))
if ((mags[i][j] >= mags[i + 1][j - 1]) &&
(mags[i][j] >= mags[i - 1][j + 1]))
pixels.set(i,j,3,mags[i][j])
pixels.set(i, j, 3, mags[i][j]);
else
pixels.set(i,j,3,0)
pixels.set(i, j, 3, 0);
}
}
return pixels
return pixels;
}
//Converts radians to degrees
var convertToDegrees = radians => (radians * 180)/Math.PI
var convertToDegrees = radians => (radians * 180) / Math.PI;
//Finds the max value in a 2d array like mags
var findMaxInMatrix = arr => Math.max(...arr.map(el=>el.map(val=>!!val?val:0)).map(el=>Math.max(...el)))
var findMaxInMatrix = arr => Math.max(...arr.map(el => el.map(val => !!val ? val : 0)).map(el => Math.max(...el)));
//Applies the double threshold to the image
function doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio) {
const highThreshold = findMaxInMatrix(mags) * 0.2
const lowThreshold = highThreshold * lowThresholdRatio
const highThreshold = findMaxInMatrix(mags) * 0.2;
const lowThreshold = highThreshold * lowThresholdRatio;
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let pixelPos = [i,j]
let pixelPos = [i, j];
mags[i][j] > lowThreshold
? mags[i][j] > highThreshold
? strongEdgePixels.push(pixelPos)
: weakEdgePixels.push(pixelPos)
:pixels.set(i,j,3,0)
: pixels.set(i, j, 3, 0);
}
}
strongEdgePixels.forEach(pix=>pixels.set(pix[0],pix[1],3,255))
strongEdgePixels.forEach(pix => pixels.set(pix[0], pix[1], 3, 255));
return pixels
return pixels;
}
// hysteresis edge tracking algorithm
function hysteresis(pixels){
// hysteresis edge tracking algorithm -- not working as of now
/* function hysteresis(pixels) {
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0], y = pixelPosition[1]
return [[x + 1, y + 1],
@@ -173,7 +171,7 @@ function hysteresis(pixels){
}
weakEdgePixels.forEach(pix => pixels.set(pix[0], pix[1], 3, 0))
return pixels
}
} */