opencv-facecrop
Advanced tools
Comparing version 0.0.4 to 0.0.5
110
index.js
const { Canvas, createCanvas, Image, ImageData, loadImage } = require('canvas'); | ||
const { JSDOM } = require('jsdom'); | ||
const { writeFileSync, existsSync, stat, statSync } = require('fs'); | ||
const { exception } = require('console'); | ||
const { writeFileSync, existsSync, statSync } = require('fs'); | ||
module.exports = async (file, name="output.jpg", type="image/jpeg", quality=0.95, trainingSet = "./node_modules/opencv-facecrop/resources/haarcascade_frontalface_default.xml") => { | ||
await loadOpenCV(); | ||
console.log("Loading file...") | ||
const image = await loadImage(file); | ||
const src = cv.imread(image); | ||
let gray = new cv.Mat(); | ||
module.exports = async (file, name = "output.jpg", type = "image/jpeg", quality = 0.95, factor = 0, trainingSet = "./node_modules/opencv-facecrop/resources/haarcascade_frontalface_default.xml") => { | ||
let image, src, gray, faces, faceCascade; | ||
try { | ||
await loadOpenCV().catch((e) => { throw new Error("Error: Loading OpenCV failed.\n" + e.message) }); | ||
console.log("Loading file..."); | ||
image = await loadImage(file) | ||
.catch((e) => { throw new Error("Error: Loading input image failed.\n" + e.message) }); | ||
if (image != null) | ||
src = cv.imread(image); | ||
gray = new cv.Mat(); | ||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0); | ||
let faces = new cv.RectVector(); | ||
let faceCascade = new cv.CascadeClassifier(); | ||
try{ | ||
faces = new cv.RectVector(); | ||
faceCascade = new cv.CascadeClassifier(); | ||
console.log("Loading pre-trained classifier files..."); | ||
statSync(trainingSet, (err) => { | ||
if(err != null) | ||
throw err; | ||
}); | ||
try { | ||
statSync(trainingSet); | ||
} | ||
catch (err) { | ||
throw new Error("Error: Pre-Trained Classifier file failed to load.\n" + err.message); | ||
} | ||
faceCascade.load(trainingSet); | ||
@@ -30,41 +35,54 @@ | ||
faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, mSize, mSize); | ||
let point1, point2; | ||
for (let i = 0; i < faces.size(); ++i) { | ||
let point1, point2; | ||
for (let i = 0; i < faces.size(); ++i) { | ||
point1 = new cv.Point(faces.get(i).x, faces.get(i).y); | ||
point2 = new cv.Point(faces.get(i).x + faces.get(i).width, faces.get(i).y + faces.get(i).height); | ||
point2 = new cv.Point(faces.get(i).x + faces.get(i).width, faces.get(i).y + faces.get(i).height); | ||
point1.x = point1.x - factor; | ||
point1.y = point1.y - factor; | ||
point2.x = point2.x + factor; | ||
point2.y = point2.y + factor; | ||
if (point1.x < 0 || point1.y < 0 || point2.x < 0 || point2.y < 0) | ||
throw new Error('Error: Factor passed is too high/low.'); | ||
const canvas = createCanvas(point2.x - point1.x, point2.y - point1.y); | ||
let rect = new cv.Rect(point1.x, point1.y, point2.x - point1.x, point2.y - point1.y); | ||
console.log('Rendering file...') | ||
console.log('Rendering output image...') | ||
let dst = src.roi(rect); | ||
console.log("Source File dimension: " + src.size().width + "x" + src.size().height); | ||
console.log("Destination File dimension: " + dst.size().width + "x" + dst.size().height); | ||
cv.imshow(canvas, dst); | ||
cv.imshow(canvas, dst); | ||
let outputFilename = name.toString(); | ||
if(faces.size() > 1){ | ||
if(outputFilename.charAt(outputFilename.length - 4) == '.'){ | ||
outputFilename = outputFilename.substr(0, (outputFilename.length - 4)) + `-${i+1}` + outputFilename.substr((outputFilename.length - 4), 4); | ||
} | ||
else { | ||
throw new Error('File extension should be 3 characters only.'); | ||
} | ||
if (faces.size() > 1) { | ||
if (outputFilename.charAt(outputFilename.length - 4) == '.') | ||
outputFilename = outputFilename.substr(0, (outputFilename.length - 4)) + `-${i + 1}` + outputFilename.substr((outputFilename.length - 4), 4); | ||
else | ||
throw new Error('Error: File extension should be 3 characters only.'); | ||
} | ||
writeFileSync(outputFilename, canvas.toBuffer(type,{ quality: quality })); | ||
writeFileSync(outputFilename, canvas.toBuffer(type, { quality: quality })); | ||
console.log(outputFilename + " created successfully."); | ||
} | ||
} | ||
return "Success"; | ||
} | ||
catch(e){ | ||
throw e; | ||
catch (e) { | ||
console.error(e.message); | ||
return e.message; | ||
} | ||
finally{ | ||
src.delete(); gray.delete(); faceCascade.delete(); faces.delete(); | ||
finally { | ||
if (src) src.delete(); | ||
if (gray) gray.delete(); | ||
if (faceCascade) faceCascade.delete(); | ||
if (faces) faces.delete(); | ||
} | ||
@@ -84,3 +102,3 @@ }; | ||
function loadOpenCV(rootDir = '/work', localRootDir = process.cwd()) { | ||
if(global.Module && global.Module.onRuntimeInitialized && global.cv && global.cv.imread) { | ||
if (global.Module && global.Module.onRuntimeInitialized && global.cv && global.cv.imread) { | ||
return Promise.resolve() | ||
@@ -103,12 +121,12 @@ } | ||
// create rootDir if it doesn't exists | ||
if(!FS.analyzePath(rootDir).exists) { | ||
if (!FS.analyzePath(rootDir).exists) { | ||
FS.mkdir(rootDir); | ||
} | ||
// create localRootFolder if it doesn't exists | ||
if(!existsSync(localRootDir)) { | ||
mkdirSync(localRootDir, { recursive: true}); | ||
if (!existsSync(localRootDir)) { | ||
mkdirSync(localRootDir, { recursive: true }); | ||
} | ||
// FS.mount() is similar to Linux/POSIX mount operation. It basically mounts an external | ||
// filesystem with given format, in given current filesystem directory. | ||
FS.mount(FS.filesystems.NODEFS, { root: localRootDir}, rootDir); | ||
FS.mount(FS.filesystems.NODEFS, { root: localRootDir }, rootDir); | ||
} | ||
@@ -119,3 +137,3 @@ }; | ||
} | ||
function installDOM(){ | ||
function installDOM() { | ||
const dom = new JSDOM(); | ||
@@ -122,0 +140,0 @@ global.document = dom.window.document; |
{ | ||
"name": "opencv-facecrop", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Npm package to autodetect and crop faces using opencv", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -30,3 +30,3 @@ # OpenCv - Face Crop : Autodetect & crop faces out of an image (Node.js) | ||
facecrop('./image-file.jpg', './dest/output.jpg', "image/jpeg", 0.95); | ||
facecrop('./image-file.jpg', './dest/output.jpg', "image/jpeg", 0.95, 50); | ||
@@ -53,15 +53,21 @@ /* Outputs image with file name output.jpg in 'dest' folder with the face cropped out. | ||
## API | ||
**facecrop(input_filename, output_filename, type, quality)** | ||
**facecrop(input_filename, output_filename, type, quality, factor)** | ||
- **input_filename**: Input String containing file name with relative/absolute filepath. | ||
- **output_filename**: Requires a string value which will contains the output file name. | ||
- **output_filename**: (Optional) Requires a string value which will contains the output file name. | ||
- **type**: Requires String value which will tell the format of the output image. | ||
- **type**: (Optional) Requires String value which will tell the format of the output image. | ||
- **quality**: Requires a float value between 0 to 1 which stands for the quality index of the output file compares to the input file. Set 1 for no reduction in quality. | ||
- **quality**: (Optional) Requires a float value between 0 to 1 which stands for the quality index of the output file compares to the input file. Set 1 for no reduction in quality. | ||
- **factor**: (Optional) Pixels by which the area of cropping of the face should be increased to add more details. Use -ve value to decrease. | ||
<!-- ## Defaults --> | ||
## Defaults | ||
- **input_filename**: Mandatory parameter | ||
- **output_filename**: "./output.jpg" | ||
- **type**: 'image/jpeg' | ||
- **quality**: 0.95 | ||
- **factor**: 0 | ||
@@ -68,0 +74,0 @@ |
943327
118
84