162 Commits

Autor SHA1 Mensagem Data
Peter Braden e3b20082ab Merge pull request #98 from hybridgroup/master
Added coffee script examplesand updated HighGUI blockingWaitKey.
2014-02-10 18:06:59 -08:00
Ron Evans fbb030e571 Merge pull request #4 from hybridgroup/face-detection-examples
Face detection examples
2014-01-10 18:47:20 -08:00
Edgar O Silva 1c96622c67 Use recursinve frame reading (instead of time interval) from video feed to try and hit max frames per second. 2014-01-10 16:01:01 -06:00
Edgar O Silva 77a6d19c3b Reading less frames per second avoids the issue of multiple faces detected when only one exists due to the same frame being updated while image detection processing is executed. 2014-01-10 15:59:29 -06:00
Ron Evans e00f24b3e4 Merge pull request #3 from hybridgroup/face-detection
Video feed with face detection example.
2014-01-09 17:43:08 -08:00
Edgar O Silva d75f437b73 Remove commented out code. 2014-01-09 19:15:42 -06:00
Edgar O Silva a6d6be2d7d Video feed with face detection example. 2014-01-09 19:12:03 -06:00
Andrew Stewart 52e03bb7f3 Merge pull request #2 from hybridgroup/examples-waitkey-upd
Added example for video feed applying gaussianBlur and canny edges filte...
2014-01-09 08:47:13 -08:00
Edgar O Silva 9e0367e9f9 Fixed typos in camera examples. 2014-01-08 15:09:04 -06:00
Edgar O Silva 22c86364c7 Added example for video feed applying gaussianBlur and canny edges filter to the video frame feed. Updated typo in camera example. 2014-01-08 14:33:03 -06:00
Andrew Stewart 5a3cc35d25 Merge pull request #1 from hybridgroup/examples-waitkey-upd
Added coffee script examplesand updated HighGUI blockingWaitKey.
2014-01-08 10:14:00 -08:00
Edgar O Silva 73c47177e2 rename examples folder to be more in accordance with the current examples naming convention. 2014-01-08 12:11:49 -06:00
Edgar O Silva fc518a1459 Remove white space name in Coffescript examples folder. 2014-01-08 11:48:15 -06:00
Edgar O Silva db3322ebcd Fix to use always the first param as timeout if only that one was provided while keeping backwards compatability with 2 params. 2014-01-07 20:36:08 -06:00
Edgar O Silva c7ae7140ea Added coffee script examples based on opencv tutorials and updated blockWaitKey function. 2014-01-07 20:28:06 -06:00
Peter Braden 1d9072aefb Merge branch 'master' of github.com:magicode/node-opencv into magicode-master
Conflicts:
	src/Matrix.cc
	src/Matrix.h
2013-12-23 17:22:42 -08:00
Peter Braden 6f9f38112b 0.4.0 2013-12-23 16:09:45 -08:00
Peter Braden f66364f1bb Fix for mavericks / homebrew re #87
Basically just copying solution from https://github.com/mshick/node-protobuf/commit/a071e792065770c9e7372b409d37f295f9473ece

Actually have no idea _why_ this works - assume there's some intricacies with xcode on mavericks.
2013-12-23 16:08:34 -08:00
Peter Braden 0d53c15058 Merge pull request #85 from fastner/fix/tobuffer-options
Add support for options in async toBuffer()
2013-10-09 15:11:59 -07:00
Sebastian Fastner bbf36e72b1 Add parameter support to async buffer generation 2013-10-03 16:32:13 +02:00
Sebastian Fastner b79c30069f Add arguments support for async toBuffer 2013-10-03 16:01:33 +02:00
magicode fddd01a3d1 add pixel function and floodFill function 2013-09-29 21:39:56 +03:00
Peter Braden dd5961cfe2 Merge pull request #72 from eschnou/feature_contour_moments
Compute the moments of a contour
2013-09-05 05:42:58 -07:00
Peter Braden 2c5324df41 Merge pull request #71 from eschnou/fix_motion_track_example
Fixed the motion track example
2013-09-05 05:33:50 -07:00
Laurent Eschenauer 0520e6dcea Compute the moments of a contour
Added a moments method to the contour object and an example
using resulting moments to display a cross at the "center
of gravity" of a contour.
2013-08-27 22:13:22 +02:00
Laurent Eschenauer 612d0f1c21 Fixed the motion track example 2013-08-27 21:46:32 +02:00
Peter Braden 65d9e3ea99 Merge pull request #70 from SergeMv/master
Did several changes and added some new functions
2013-08-25 02:07:25 -07:00
Paul 824ffceeb2 removed unneeded stuff 2013-08-22 23:48:45 +04:00
Paul 5daf9c0f4d Merge branch 'master' of https://github.com/SergeMv/node-opencv 2013-08-22 23:45:11 +04:00
Paul 187b6d073a added some functions: cvtColor, split, merge, equalizeHist 2013-08-22 23:43:41 +04:00
Paul 146925ee6d provided interpolation option for the resize() func 2013-08-22 19:37:08 +04:00
Paul e7300b1cfc added options for toBuffer() func 2013-08-22 19:07:10 +04:00
SergeMv e0c4d42503 Merge pull request #1 from SergeMv/rotate
fixed the rotate() func for angles which are multiple of 90
2013-08-22 06:07:28 -07:00
Paul b2ed603a2a fixed the rotate() func for angles which are multiple of 90 2013-08-22 16:55:32 +04:00
Paul 3105e14f25 implemented copyTo() func 2013-08-22 05:06:58 +04:00
Peter Braden 276e42bffc Merge pull request #63 from timfpark/master
Add absDiff, bitwiseXor, and countNonZero to Matrix operations
2013-07-30 09:51:55 -07:00
Tim Park ce742ecce2 rename test to match combined tests 2013-07-29 13:21:37 -07:00
Tim Park 6bdaa3a24f combine absDiff and countNonZero tests 2013-07-29 13:17:49 -07:00
Peter Braden cceea7b498 Merge pull request #62 from SonicHedgehog/package.json
Enhance package.json
2013-07-29 13:10:03 -07:00
Tim Park d60e3d11d5 add countNonZero to Matrix operations 2013-07-29 12:54:38 -07:00
Tim Park 363b950f1e add tests for bitwiseXor and absDiff 2013-07-29 10:48:44 -07:00
Jakob Krigovsky 813e5ee55f Specify repository url in package.json 2013-07-29 03:30:05 +02:00
Jakob Krigovsky 852de17b47 Specify MIT license in package.json 2013-07-29 03:27:56 +02:00
Jakob Krigovsky a190298eaf Specify necessary node version in package.json correctly 2013-07-29 03:27:05 +02:00
Tim Park 4ce14beb96 Add bitwiseXor and absDiff to Matrix operations 2013-07-28 11:25:01 -07:00
Peter Braden b8ec62e5f8 example of roi 2013-07-26 10:41:13 -07:00
Peter Braden 03a00c062f Merge pull request #59 from penguin359/master
Smoke test now uses portable file path
2013-07-23 10:06:42 -07:00
Peter Braden d9f0b16f16 Merge pull request #60 from carthagan/patch-1
Fix of bindings.gyo for windows
2013-07-23 10:05:03 -07:00
carthagan 7ea1435491 Fix of bindings.gyo for windows
Adding includes in windows BuildMS
2013-07-19 09:20:56 -07:00
Loren M. Lang 13488fa94b Smoke test now uses portable file path
Added a sanity check to ensure smoke.sh is run from the correct folder
and use a relative path to the mona image so it works on any system.
2013-07-17 22:26:16 -07:00
Peter Braden 85e1ce2448 0.3.1 2013-07-17 15:48:12 -07:00
Peter Braden 3b4c361f5c Merge pull request #57 from magicode/master
fix issues #3
2013-07-17 15:46:07 -07:00
magicode 5eb7e836c3 fix issues #3 2013-07-17 08:00:12 +03:00
Peter Braden abb20798c3 0.3.0 2013-06-19 11:27:12 -07:00
Peter Braden 7548d39616 Merge branch 'master' of github.com:peterbraden/node-opencv
Conflicts:
	src/Matrix.cc
	src/Matrix.h
2013-06-19 11:26:56 -07:00
Peter Braden 762ac42f3b 0.2.0 2013-06-19 11:23:24 -07:00
Peter Braden 45846cd3b2 Open Source Bridge Live coding - woohoo 2013-06-19 11:21:59 -07:00
Peter Braden 27f722e6aa Merge pull request #54 from smoodiver/master
Examples, added err argument to callback functions where missing
2013-06-09 16:22:24 -07:00
Ray Smoodiver 1e5a0f2a23 Added err arguments
Added err arguments to callback functions
2013-06-09 18:19:06 +12:00
Ray Smoodiver 4cc5eff25b Added err arguments
OpenCV functions now seem to return (err, val) style arguments. Updated example to handle
2013-06-09 18:16:03 +12:00
Peter Braden ca87972037 test it 2013-05-16 19:02:52 -07:00
Peter Braden bae7a1bfd9 threshold 2013-05-16 18:57:26 -07:00
Peter Braden c93cfb782b Merge pull request #50 from gluxon/master
Use GitHub Flavored Markdown for JavaScript code and bash
2013-05-14 09:20:01 -07:00
Brandon Cheng bce9d95c29 use github flavored markdown for javascript and bash 2013-05-13 17:00:42 -04:00
Peter Braden 25bec10b28 Merge pull request #49 from nolith/meanStdDev
meanStdDev for Matrix
2013-05-09 10:02:43 -07:00
Alessio Caiazza f5df8f6599 meanStdDev for Matrix 2013-05-09 18:03:38 +02:00
Peter Braden f6ff1e58b5 Merge pull request #48 from mattholl/master
Just fixed a tiny issue where err wasn't passed as the first argument to read()
2013-05-07 15:16:21 -07:00
mattholl e507377a80 fixed tiny issue where err is missing as the first argument to read from a video stream 2013-05-07 19:37:07 +01:00
Peter Braden aa7b3317fe Merge pull request #46 from RNELord/master
Matrix::flip, Matrix::ROI, Matrix::rotate
2013-05-01 13:07:53 -07:00
Peter Braden 769d6ebf77 v0.1.0 2013-05-01 11:53:17 -07:00
Peter Braden 21917f3f17 Merge branch 'master' of github.com:peterbraden/node-opencv 2013-05-01 11:49:50 -07:00
Ryan Lord 7b3835bbf5 Matrix::rotate bind using cv::warpAffine 2013-05-01 14:12:30 +01:00
Ryan Lord c3d1379cd5 Added ROI bindings to Matrix 2013-05-01 11:50:37 +01:00
Ryan Lord c4a20bb279 Made exception from ::flip throw a type error 2013-05-01 02:18:55 +01:00
Ryan Lord cca52ad691 Added cv::flip function to Matrix objects 2013-05-01 02:10:27 +01:00
Peter Braden 67abbf4c24 Merge pull request #45 from shykes/dockerfile
Build instructions for docker
2013-04-23 10:26:37 -07:00
Solomon Hykes d364f64b84 Added a Dockerfile describing how to build node-opencv and all its dependencies into a ready-to-use linux container 2013-04-21 11:35:29 -07:00
Peter Braden 440a72c38e Merge branch 'master' of github.com:peterbraden/node-opencv into beta 2013-04-09 21:34:41 -07:00
Peter Braden 865962c845 videocapture read now uses err, im convention 2013-04-09 21:34:00 -07:00
Peter Braden a347ab682e add adjustROI 2013-04-06 18:34:08 -07:00
Peter Braden f1d629bfb3 Merge pull request #43 from carter-thaxton/master
Add async save method
2013-03-28 10:21:40 -07:00
Carter Thaxton 507ecbf832 Add async save, triggering off existence of callback 2013-03-28 01:01:55 -07:00
Peter Braden f0461db126 Merge pull request #42 from mrnugget/patch-1
Fix travis.yml to run with correct Node.js version
2013-03-25 10:55:31 -07:00
Thorsten Ball 3c6028e0e3 Fix travis.yml to run with correct Node.js version
This changes the `.travis.yml` to use the correct Node.js version
by using strings as version numbers.

Relevant Travis CI documentation page: http://about.travis-ci.org/docs/user/languages/javascript-with-nodejs/#Choosing-Node-versions-to-test-against

Without using strings to specify the desired versions Travis CI
runs on Node.js 0.1 instead of 0.10.
2013-03-25 10:49:20 +01:00
Peter Braden 95b2585838 Merge branch 'master' of github.com:peterbraden/node-opencv 2013-03-19 17:18:49 -07:00
Peter Braden 289c519362 add 0.10 to tests 2013-03-19 16:54:54 -07:00
Peter Braden 1d542bc056 Cast cb for node 0.10 2013-03-19 16:53:50 -07:00
Peter Braden 76f3847321 get mat etc 2013-03-15 15:28:58 -07:00
Peter Braden 8e55b380cd add updateSync 2013-03-15 15:07:16 -07:00
Peter Braden 0efbd11d0c Constructors for other algorithms 2013-03-15 14:48:43 -07:00
Peter Braden b8ce5d0def Correct basic case with feedback from jraadt 2013-03-15 13:55:01 -07:00
Peter Braden 053a693c9a Basic version of Face recognition working 2013-03-13 18:08:05 -07:00
Peter Braden 64f933f2a9 WIP on face recognition 2013-03-13 17:42:05 -07:00
Peter Braden b17fceca72 Initial work on face recognition using the FaceRecognizer class from opencv 2.4.4 2013-03-13 16:15:29 -07:00
Peter Braden e5be89c813 Merge pull request #40 from jraadt/master
Fixed pausing a video stream.
2013-03-12 21:43:41 -07:00
Jeremy Raadt fd25b58e43 Fixed an invalid reference to this for pausing a video stream. 2013-03-12 23:34:58 -05:00
Peter Braden ebd1f6e4e8 Merge branch 'waitkey' into beta 2013-03-11 15:41:58 -07:00
Peter Braden e88d2d6b8a Blocking waitKey for development 2013-03-11 15:41:36 -07:00
Peter Braden daca1a14cb PyrDown / PyrUp 2013-03-05 11:28:37 -08:00
Peter Braden 11db468dcf v0.0.12 2013-03-05 11:19:25 -08:00
Peter Braden 55cbf0a37f add matrix clone 2013-03-04 12:03:35 -08:00
Peter Braden 77279a33c0 Add basic highgui window support 2013-03-04 11:12:33 -08:00
Peter Braden 6225a3c0f0 add keywords to package.json 2013-02-28 18:14:37 -08:00
Peter Braden f2ec2cd3ed Allow video capture to be streamed 2013-02-26 19:07:39 -08:00
Peter Braden c3d3f0f4b4 beta 0.0.11 2013-02-26 17:23:19 -08:00
Peter Braden 0840e0b2e2 Merge branch 'provide-cascades' into beta
Conflicts:
	lib/opencv.js
2013-02-26 16:52:36 -08:00
Peter Braden 4ca165635e provide image to event 2013-02-26 16:51:45 -08:00
Peter Braden a8e5ac4b6b Fix path 2013-02-26 16:27:34 -08:00
Peter Braden 24f255a161 unit test for imagestream 2013-02-26 16:23:14 -08:00
Peter Braden 0bb7fe9918 Add shortcut for face cascade file -> cv.FACE_CASCADE 2013-02-26 15:34:27 -08:00
Peter Braden 0cb436e930 Changing ImageStream -> ImageDataStream and creating ImageStream.
To pipe data into an image matrix, you now use ImageDataStream.

ImageStream is now a stream that transforms image buffers into matrices.
2013-02-26 15:26:54 -08:00
Peter Braden 3a7469fe52 catch older versions in build step 2013-02-26 15:00:29 -08:00
Peter Braden e1e1267bc3 Merge pull request #37 from ryansouza/node-08
Have travis test against node 0.8 as well
2013-02-26 10:43:49 -08:00
Peter Braden 32a1b76852 Merge pull request #36 from ryansouza/contour-stuff
Include more info about working with contours
2013-02-26 10:43:30 -08:00
Ryan Souza a320ff9af0 Have travis test against node 0.8 as well 2013-02-25 23:06:21 -08:00
Ryan Souza 521139a76e Include more info about working with contours
Some readme examples for using functions on a Contours object
Examples detecting and playing with simple shapes and contours
2013-02-25 22:58:14 -08:00
Peter Braden 454fd1188a s/cols,rows/rows,cols/g re #30 2013-02-13 13:30:31 -08:00
Peter Braden 0de039956e Clarify width, height params re #30 2013-02-12 05:24:50 -08:00
Peter Braden bb1fa037f3 Merge pull request #34 from mintplant/contours
Contours expansion: minAreaRect and convexHull bindings, expose underlying point data
2013-02-11 12:18:16 -08:00
Michael Smith 84e5f255df Add ConvexHull binding for Contours class 2013-02-10 15:26:58 -08:00
Michael Smith 4f7968e567 Expose MinAreaRect binding for Contours 2013-02-10 15:25:26 -08:00
Michael Smith a197586673 Expose point data from Contours
Add in a Point method to the Contours class to access the underlying
point coordinates from the JavaScript side.
2013-02-10 15:04:37 -08:00
Peter Braden e64b558bbd v0.0.10 2013-02-05 14:39:19 -08:00
Peter Braden c057d411a5 Remove todo - that's what github issues are for 2013-02-05 14:27:46 -08:00
Peter Braden fb55cec501 Merge pull request #29 from jtlebi/master
New bindings
2013-02-05 14:25:55 -08:00
Peter Braden be92fe5e65 Strip trailing spaces in matrix.cc re #29 2013-02-05 14:24:05 -08:00
Peter Braden 642f111f9d Merge branch 'master' of github.com:peterbraden/node-opencv 2013-02-05 14:21:35 -08:00
Peter Braden 8d6180bcaf Merge pull request #26 from prabirshrestha/buffers
fixed require('buffers')
2013-02-04 09:00:34 -08:00
Peter Braden 63891ae4fa Merge pull request #31 from gluxon/master
Add bindings for inRange
2013-02-03 11:01:33 -08:00
Brandon Cheng 22bdf646b1 Add bindings for cv::inRange 2013-01-27 18:16:30 -05:00
Jean-Tiare LE BIGOT 3b3c591517 add bindings for boundingBox in contours --> returns an (x, y, width, height) object 2013-01-20 15:39:51 +01:00
Jean-Tiare LE BIGOT abf5e9948c add bindings for cornerCount (size in OpenCV) in contours + fix bool instead of double in approxPolyDP 2013-01-20 15:07:20 +01:00
Jean-Tiare LE BIGOT d2e8b1969f add bindings for isConvex in contours 2013-01-20 14:20:33 +01:00
Jean-Tiare LE BIGOT e3280ddc1e add bindings for approxPolyDP in contours 2013-01-20 14:16:16 +01:00
Jean-Tiare LE BIGOT a94bc32d5f add bindings for arcLength in contours 2013-01-20 14:02:48 +01:00
Jean-Tiare LE BIGOT 7be98efacf add bindings for gaussianBlur 2013-01-20 01:05:43 +01:00
Jean-Tiare LE BIGOT b73ccb67fa add bindings for 'erode' 2013-01-19 23:28:54 +01:00
prabirshrestha 3efe469ea0 fixed require('buffers') 2012-12-03 13:34:50 -05:00
Peter Braden 8b899d073a don't save images in example 2012-11-29 13:44:31 -08:00
Peter Braden 2d0e747a4d Getting rid of old build script 2012-11-27 17:13:57 -08:00
Peter Braden 644f6797d3 Merge branch 'camshift' 2012-11-27 17:09:18 -08:00
Peter Braden f90cea5ffd std::vector, explicitly 2012-11-27 16:54:29 -08:00
Peter Braden 4f56834420 correct import. Linux is way whinier about this sort of stuff. 2012-11-27 16:52:05 -08:00
Peter Braden ab686c5445 specify std::dtring 2012-11-27 16:48:20 -08:00
Peter Braden dcf7462b13 travis is puking again 2012-11-27 16:42:33 -08:00
Peter Braden 7d43360b72 fix unit test 2012-11-27 16:36:18 -08:00
Peter Braden 20fa7a1c51 ignore out jpgs and examples avi's - too big for repos and test output 2012-11-27 16:15:31 -08:00
Peter Braden 0ab26f913c WIP 2012-11-27 16:13:23 -08:00
Peter Braden c4aac1d201 Allow specifying which image channel to use for the back projection 2012-11-27 16:08:58 -08:00
Peter Braden 6df8bbbb9b WIP on camshift re #22 - Got a working example but still unreliable
This is a combination of 4 commits.
WIP on camshift - need to focus the histogram on the ROI

Weird fringing issue, but otherwise tracking objects successfully

motion track example

WIP on camshift

WIP on camshift - have a smoke example, but bad results are coming back.
2012-11-26 20:11:59 -08:00
Peter Braden 33146b15e0 stubbing test for multiple imports bug 2012-11-19 12:39:49 -08:00
Contra c50cdf35a4 allow thickness and color args for ellipse 2012-11-19 12:15:59 -08:00
Peter Braden fa6e6b4da1 poitential fix for null pointer error. Test still screwed though. 2012-11-19 12:14:18 -08:00
Peter Braden b6468cff4e 0.0.9 2012-11-12 13:33:53 -08:00
Peter Braden e33afd97ef WIP on TrackedObject re #22 2012-11-12 13:30:26 -08:00
Peter Braden a9717c7dc0 WIP on camshift re #22 2012-11-12 10:54:37 -08:00
Peter Braden b5fe027703 setting up trackedobject 2012-11-09 17:29:54 -08:00
Peter Braden 3a1477c527 WIP on CamShift with TrackedObject re #22 2012-11-09 16:48:31 -08:00
Peter Braden e4c0ddd4e4 changelog 2012-11-09 10:29:46 -08:00
Peter Braden d71b0ae7b3 if toBuffer has a cb, run it async. re #21 2012-11-09 10:21:41 -08:00
Peter Braden ac6c685b56 Fix async toBufffer test 2012-10-29 23:48:12 -07:00
Peter Braden 56fd1824d3 WIP on an async toBuffer re #21 2012-10-29 23:10:34 -07:00
54 arquivos alterados com 28977 adições e 271 exclusões
+3 -1
Ver Arquivo
@@ -3,4 +3,6 @@ build
.DS_Store
node_modules
npm-debug.log
out.jpg
out*.jpg
out*.png
examples/*.avi
+4 -1
Ver Arquivo
@@ -1,8 +1,11 @@
language: node_js
node_js:
- 0.6
- "0.6"
- "0.8"
- "0.10"
before_install:
- sudo apt-get update
- sudo apt-get install libcv-dev
- sudo apt-get install libopencv-dev
- sudo apt-get install libhighgui-dev
+18
Ver Arquivo
@@ -0,0 +1,18 @@
# This file describes how to build node-opencv into a runnable linux container with all dependencies installed
# To build:
# 1) Install docker (http://docker.io)
# 2) Build: wget https://raw.github.com/dotcloud/docker/v0.1.6/contrib/docker-build/docker-build && python docker-build $USER/node-opencv < Dockerfile
# 3) Test: docker run $USER/node-opencv node -e "console.log(require('opencv').version)"
#
# VERSION 0.1
# DOCKER-VERSION 0.1.6
from ubuntu:12.04
run echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
run apt-get update
run apt-get install -q -y libcv-dev
run apt-get install -q -y libopencv-dev
run apt-get install -q -y libhighgui-dev
run apt-get install wget
run wget -O - http://nodejs.org/dist/v0.8.23/node-v0.8.23-linux-x64.tar.gz | tar -C /usr/local/ --strip-components=1 -zxv
run npm install opencv
+163 -52
Ver Arquivo
@@ -13,31 +13,31 @@ You'll need OpenCV 2.3.1 installed.
Then:
npm install opencv
```bash
$ npm install opencv
```
Or to build the repo:
node-gyp rebuild
```bash
$ node-gyp rebuild
```
## Examples
### Face Detection
cv.readImage("./examples/test.jpg", function(err, im){
im.detectObject("./data/haarcascade_frontalface_alt.xml", {}, function(err, faces){
for (var i=0;i<faces.length; i++){
var x = faces[i]
im.ellipse(x.x + x.width/2, x.y + x.height/2, x.width/2, x.height/2);
}
im.save('./out.jpg');
});
})
```javascript
cv.readImage("./examples/test.jpg", function(err, im){
im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){
for (var i=0;i<faces.length; i++){
var x = faces[i]
im.ellipse(x.x + x.width/2, x.y + x.height/2, x.width/2, x.height/2);
}
im.save('./out.jpg');
});
})
```
## API Documentation
@@ -49,60 +49,95 @@ base datastructure in OpenCV. Things like images are just matrices of pixels.
#### Creation
new Matrix(width, height)
```javascript
new Matrix(rows, cols)
```
Or if you're thinking of a Matrix as an image:
```javascript
new Matrix(height, width)
```
Or you can use opencv to read in image files. Supported formats are in the OpenCV docs, but jpgs etc are supported.
cv.readImage(filename, function(mat){
...
})
```javascript
cv.readImage(filename, function(mat){
...
})
cv.readImage(buffer, function(mat){
...
})
cv.readImage(buffer, function(mat){
...
})
```
If you need to pipe data into an image, you can use an imagestream:
If you need to pipe data into an image, you can use an ImageDataStream:
var s = new cv.ImageStream()
```javascript
var s = new cv.ImageDataStream()
s.on('load', function(matrix){
...
})
fs.createReadStream('./examples/test.jpg').pipe(s);
```
If however, you have a series of images, and you wish to stream them into a
stream of Matrices, you can use an ImageStream. Thus:
```javascript
var s = new cv.ImageStream()
s.on('data', function(matrix){
...
})
ardrone.createPngStream().pipe(s);
```
Note: Each 'data' event into the ImageStream should be a complete image buffer.
s.on('load', function(matrix){
...
})
fs.createReadStream('./examples/test.jpg').pipe(s);
#### Accessing Data
var mat = new cv.Matrix.Eye(4,4); // Create identity matrix
```javascript
var mat = new cv.Matrix.Eye(4,4); // Create identity matrix
mat.get(0,0) // 1
mat.row(0) // [1,0,0,0]
mat.col(4) // [0,0,0,1]
mat.get(0,0) // 1
mat.row(0) // [1,0,0,0]
mat.col(4) // [0,0,0,1]
```
##### Save
mat.save('./pic.jpg')
```javascript
mat.save('./pic.jpg')
```
or:
var buff = mat.toBuffer()
```javascript
var buff = mat.toBuffer()
```
#### Image Processing
im.convertGrayscale()
im.canny(5, 300)
im.houghLinesP()
```javascript
im.convertGrayscale()
im.canny(5, 300)
im.houghLinesP()
```
#### Simple Drawing
im.ellipse(x, y)
im.line([x1,y1], [x2, y2])
```javascript
im.ellipse(x, y)
im.line([x1,y1], [x2, y2])
```
#### Object Detection
@@ -110,22 +145,98 @@ There is a shortcut method for
[Viola-Jones Haar Cascade](http://www.cognotics.com/opencv/servo_2007_series/part_2/sidebar.html) object
detection. This can be used for face detection etc.
```javascript
mat.detectObject(haar_cascade_xml, opts, function(err, matches){})
```
mat.detectObject(haar_cascade_xml, opts, function(err, matches){})
For convenience in face recognition, cv.FACE_CASCADE is a cascade that can be used for frontal face recognition.
Also:
mat.goodFeaturesToTrack
```javascript
mat.goodFeaturesToTrack
```
#### Contours
mat.findCountours
mat.drawContour
mat.drawAllContours
```javascript
mat.findCountours
mat.drawContour
mat.drawAllContours
```
### Using Contours
`findContours` returns a `Contours` collection object, not a native array. This object provides
functions for accessing, computing with, and altering the contours contained in it.
See [relevant source code](src/Contours.cc) and [examples](examples/)
```javascript
var contours = im.findContours;
# Count of contours in the Contours object
contours.size();
# Count of corners(verticies) of contour `index`
contours.cornerCount(index);
# Access vertex data of contours
for(var c = 0; c < contours.size(); ++c) {
console.log("Contour " + c);
for(var i = 0; i < contours.cornerCount(c); ++i) {
var point = contours.point(c, i);
console.log("(" + point.x + "," + point.y + ")");"
}
}
# Computations of contour `index`
contours.area(index);
contours.arcLength(index, isClosed);
contours.boundingRect(index);
contours.minAreaRect(index);
contours.isConvex(index);
# Destructively alter contour `index`
contours.approxPolyDP(index, epsilon, isClosed);
contours.convexHull(index, clockwise);
```
## MIT License
The library is distributed under the MIT License - if for some reason that
doesn't work for you please get in touch.
## Changelog
#### 0.0.13
- V Early support for face recognition - API is _likely_ to change. Have fun!
- *API Change*: VideoCapture.read now calls callback(err, im) instead of callback(im)
#### 0.0.12
- Matrix clone()
- NamedWindow Support
#### 0.0.11
- Bug Fixes
- ImageStream becomes ImageDataStream, and new ImageStream allows multiple images to be
streamed as matrices, for example, with an object detection stream.
- @ryansouza improved documentation
- Correcting matrix constructor (thanks @gluxon)
- @Michael Smith expanded Contours functionality.
Thanks all!
#### 0.0.10
- Bug Fixes
- @Contra added code that allows thickness and color args for ellipse
- Camshift Support
- @jtlebi added bindings for erode, gaussianBlur, arcLength, approxPolyDP, isConvex, cornerCount
- @gluxon added bindings for inRange
Thanks everyone!
#### 0.0.9
- toBuffer can now take a callback and be run async (re #21)
-45
Ver Arquivo
@@ -1,45 +0,0 @@
im.calcHistograms(function(err, hist){})
im.calcHistograms(mask, function(err, hist){})
## Face recognition TODO
// Load Database
// TODO<
cv.loadImage('test.jpg', function(err, im){
im.detectObject("front-face.xml", {}, function(err, faces){
_.each(faces, function(v){
// TODO {
var section = im.slice(v.x, v.y, v.x + v.width, v.y + v.height);
section.convertGrayscale()
section.resize(WID, HEIGHT);
section.equaliseHistogram();
// } TODO
})
})
})
-----
http://www.athile.net/library/wiki/index.php?title=Library/V8/Tutorial#Wrapping_a_Javascript_function_as_a_std::function.3C.3E
https://www.cloudkick.com/blog/2010/aug/23/writing-nodejs-native-extensions/
+13 -1
Ver Arquivo
@@ -9,12 +9,21 @@
, "src/Contours.cc"
, "src/Point.cc"
, "src/VideoCaptureWrap.cc"
, "src/CamShift.cc"
, "src/HighGUI.cc"
, "src/FaceRecognizer.cc"
]
, 'libraries': [
'<!@(pkg-config --libs opencv)'
]
# For windows
,'include_dirs': [
'<!@(pkg-config --cflags opencv)'
]
, 'cflags': [
'<!@(pkg-config --cflags --libs opencv)'
'<!@(pkg-config --cflags "opencv >= 2.3.1" )'
, '-Wall'
]
, 'cflags!' : [ '-fno-exceptions']
@@ -24,6 +33,9 @@
# cflags on OS X are stupid and have to be defined like this
'xcode_settings': {
'OTHER_CFLAGS': [
"-mmacosx-version-min=10.7",
"-std=c++11",
"-stdlib=libc++",
'<!@(pkg-config --cflags opencv)'
]
, "GCC_ENABLE_CPP_RTTI": "YES"
-6
Ver Arquivo
@@ -1,6 +0,0 @@
#!/bin/bash
node-gyp rebuild &&
cd examples &&
#node face_detection.js
node $1
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@ var camera = new cv.VideoCapture(0);
setInterval(function() {
camera.read(function(im) {
camera.read(function(err, im) {
im.save('/tmp/cam.png');
});
+31
Ver Arquivo
@@ -0,0 +1,31 @@
cv = require 'opencv'
# we create a function helper to display the images.
displayImage = (windowName, img) ->
namedWindow = new cv.NamedWindow(windowName)
namedWindow.show(img)
namedWindow.blockingWaitKey(0, 5000)
# Load both sources to be blended
cv.readImage("./images/windows-logo.png", (err, src1) ->
# Display Source 1
displayImage('Source 1', src1)
# Load source #2
cv.readImage("./images/linux-logo.png", (err, src2) ->
# Display Source 2
displayImage('Source 2', src2)
# We use the addWeighted opencv wrapper to blend the images.
# we need to use a different image object, since src1 and src2
# will be manipulated.
result = new cv.Matrix(src1.width(), src2.height())
result.addWeighted(src1, 0.7, src2, 0.9)
result.save("./tmp/blended.png")
# Display Blended result 2
displayImage('Blended', result)
)
)
@@ -0,0 +1,56 @@
cv = require 'opencv'
# First we create a new VideoCapture object to get
# video from the camera (0 for default camera)
camera = new cv.VideoCapture(1)
# we create a window to display the Video frames
namedWindow = new cv.NamedWindow('Video', 0)
color = [255,0,0]
frameRead = () ->
# camera.read allows us to retrieve the current
# frame to be displayed in the video window.
camera.read((err, im) ->
# We can check for errors and even break the
# program execution if an error is detected here.
console.log "The err ==>#{ err }" if err
# There is no need to display the image width or Height
# but I leave this here in case anyone needs to check them.
#console.log("Width: #{im.width()}")
#console.log("height: #{im.height()}")
# Before working with the frame we need to check the image
# is already available and has a width and height greater than 0,
# otherwise it will fail when trying to do namedWindow.show()
# and the image has width or height equal or less than 0.
if im.width() > 0 and im.height() > 0
#console.log("Interval ID => #{ intervalId }")
#console.log(intervalId)
clearInterval(intervalId) if intervalId?
im.detectObject('./haarcascades/haarcascade_frontalface_alt.xml', {}, (err, faces) ->
for face in faces
im.rectangle([face.x, face.y], [face.x + face.width, face.y + face.height], [0,255,0], 2)
# We use the previously created namedWindow to display the
# video frame to wich we applied the blur and filter.
namedWindow.show(im)
# Finally we get the key pressed on the window to terminate
# execution of the program.
res = namedWindow.blockingWaitKey(0, 20)
# In this case we terminate the program if any key is pressed.
#if res >= 0 then do not set a new timeout to get a new frame.
setTimeout(frameRead, 5) if res < 0
)
)
# We set an interval to retrieve frames from the
# video source and we get the intervalId so we can
# stop the program by pressing any key on the video feed window.
intervalId = setInterval(() ->
frameRead(intervalId)
, 100)
@@ -0,0 +1,49 @@
cv = require 'opencv'
# First we create a new VideoCapture object to get
# video from the camera (0 for default camera)
camera = new cv.VideoCapture(1)
# we create a window to display the Video frames
namedWindow = new cv.NamedWindow('Video',1)
color = [255,0,0]
# We set an interval to retrieve frames from the
# video source and we get the intervalId so we can
# stop the program from the video feed window.
intervalId = setInterval(()->
# camera.read allows us to retrieve the current
# frame to be displayed in the video window.
camera.read((err, im) ->
# We can check for errors and even break the
# program execution if an error is detected here.
console.log "The err ==>#{ err }" if err
# There is no need to display the image width or Height
# but I leave this here in case anyone needs to check them.
#console.log("Width: #{im.width()}")
#console.log("height: #{im.height()}")
# Before working with the frame we need to check the image
# is already available and has a width and height greater than 0,
# otherwise it will fail when trying to do namedWindow.show()
# and the image has width or height equal or less than 0.
if im.width() > 0 and im.height() > 0
im.detectObject('./haarcascades/haarcascade_frontalface_alt.xml', {}, (err, faces) ->
for face in faces
im.rectangle([face.x, face.y], [face.x + face.width, face.y + face.height], [0,255,0], 2)
# We use the previously created namedWindow to display the
# video frame to wich we applied the blur and filter.
namedWindow.show(im)
)
# Finally we get the key pressed on the window to terminate
# execution of the program.
res = namedWindow.blockingWaitKey(0, 50)
# In this case I terminate the program if any key is pressed.
if res >= 0 then clearInterval(intervalId)
)
, 150)
@@ -0,0 +1,58 @@
cv = require 'opencv'
# First we create a new VideoCapture object to get
# video from the camera (0 for default camera)
camera = new cv.VideoCapture(1)
# we create a window to display the Video frames
namedWindow = new cv.NamedWindow('Video',1)
# We set an interval to retrieve frames from the
# video source and we get the intervalId so we can
# stop the program from the video feed window.
intervalId = setInterval(()->
# camera.read allows us to retrieve the current
# frame to be displayed in the video window.
camera.read((err, im) ->
# We can check for errors and even break the
# program execution if an error is detected here.
console.log "The err ==>#{ err }" if err
# There is no need to display the image width or Height
# but I leave this here in case anyone needs to check them.
#console.log("Width: #{im.width()}")
#console.log("height: #{im.height()}")
# Before working with the frame we need to check the image
# is already available and has a width and height greater than 0,
# otherwise it will fail when trying to do namedWindow.show()
# and the image has width or height equal or less than 0.
if im.width() > 0 and im.height() > 0
# We apply filters and effects to the frame we got from the
# camera to manipulate the video that we'll display.
# First we convert to grayscale.
im.convertGrayscale()
# We then apply GaussianBlur.
# It takes an array of type double and size 2
# that indicates how strong the gaussian blur should be.
im.gaussianBlur([7,7])
# We then apply canny edge filtering.
# Params are lower and higher threshold and aperture size,
# although nodejs-opencv overwrite the aperture size param
# with 0. An update to consider it is needed.
im.canny(0, 30, 3)
# We use the previously created namedWindow to display the
# video frame to wich we applied the blur and filter.
namedWindow.show(im)
# Finally we get the key pressed on the window to terminate
# execution of the program.
res = namedWindow.blockingWaitKey(0, 20)
console.log("KEYPRESSED => #{ res } ")
# In this case I terminate the program if any key is pressed.
if res >= 0 then clearInterval(intervalId)
)
, 50)
@@ -0,0 +1,57 @@
cv = require 'opencv'
# First we create a new VideoCapture object to get
# video from the camera (0 for default camera)
camera = new cv.VideoCapture(1)
# we create a window to display the Video frames
namedWindow = new cv.NamedWindow('Video',1)
# We set an interval to retrieve frames from the
# video source and we get the intervalId so we can
# stop the program from the video feed window.
intervalId = setInterval(()->
# camera.read allows us to retrieve the current
# frame to be displayed in the video window.
camera.read((err, im) ->
# We can check for errors and even break the
# program execution if an error is detected here.
console.log "The err ==>#{ err }" if err
# There is no need to display the image width or Height
# but I leave this here in case anyone needs to check them.
#console.log("Width: #{im.width()}")
#console.log("height: #{im.height()}")
# Before working with the frame we need to check the image
# is already available and has a width and height greater than 0,
# otherwise it will fail when trying to do namedWindow.show()
# and the image has width or height equal or less than 0.
if im.width() > 0 and im.height() > 0
# We apply filters and effects to the frame we got from the
# camera to manipulate the video that we'll display.
# First we convert to grayscale.
im.convertGrayscale()
# We then apply GaussianBlur.
# It takes an array of type double and size 2
# that indicates how strong the gaussian blur should be.
im.gaussianBlur([7,7])
# We then apply canny edge filtering.
# Params are lower and higher threshold and aperture size,
# although nodejs-opencv overwrite the aperture size param
# with 0. An update to consider it is needed.
im.canny(0, 30, 3)
# We use the previously created namedWindow to display the
# video frame to wich we applied the blur and filter.
namedWindow.show(im)
# Finally we get the key pressed on the window to terminate
# execution of the program.
res = namedWindow.blockingWaitKey(0, 20)
# In this case I terminate the program if any key is pressed.
if res >= 0 then clearInterval(intervalId)
)
, 50)
+41
Ver Arquivo
@@ -0,0 +1,41 @@
cv = require 'opencv'
# First we create a new VideoCapture object to get
# video from the camera (0 for default camera)
camera = new cv.VideoCapture(1)
# we create a window to display the Video frames
namedWindow = new cv.NamedWindow('Video',1)
# We set an interval to retrieve frames from the
# video source and we get the intervalId so we can
# stop the program from the video feed window.
intervalId = setInterval(()->
# camera.read allows us to retrieve the current
# frame to be displayed in the video window.
camera.read((err, im) ->
# We can check for errors and even break the
# program execution if an error is detected here.
console.log "The err ==>#{ err }" if err
# There is no need to display the image width or Height
# but I leave this here in case anyone needs to check them.
#console.log("Width: #{im.width()}")
#console.log("height: #{im.height()}")
# We use the previously created namedWindow to display the
# video feed frame, we need to check the image is already
# available and has a width and height greater than 0,
# otherwise namedWindow.show() will fail if any of those is 0.
namedWindow.show(im) if im.width() > 0 and im.height() > 0
# Finally we get the key pressed on the window to terminate
# execution of the program.
res = namedWindow.blockingWaitKey(0, 20)
console.log("KEYPRESSED => #{ res } ")
# In this case I terminate the program if any key is pressed.
if res >= 0 then clearInterval(intervalId)
)
, 500)
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
@@ -0,0 +1,29 @@
cv = require('opencv')
cv.readImage("./images/mona.png", (err, im) ->
# Create new NamedWindow object to hold the image
# NamedWindow takes two arguments String WindowName and String windowSize
namedWindow = new cv.NamedWindow('Display Window', '400x400')
# We add a couple of basic shapes to the image, just to show how
# to create basic shapes.
# im.rectangle([startX, StartY], [width, height], color(array of RGB)
im.rectangle([50, 50], [200, 200], [0, 255, 0], 2)
# im.ellipse(centerX, centerY, width, height, color(array of RGB)
im.ellipse(150, 150, 50, 50, [255, 255, 0], 2)
# We then tell the image to show the image we loaded.
namedWindow.show(im)
console.log("Image should be displayed inside a window.")
# Finally we tell the NamedWindow to wait for any key being pressed to close
# itself (by passing a 0 as the first param, or wait a defined amount of time
# by passing the time as a second argument (in milliseconds)
#
# If we do not tell the window to wait it will just load and show the image
# and close so fast that it will appear nothing happened.
namedWindow.blockingWaitKey(0, 5000)
console.log("And the window should close automatically or by pressing any key on it.")
)
@@ -0,0 +1,22 @@
cv = require('opencv')
cv.readImage("./images/mona.png", (err, im) ->
# Create new NamedWindow object to hold the image
# NamedWindow takes two arguments String WindowName and String windowSize
namedWindow = new cv.NamedWindow('Display Window', '400x400')
# We then tell the image to show the image we loaded.
namedWindow.show(im)
console.log("Image should be displayed inside a window.")
# Finally we tell the NamedWindow to wait for any key being pressed to close
# itself (by passing a 0 as the first param, or wait a defined amount of time
# by passing the time as a second argument (in milliseconds)
#
# If we do not tell the window to wait it will just load and show the image
# and close so fast that it will appear nothing happened.
namedWindow.blockingWaitKey(0, 5000)
console.log("And the window should close automatically or by pressing any key on it.")
)
@@ -0,0 +1,28 @@
cv = require('opencv')
cv.readImage("./images/windows-logo.png", (err, im) ->
# The nodejs-opencv has some shortcodes for image manipulation.
# We modify the image using the handy function im.convertGrayscale()
# This will overwrite the current image with a grayscaled version.
im.convertGrayscale()
# Create new NamedWindow object to hold the image
# NamedWindow takes two arguments String WindowName and String windowSize
namedWindow = new cv.NamedWindow('Display Window', '400x400')
# We then tell the image to show the image we loaded.
namedWindow.show(im)
console.log("Image should be displayed inside a window.")
# Finally we tell the NamedWindow to wait for any key being pressed to close
# itself (by passing a 0 as the first param, or wait a defined amount of time
# by passing the time as a second argument (in milliseconds)
#
# If we do not tell the window to wait it will just load and show the image
# and close so fast that it will appear nothing happened.
namedWindow.blockingWaitKey(0, 5000)
console.log("And the window should close automatically or by pressing any key on it.")
)
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 17 KiB

BIN
Ver Arquivo
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 518 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 50 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 9.4 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 13 KiB

+12
Ver Arquivo
@@ -0,0 +1,12 @@
var cv = require('../lib/opencv');
// (B)lue, (G)reen, (R)ed
var lower_threshold = [46, 57, 83];
var upper_threshold = [80, 96, 115];
cv.readImage('./coin1.jpg', function(err, im) {
im.inRange(lower_threshold, upper_threshold);
im.save('./coin_detected.jpg');
});
+6 -1
Ver Arquivo
@@ -7,7 +7,7 @@ var maxArea = 2500;
var GREEN = [0, 255, 0]; //B, G, R
var WHITE = [255, 255, 255]; //B, G, R
var RED = [0, 0, 255]; //B, G, R
cv.readImage('./stuff.png', function(err, im) {
@@ -24,7 +24,12 @@ cv.readImage('./stuff.png', function(err, im) {
for(i = 0; i < contours.size(); i++) {
if(contours.area(i) > maxArea) {
var moments = contours.moments(i);
var cgx = Math.round(moments.m10/moments.m00);
var cgy = Math.round(moments.m01/moments.m00);
big.drawContour(contours, i, GREEN);
big.line([cgx - 5, cgy], [cgx + 5, cgy], RED);
big.line([cgx, cgy - 5], [cgx, cgy + 5], RED);
}
}
Arquivo executável
+52
Ver Arquivo
@@ -0,0 +1,52 @@
#!/usr/bin/env node
//
// Detects triangles and quadrilaterals
//
var cv = require('../lib/opencv');
var lowThresh = 0;
var highThresh = 100;
var nIters = 2;
var minArea = 2000;
var BLUE = [0, 255, 0]; //B, G, R
var RED = [0, 0, 255]; //B, G, R
var GREEN = [0, 255, 0]; //B, G, R
var WHITE = [255, 255, 255]; //B, G, R
cv.readImage('./shapes.jpg', function(err, im) {
var out = new cv.Matrix(im.height(), im.width());
im.convertGrayscale();
im_canny = im.copy();
im_canny.canny(lowThresh, highThresh);
im_canny.dilate(nIters);
contours = im_canny.findContours();
for(i = 0; i < contours.size(); i++) {
if(contours.area(i) < minArea) continue;
var arcLength = contours.arcLength(i, true);
contours.approxPolyDP(i, 0.01 * arcLength, true);
switch(contours.cornerCount(i)) {
case 3:
out.drawContour(contours, i, GREEN);
break;
case 4:
out.drawContour(contours, i, RED);
break;
default:
out.drawContour(contours, i, WHITE);
}
}
out.save('./out.png');
});
+1
Ver Arquivo
@@ -0,0 +1 @@
mencoder examples/motion.mov -ovc raw -vf format=i420 -nosound -o examples/motion.avi
+25
Ver Arquivo
@@ -0,0 +1,25 @@
var path = require('path'),
cv = require('../lib/opencv');
// When opening a file, the full path must be passed to opencv
var vid = new cv.VideoCapture(path.join(__dirname, "motion.mov"));
vid.read(function(err, mat){
var track = new cv.TrackedObject(mat, [420, 110, 490, 170], {channel: "value"});
var x = 0;
var iter = function(){
vid.read(function(err, m2){
x++;
var rec = track.track(m2)
console.log(">>", x, ":" , rec)
if (x % 10 == 0){
m2.rectangle([rec[0], rec[1]], [rec[2], rec[3]])
// m2.save('./out-motiontrack-' + x + '.jpg')
}
if (x<100)
iter();
})
}
iter();
})
Arquivo binário não exibido.
Arquivo executável
+55
Ver Arquivo
@@ -0,0 +1,55 @@
#!/usr/bin/env node
//
// Finds quadrilaterals and fills them with an X
//
var cv = require('../lib/opencv');
var lowThresh = 0;
var highThresh = 100;
var nIters = 2;
var minArea = 2000;
var maxArea = 100000;
var BLUE = [0, 255, 0]; //B, G, R
var RED = [0, 0, 255]; //B, G, R
var GREEN = [0, 255, 0]; //B, G, R
var WHITE = [255, 255, 255]; //B, G, R
cv.readImage('./quads.jpg', function(err, im) {
var out = im.copy();
im.convertGrayscale();
im_canny = im.copy();
im_canny.canny(lowThresh, highThresh);
im_canny.dilate(nIters);
contours = im_canny.findContours();
for(i = 0; i < contours.size(); i++) {
var area = contours.area(i);
if(area < minArea || area > maxArea) continue;
var arcLength = contours.arcLength(i, true);
contours.approxPolyDP(i, 0.01 * arcLength, true);
if(contours.cornerCount(i) != 4) continue;
var points = [
contours.point(i, 0),
contours.point(i, 1),
contours.point(i, 2),
contours.point(i, 3)
]
out.line([points[0].x,points[0].y], [points[2].x, points[2].y], RED);
out.line([points[1].x,points[1].y], [points[3].x, points[3].y], RED);
}
out.save('./out.png');
});
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 111 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 116 KiB

+31
Ver Arquivo
@@ -0,0 +1,31 @@
var cv = require('../lib/opencv')
var vid = new cv.VideoCapture(0)
var snap = function(){
vid.read(function(err, im){
im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){
if (!faces){
console.log("No Faces")
return;
}
var face = faces[0]
, ims = im.size()
var im2 = im.roi(face.x, face.y, face.width, face.height)
/*
im.adjustROI(
-face.y
, (face.y + face.height) - ims[0]
, -face.x
, (face.x + face.width) - ims[1])
*/
im2.save('out.jpg')
})
});
}
snap()
+106 -10
Ver Arquivo
@@ -1,6 +1,7 @@
var Stream = require('stream').Stream
, Buffers = require('buffer')
, util = require('util');
, Buffers = require('buffers')
, util = require('util')
, path = require('path')
var bindings = require('./bindings')
@@ -20,7 +21,15 @@ var matrix = cv.Matrix.prototype;
matrix.detectObject = function(classifier, opts, cb){
opts = opts || {}
var face_cascade = new cv.CascadeClassifier(classifier);
cv._detectObjectClassifiers = cv._detectObjectClassifiers || {}
if (cv._detectObjectClassifiers[classifier]){
var face_cascade = cv._detectObjectClassifiers[classifier];
} else{
var face_cascade = new cv.CascadeClassifier(classifier);
cv._detectObjectClassifiers[classifier] = face_cascade;
}
face_cascade.detectMultiScale(this, cb, opts.scale, opts.neighbors
, opts.min && opts.min[0], opts.min && opts.min[1]);
}
@@ -32,23 +41,23 @@ matrix.inspect = function(){
}
cv.ImageStream = function(){
cv.ImageDataStream = function(){
this.data = Buffers([])
this.writable = true
}
util.inherits(cv.ImageStream, Stream);
var imagestream = cv.ImageStream.prototype;
util.inherits(cv.ImageDataStream, Stream);
var imagedatastream = cv.ImageDataStream.prototype;
imagestream.write = function(buf){
this.data.push(buf)
imagedatastream.write = function(buf){
this.data.push(buf)
return true;
}
imagestream.end = function(b){
imagedatastream.end = function(b){
var self = this;
if (b)
imagestream.write.call(this,b);
@@ -59,3 +68,90 @@ imagestream.end = function(b){
});
}
cv.ImageStream = function(){
this.writable = true
}
util.inherits(cv.ImageStream, Stream);
var imagestream = cv.ImageStream.prototype;
imagestream.write = function(buf){
var self = this;
cv.readImage(buf, function(err, matrix){
self.emit('data', matrix);
});
}
// Object detect stream
cv.ObjectDetectionStream = function(cascade, opts){
this.classifier = new cv.CascadeClassifier(cascade);
this.opts = opts || {}
this.readable = true;
this.writable = true;
}
util.inherits(cv.ObjectDetectionStream, Stream);
var ods = cv.ObjectDetectionStream.prototype;
ods.write = function(m){
var self = this;
this.classifier.detectMultiScale(m,
function(e, objs){
if (e) { throw e }
self.emit('data', objs, m);
}
, this.opts.scale, this.opts.neighbors
, this.opts.min && this.opts.min[0], this.opts.min && this.opts.min[1]);
}
// == Video Stream ==
cv.VideoStream = function(src){
if (src instanceof cv.VideoCapture){
this.video = src
} else {
this.video = new cv.VideoCapture(src);
}
this.readable = true;
this.paused = false;
}
util.inherits(cv.VideoStream, Stream);
var videostream = cv.VideoStream.prototype;
cv.VideoCapture.prototype.toStream = function(){
return new cv.VideoStream(this);
}
videostream.read = function(){
var self = this;
var frame = function(){
self.video.read(function(err, mat){
self.emit('data', mat)
if (!self.paused){
process.nextTick(frame)
}
})
}
frame();
}
videostream.pause = function(){
this.paused = true
}
videostream.resume = function(){
this.paused = false
this.read()
}
// Provide cascade data for faces etc.
cv.FACE_CASCADE = path.resolve(__dirname, '../data/haarcascade_frontalface_alt.xml')
+16 -3
Ver Arquivo
@@ -5,14 +5,27 @@
"dependencies": {
"buffers": "0.1.1"
},
"version": "0.0.8",
"version": "0.4.0",
"devDependencies": {
"vows": "*"
},
"engine": "node >= 0.4.1",
"engines": {
"node": ">=0.4.1"
},
"license": "MIT",
"scripts": {
"preinstall": "node-gyp clean rebuild",
"test": "vows test/unit.js"
},
"main": "./lib/opencv"
"keywords": [
"opencv",
"computer",
"vision",
"quadrocopter"
],
"main": "./lib/opencv",
"repository": {
"type": "git",
"url": "https://github.com/peterbraden/node-opencv.git"
}
}
+10 -2
Ver Arquivo
@@ -1,6 +1,14 @@
#!/bin/bash
node-gyp rebuild && echo '-- Compiled OK --
if [ ! -f smoke/smoketest.js ]; then
echo "Please run smoke test from the top-level folder of the repository." >&2
exit 1
fi
node-gyp build && echo '-- Compiled OK --
' && node smoke/smoketest.js && echo '-- Smoke Done, running tests --
' && npm test
' && npm test # && echo '-- Tests Run, runnning examples --
#(building example data)
#' && ./examples/make-example-files.sh && node examples/motion-track.js
+20 -26
Ver Arquivo
@@ -1,34 +1,28 @@
var cv = require('../lib/opencv')
var trainingData = []
/*
new cv.VideoCapture(0).read(function(mat){
for (var i = 1; i< 41; i++){
for (var j = 1; j<10; j++){
trainingData.push([i,"/Users/peterbraden/Downloads/orl_faces/s" + i + "/" + j + ".pgm" ])
}
}
mat.resize(200,100)
mat.save('./out.jpg')
cv.readImage("/Users/peterbraden/Downloads/orl_faces/s6/10.pgm", function(e, im){
var facerec = cv.FaceRecognizer.createEigenFaceRecognizer();
//facerec.trainSync(trainingData);
facerec.loadSync("/Users/peterbraden/Desktop/ORL")
console.log(facerec.predictSync(im));
mat.detectObject("./data/haarcascade_frontalface_alt.xml", {min : [30,30]}, function(err, faces){
for (var i=0;i<faces.length; i++){
var x = faces[i]
mat.ellipse(x.x + x.width/2, x.y + x.height/2, x.width/2, x.height/2);
}
console.log(faces.length ? (faces.length + " faces found") : "No faces")
mat.save('./out.jpg');
})
})
*/
cv.readImage("examples/mona.png", function(e, mat){
var th = mat.threshold(200, 200, "Threshold to Zero Inverted");
th.save('out.png')
})
cv.readImage("./examples/stuff.png", function(err, im){
var i2 = im.copy()
i2.convertGrayscale()
i2.canny(5, 300)
var features = i2.houghLinesP();
for (var i=0;i<features.length; i++){
var x = features[i]
im.line([x[0], x[1]], [x[2], x[3]]);
im.ellipse(x[0], x[1]);
im.ellipse(x[2], x[3]);
}
console.log(features)
im.save('./out.jpg');
});
+191
Ver Arquivo
@@ -0,0 +1,191 @@
#include "CamShift.h"
#include "OpenCV.h"
#include "Matrix.h"
#define CHANNEL_HUE 0
#define CHANNEL_SATURATION 1
#define CHANNEL_VALUE 2
Persistent<FunctionTemplate> TrackedObject::constructor;
void
TrackedObject::Init(Handle<Object> target) {
HandleScope scope;
// Constructor
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(TrackedObject::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("TrackedObject"));
// Prototype
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(constructor, "track", Track);
target->Set(String::NewSymbol("TrackedObject"), constructor->GetFunction());
};
Handle<Value>
TrackedObject::New(const Arguments &args) {
HandleScope scope;
if (args.This()->InternalFieldCount() == 0){
JSTHROW_TYPE("Cannot Instantiate without new")
}
Matrix* m = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
cv::Rect r;
int channel = CHANNEL_HUE;
if (args[1]->IsArray()){
Local<Object> v8rec = args[1]->ToObject();
r = cv::Rect(
v8rec->Get(0)->IntegerValue(),
v8rec->Get(1)->IntegerValue(),
v8rec->Get(2)->IntegerValue() - v8rec->Get(0)->IntegerValue(),
v8rec->Get(3)->IntegerValue() - v8rec->Get(1)->IntegerValue());
} else {
JSTHROW_TYPE("Must pass rectangle to track")
}
if (args[2]->IsObject()){
Local<Object> opts = args[2]->ToObject();
if (opts->Get(String::New("channel"))->IsString()){
v8::String::Utf8Value c(opts->Get(String::New("channel"))->ToString());
std::string cc = std::string(*c);
if (cc == "hue" || cc == "h"){
channel = CHANNEL_HUE;
}
if (cc == "saturation" || cc == "s"){
channel = CHANNEL_SATURATION;
}
if (cc == "value" || cc == "v"){
channel = CHANNEL_VALUE;
}
}
}
TrackedObject *to = new TrackedObject(m->mat, r, channel);
to->Wrap(args.This());
return args.This();
}
void update_chann_image(TrackedObject* t, cv::Mat image){
// Store HSV Hue Image
cv::cvtColor(image, t->hsv, CV_BGR2HSV); // convert to HSV space
//mask out-of-range values
int vmin = 65, vmax = 256, smin = 55;
cv::inRange(t->hsv, //source
cv::Scalar(0, smin, MIN(vmin, vmax), 0), //lower bound
cv::Scalar(180, 256, MAX(vmin, vmax) ,0), //upper bound
t->mask); //destination
//extract the hue channel, split: src, dest channels
std::vector<cv::Mat> hsvplanes;
cv::split(t->hsv, hsvplanes);
t->hue = hsvplanes[t->channel];
}
TrackedObject::TrackedObject(cv::Mat image, cv::Rect rect, int chan){
channel = chan;
update_chann_image(this, image);
prev_rect = rect;
// Calculate Histogram
int hbins = 30, sbins = 32;
int histSizes[] = {hbins, sbins};
//float hranges[] = { 0, 180 };
// saturation varies from 0 (black-gray-white) to
// 255 (pure spectrum color)
float sranges[] = { 0, 256 };
const float* ranges[] = { sranges };
cv::Mat hue_roi = hue(rect);
cv::Mat mask_roi = mask(rect);
cv::calcHist(&hue_roi, 1, 0, mask_roi, hist, 1, histSizes, ranges, true, false);
}
Handle<Value>
TrackedObject::Track(const v8::Arguments& args){
SETUP_FUNCTION(TrackedObject)
if (args.Length() != 1){
v8::ThrowException(v8::Exception::TypeError(v8::String::New("track takes an image param")));
return Undefined();
}
Matrix *im = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
cv::RotatedRect r;
if (self->prev_rect.x <0 ||
self->prev_rect.y <0 ||
self->prev_rect.width <= 1 ||
self->prev_rect.height <= 1){
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("OPENCV ERROR: prev rectangle is illogical")));
}
update_chann_image(self, im->mat);
cv::Rect backup_prev_rect = cv::Rect(
self->prev_rect.x,
self->prev_rect.y,
self->prev_rect.width,
self->prev_rect.height);
float sranges[] = { 0, 256 };
const float* ranges[] = { sranges };
int channel = 0;
cv::calcBackProject(&self->hue, 1, &channel, self->hist, self->prob, ranges);
r = cv::CamShift(self->prob, self->prev_rect,
cv::TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1));
cv::Rect bounds = r.boundingRect();
if (bounds.x >=0 && bounds.y >=0 && bounds.width > 1 && bounds.height > 1){
self->prev_rect = bounds;
} else {
//printf("CRAP> %i %i %i %i ;", self->prev_rect.x, self->prev_rect.y, self->prev_rect.width, self->prev_rect.height);
// We have encountered a bug in opencv. Somehow the prev_rect has got mangled, so we
// must reset it to a good value.
self->prev_rect = backup_prev_rect;
}
v8::Local<v8::Array> arr = v8::Array::New(4);
arr->Set(0, Number::New(bounds.x));
arr->Set(1, Number::New(bounds.y));
arr->Set(2, Number::New(bounds.x + bounds.width));
arr->Set(3, Number::New(bounds.y + bounds.height));
/*
cv::Point2f pts[4];
r.points(pts);
for (int i=0; i<8; i+=2){
arr->Set(i, Number::New(pts[i].x));
arr->Set(i+1, Number::New(pts[i].y));
}
*/
return scope.Close(arr);
}
+23
Ver Arquivo
@@ -0,0 +1,23 @@
#include "OpenCV.h"
class TrackedObject: public node::ObjectWrap {
public:
int channel;
cv::Mat hsv;
cv::Mat hue;
cv::Mat mask;
cv::Mat prob;
cv::Mat hist;
cv::Rect prev_rect;
static Persistent<FunctionTemplate> constructor;
static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
TrackedObject(cv::Mat image, cv::Rect rect, int channel);
JSFUNC(Track);
};
+1 -1
Ver Arquivo
@@ -112,7 +112,7 @@ CascadeClassifierWrap::DetectMultiScale(const v8::Arguments& args){
// eio_custom(EIO_DetectMultiScale, EIO_PRI_DEFAULT, EIO_AfterDetectMultiScale, baton);
// ev_ref(EV_DEFAULT_UC);
uv_queue_work(uv_default_loop(), &baton->request, AsyncDetectMultiScale, AfterAsyncDetectMultiScale);
uv_queue_work(uv_default_loop(), &baton->request, AsyncDetectMultiScale, (uv_after_work_cb)AfterAsyncDetectMultiScale);
return Undefined();
+2 -2
Ver Arquivo
@@ -13,7 +13,7 @@ class CascadeClassifierWrap: public node::ObjectWrap {
//static Handle<Value> LoadHaarClassifierCascade(const v8::Arguments&);
static Handle<Value> DetectMultiScale(const v8::Arguments&);
static void EIO_DetectMultiScale(eio_req *req);
static int EIO_AfterDetectMultiScale(eio_req *req);
static void EIO_DetectMultiScale(uv_work_t *req);
static int EIO_AfterDetectMultiScale(uv_work_t *req);
};
+174 -3
Ver Arquivo
@@ -23,8 +23,17 @@ Contour::Init(Handle<Object> target) {
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(constructor, "point", Point);
NODE_SET_PROTOTYPE_METHOD(constructor, "size", Size);
NODE_SET_PROTOTYPE_METHOD(constructor, "cornerCount", CornerCount);
NODE_SET_PROTOTYPE_METHOD(constructor, "area", Area);
NODE_SET_PROTOTYPE_METHOD(constructor, "arcLength", ArcLength);
NODE_SET_PROTOTYPE_METHOD(constructor, "approxPolyDP", ApproxPolyDP);
NODE_SET_PROTOTYPE_METHOD(constructor, "convexHull", ConvexHull);
NODE_SET_PROTOTYPE_METHOD(constructor, "boundingRect", BoundingRect);
NODE_SET_PROTOTYPE_METHOD(constructor, "minAreaRect", BoundingRect);
NODE_SET_PROTOTYPE_METHOD(constructor, "isConvex", IsConvex);
NODE_SET_PROTOTYPE_METHOD(constructor, "moments", Moments);
target->Set(String::NewSymbol("Contours"), m->GetFunction());
};
@@ -48,6 +57,26 @@ Contour::Contour(): ObjectWrap() {
}
Handle<Value>
Contour::Point(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
int index = args[1]->NumberValue();
cv::Point point = self->contours[pos][index];
Local<Object> data = Object::New();
data->Set(String::NewSymbol("x"), Number::New(point.x));
data->Set(String::NewSymbol("y"), Number::New(point.y));
return scope.Close(data);
}
// FIXME: this sould better be called "Length" as ``Contours`` is an Array like structure
// also, this would allow to use ``Size`` for the function returning the number of corners
// in the contour for better consistency with OpenCV.
Handle<Value>
Contour::Size(const Arguments &args) {
HandleScope scope;
@@ -55,9 +84,17 @@ Contour::Size(const Arguments &args) {
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
return scope.Close(Number::New(self->contours.size()));
}
Handle<Value>
Contour::CornerCount(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
return scope.Close(Number::New(self->contours[pos].size()));
}
Handle<Value>
Contour::Area(const Arguments &args) {
@@ -68,6 +105,140 @@ Contour::Area(const Arguments &args) {
//return scope.Close(Number::New(contourArea(self->contours)));
return scope.Close(Number::New(contourArea(cv::Mat(self->contours[pos]))));
}
Handle<Value>
Contour::ArcLength(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
bool isClosed = args[1]->BooleanValue();
return scope.Close(Number::New(arcLength(cv::Mat(self->contours[pos]), isClosed)));
}
Handle<Value>
Contour::ApproxPolyDP(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
double epsilon = args[1]->NumberValue();
bool isClosed = args[2]->BooleanValue();
cv::Mat approxed;
approxPolyDP(cv::Mat(self->contours[pos]), approxed, epsilon, isClosed);
approxed.copyTo(self->contours[pos]);
return scope.Close(v8::Null());
}
Handle<Value>
Contour::ConvexHull(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
bool clockwise = args[1]->BooleanValue();
cv::Mat hull;
cv::convexHull(cv::Mat(self->contours[pos]), hull, clockwise);
hull.copyTo(self->contours[pos]);
return scope.Close(v8::Null());
}
Handle<Value>
Contour::BoundingRect(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
cv::Rect bounding = cv::boundingRect(cv::Mat(self->contours[pos]));
Local<Object> rect = Object::New();
rect->Set(String::NewSymbol("x"), Number::New(bounding.x));
rect->Set(String::NewSymbol("y"), Number::New(bounding.y));
rect->Set(String::NewSymbol("width"), Number::New(bounding.width));
rect->Set(String::NewSymbol("height"), Number::New(bounding.height));
return scope.Close(rect);
}
Handle<Value>
Contour::MinAreaRect(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
cv::RotatedRect minimum = cv::minAreaRect(cv::Mat(self->contours[pos]));
Local<Object> rect = Object::New();
rect->Set(String::NewSymbol("angle"), Number::New(minimum.angle));
Local<Object> size = Object::New();
size->Set(String::NewSymbol("height"), Number::New(minimum.size.height));
size->Set(String::NewSymbol("width"), Number::New(minimum.size.width));
rect->Set(String::NewSymbol("size"), size);
Local<Object> center = Object::New();
center->Set(String::NewSymbol("x"), Number::New(minimum.center.x));
center->Set(String::NewSymbol("y"), Number::New(minimum.center.y));
v8::Local<v8::Array> points = v8::Array::New(4);
cv::Point2f rect_points[4];
minimum.points(rect_points);
for (unsigned int i=0; i<4; i++){
Local<Object> point = Object::New();
point->Set(String::NewSymbol("x"), Number::New(rect_points[i].x));
point->Set(String::NewSymbol("y"), Number::New(rect_points[i].y));
points->Set(i, point);
}
rect->Set(String::NewSymbol("points"), points);
return scope.Close(rect);
}
Handle<Value>
Contour::IsConvex(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
return scope.Close(Boolean::New(isContourConvex(cv::Mat(self->contours[pos]))));
}
Handle<Value>
Contour::Moments(const Arguments &args) {
HandleScope scope;
Contour *self = ObjectWrap::Unwrap<Contour>(args.This());
int pos = args[0]->NumberValue();
/// Get the moments
cv::Moments mu = moments( self->contours[pos], false );
Local<Object> res = Object::New();
res->Set(String::NewSymbol("m00"), Number::New(mu.m00));
res->Set(String::NewSymbol("m10"), Number::New(mu.m10));
res->Set(String::NewSymbol("m01"), Number::New(mu.m01));
res->Set(String::NewSymbol("m11"), Number::New(mu.m11));
return scope.Close(res);
}
+10 -1
Ver Arquivo
@@ -11,10 +11,19 @@ class Contour: public node::ObjectWrap {
static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
Contour();
Contour();
//JSFUNC(Size)
static Handle<Value> Point(const v8::Arguments&);
static Handle<Value> Size(const v8::Arguments&);
static Handle<Value> CornerCount(const v8::Arguments&);
static Handle<Value> Area(const v8::Arguments&);
static Handle<Value> ArcLength(const v8::Arguments&);
static Handle<Value> ApproxPolyDP(const v8::Arguments&);
static Handle<Value> ConvexHull(const v8::Arguments&);
static Handle<Value> BoundingRect(const v8::Arguments&);
static Handle<Value> MinAreaRect(const v8::Arguments&);
static Handle<Value> IsConvex(const v8::Arguments&);
static Handle<Value> Moments(const v8::Arguments&);
};
+283
Ver Arquivo
@@ -0,0 +1,283 @@
#include "FaceRecognizer.h"
#include "OpenCV.h"
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
#include "Matrix.h"
#define EIGEN 0
#define LBPH 1
#define FISHER 2
// Todo, move somewhere useful
cv::Mat fromMatrixOrFilename(Local<Value> v){
cv::Mat im;
if (v->IsString()){
std::string filename = std::string(*v8::String::AsciiValue(v->ToString()));
im = cv::imread(filename);
//std::cout<< im.size();
} else {
Matrix *img = ObjectWrap::Unwrap<Matrix>(v->ToObject());
im = img->mat;
}
return im;
}
void AsyncPredict(uv_work_t *req);
void AfterAsyncPredict(uv_work_t *req);
Persistent<FunctionTemplate> FaceRecognizerWrap::constructor;
void
FaceRecognizerWrap::Init(Handle<Object> target) {
HandleScope scope;
// Constructor
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(FaceRecognizerWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("FaceRecognizer"));
NODE_SET_METHOD(constructor, "createLBPHFaceRecognizer", CreateLBPH);
NODE_SET_METHOD(constructor, "createEigenFaceRecognizer", CreateEigen);
NODE_SET_METHOD(constructor, "createFisherFaceRecognizer", CreateFisher);
NODE_SET_PROTOTYPE_METHOD(constructor, "trainSync", TrainSync);
NODE_SET_PROTOTYPE_METHOD(constructor, "updateSync", UpdateSync);
NODE_SET_PROTOTYPE_METHOD(constructor, "predictSync", PredictSync);
NODE_SET_PROTOTYPE_METHOD(constructor, "saveSync", SaveSync);
NODE_SET_PROTOTYPE_METHOD(constructor, "loadSync", LoadSync);
NODE_SET_PROTOTYPE_METHOD(constructor, "getMat", GetMat);
target->Set(String::NewSymbol("FaceRecognizer"), constructor->GetFunction());
};
Handle<Value>
FaceRecognizerWrap::New(const Arguments &args) {
HandleScope scope;
if (args.This()->InternalFieldCount() == 0)
JSTHROW_TYPE("Cannot Instantiate without new")
// By default initialize LBPH
cv::Ptr<cv::FaceRecognizer> f = cv::createLBPHFaceRecognizer(1, 8, 8, 8, 80.0);
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, LBPH);
pt->Wrap(args.This());
return args.This();
}
Handle<Value>
FaceRecognizerWrap::CreateLBPH(const Arguments &args) {
HandleScope scope;
int radius = 1;
int neighbors = 8;
int grid_x = 8;
int grid_y = 8;
double threshold = 80;
INT_FROM_ARGS(radius, 0)
INT_FROM_ARGS(neighbors, 1)
INT_FROM_ARGS(grid_x, 2)
INT_FROM_ARGS(grid_y, 3)
DOUBLE_FROM_ARGS(threshold, 4)
Local<Object> n = FaceRecognizerWrap::constructor->GetFunction()->NewInstance();
cv::Ptr<cv::FaceRecognizer> f = cv::createLBPHFaceRecognizer(
radius, neighbors, grid_x, grid_y, threshold
);
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, LBPH);
pt->Wrap(n);
return n;
}
Handle<Value>
FaceRecognizerWrap::CreateEigen(const Arguments &args) {
HandleScope scope;
int components = 0;
double threshold = DBL_MAX;
INT_FROM_ARGS(components, 0)
DOUBLE_FROM_ARGS(threshold, 1)
Local<Object> n = FaceRecognizerWrap::constructor->GetFunction()->NewInstance();
cv::Ptr<cv::FaceRecognizer> f = cv::createEigenFaceRecognizer(
components, threshold
);
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, EIGEN);
pt->Wrap(n);
return n;
}
Handle<Value>
FaceRecognizerWrap::CreateFisher(const Arguments &args) {
HandleScope scope;
int components = 0;
double threshold = DBL_MAX;
INT_FROM_ARGS(components, 0)
DOUBLE_FROM_ARGS(threshold, 1)
Local<Object> n = FaceRecognizerWrap::constructor->GetFunction()->NewInstance();
cv::Ptr<cv::FaceRecognizer> f = cv::createFisherFaceRecognizer(
components, threshold
);
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, FISHER);
pt->Wrap(n);
return n;
}
FaceRecognizerWrap::FaceRecognizerWrap(cv::Ptr<cv::FaceRecognizer> f, int type){
rec = f;
typ = type;
}
Handle<Value> UnwrapTrainingData(const Arguments& args, cv::vector<cv::Mat>* images, cv::vector<int>* labels){
if (args.Length() < 1 || !args[0]->IsArray()){
JSTHROW("FaceRecognizer.train takes a list of [<int> label, image] tuples")
}
// Iterate through [[label, image], ...] etc, and add matrix / label to vectors
const Local<Array> tuples = v8::Array::Cast(*args[0]);
const uint32_t length = tuples->Length();
for (uint32_t i=0 ; i<length ; ++i){
const Local<Value> val = tuples->Get(i);
if (!val->IsArray()){
JSTHROW("train takes a list of [label, image] tuples")
}
Local<Array> valarr = v8::Array::Cast(*val);
if (valarr->Length() != 2 || !valarr->Get(0)->IsInt32()){
JSTHROW("train takes a list of [label, image] tuples")
}
int label = valarr->Get(0)->Uint32Value();
cv::Mat im = fromMatrixOrFilename(valarr->Get(1));
im = im.clone();
cv::cvtColor(im, im, CV_RGB2GRAY);
labels->push_back(label);
images->push_back(im);
}
return v8::Undefined();
}
Handle<Value>
FaceRecognizerWrap::TrainSync(const Arguments& args){
SETUP_FUNCTION(FaceRecognizerWrap)
cv::vector<cv::Mat> images;
cv::vector<int> labels;
Handle<Value> exception = UnwrapTrainingData(args, &images, &labels);
if (!exception->IsUndefined()){
return exception;
}
self->rec->train(images, labels);
return scope.Close(v8::Undefined());
}
Handle<Value>
FaceRecognizerWrap::UpdateSync(const Arguments& args){
SETUP_FUNCTION(FaceRecognizerWrap)
if (self->typ == EIGEN){
JSTHROW("Eigen Recognizer does not support update")
}
if (self->typ == FISHER){
JSTHROW("Fisher Recognizer does not support update")
}
cv::vector<cv::Mat> images;
cv::vector<int> labels;
Handle<Value> exception = UnwrapTrainingData(args, &images, &labels);
if (!exception->IsUndefined()){
return exception;
}
self->rec->update(images, labels);
return scope.Close(v8::Undefined());
}
Handle<Value>
FaceRecognizerWrap::PredictSync(const Arguments& args){
SETUP_FUNCTION(FaceRecognizerWrap)
cv::Mat im = fromMatrixOrFilename(args[0]);//TODO CHECK!
cv::cvtColor(im, im, CV_RGB2GRAY);
// int predictedLabel = self->rec->predict(im);
int predictedLabel = -1;
double confidence = 0.0;
self->rec->predict(im, predictedLabel, confidence);
v8::Local<v8::Object> res = v8::Object::New();
res->Set(v8::String::New("id"), v8::Number::New(predictedLabel));
res->Set(v8::String::New("confidence"), v8::Number::New(confidence));
return scope.Close(res);
}
Handle<Value>
FaceRecognizerWrap::SaveSync(const Arguments& args){
SETUP_FUNCTION(FaceRecognizerWrap)
if (!args[0]->IsString()){
JSTHROW("Save takes a filename")
}
std::string filename = std::string(*v8::String::AsciiValue(args[0]->ToString()));
self->rec->save(filename);
return v8::Undefined();
}
Handle<Value>
FaceRecognizerWrap::LoadSync(const Arguments& args){
SETUP_FUNCTION(FaceRecognizerWrap)
if (!args[0]->IsString()){
JSTHROW("Load takes a filename")
}
std::string filename = std::string(*v8::String::AsciiValue(args[0]->ToString()));
self->rec->load(filename);
return v8::Undefined();
}
Handle<Value>
FaceRecognizerWrap::GetMat(const Arguments& args){
SETUP_FUNCTION(FaceRecognizerWrap)
if (!args[0]->IsString()){
JSTHROW("getMat takes a key")
}
std::string key = std::string(*v8::String::AsciiValue(args[0]->ToString()));
cv::Mat m = self->rec->getMat(key);
Local<Object> im = Matrix::constructor->GetFunction()->NewInstance();
Matrix *img = ObjectWrap::Unwrap<Matrix>(im);
img->mat = m;
return im;
}
#endif // End version > 2.4
+41
Ver Arquivo
@@ -0,0 +1,41 @@
#include "OpenCV.h"
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
#include "opencv2/contrib/contrib.hpp"
class FaceRecognizerWrap: public node::ObjectWrap {
public:
cv::Ptr<cv::FaceRecognizer> rec;
int typ;
static Persistent<FunctionTemplate> constructor;
static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
FaceRecognizerWrap(cv::Ptr<cv::FaceRecognizer> f, int type);
JSFUNC(CreateLBPH)
JSFUNC(CreateEigen)
JSFUNC(CreateFisher)
JSFUNC(TrainSync)
//JSFUNC(Train)
JSFUNC(UpdateSync)
//JSFUNC(Update)
JSFUNC(PredictSync)
// JSFUNC(Predict)
//static void EIO_Predict(eio_req *req);
//static int EIO_AfterPredict(eio_req *req);
JSFUNC(SaveSync)
JSFUNC(LoadSync)
JSFUNC(GetMat)
};
#endif
+88
Ver Arquivo
@@ -0,0 +1,88 @@
#include "HighGUI.h"
#include "OpenCV.h"
#include "Matrix.h"
Persistent<FunctionTemplate> NamedWindow::constructor;
void
NamedWindow::Init(Handle<Object> target) {
HandleScope scope;
// Constructor
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(NamedWindow::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("NamedWindow"));
// Prototype
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(constructor, "show", Show);
NODE_SET_PROTOTYPE_METHOD(constructor, "destroy", Destroy);
NODE_SET_PROTOTYPE_METHOD(constructor, "blockingWaitKey", BlockingWaitKey);
target->Set(String::NewSymbol("NamedWindow"), constructor->GetFunction());
};
Handle<Value>
NamedWindow::New(const Arguments &args) {
HandleScope scope;
if (args.This()->InternalFieldCount() == 0){
JSTHROW_TYPE("Cannot Instantiate without new")
}
NamedWindow* win;
if (args.Length() == 1){
win = new NamedWindow(std::string(*v8::String::AsciiValue(args[0]->ToString())), 0);
} else if (args.Length() == 2){
win = new NamedWindow(std::string(*v8::String::AsciiValue(args[0]->ToString())), 0);
}
win->Wrap(args.Holder());
return scope.Close(args.Holder());
}
NamedWindow::NamedWindow(const std::string& name, int f){
winname = std::string(name);
flags = f;
cv::namedWindow(winname, flags);
}
Handle<Value>
NamedWindow::Show(const v8::Arguments& args){
SETUP_FUNCTION(NamedWindow)
Matrix *im = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
cv::imshow(self->winname, im->mat);
return scope.Close(args.Holder());
}
Handle<Value>
NamedWindow::Destroy(const v8::Arguments& args){
SETUP_FUNCTION(NamedWindow)
cv::destroyWindow(self->winname);
return scope.Close(args.Holder());
}
Handle<Value>
NamedWindow::BlockingWaitKey(const v8::Arguments& args){
HandleScope scope;
//SETUP_FUNCTION(NamedWindow)
int time = 0;
if (args.Length() > 1){
time = args[1]->IntegerValue();
}else{
if (args.Length() > 0){
time = args[0]->IntegerValue();
}
}
int res = cv::waitKey(time);
return scope.Close(Number::New(res));
}
+20
Ver Arquivo
@@ -0,0 +1,20 @@
#include "OpenCV.h"
class NamedWindow: public node::ObjectWrap {
public:
std::string winname;
int flags;
static Persistent<FunctionTemplate> constructor;
static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
NamedWindow(const std::string& winname, int flags);
JSFUNC(Show);
JSFUNC(Destroy);
JSFUNC(BlockingWaitKey);
};
+882 -52
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+34 -8
Ver Arquivo
@@ -2,12 +2,12 @@
class Matrix: public node::ObjectWrap {
public:
cv::Mat mat;
static Persistent<FunctionTemplate> constructor;
static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
Matrix();
Matrix();
Matrix(cv::Mat other, cv::Rect roi);
Matrix(int rows, int cols);
Matrix(int rows, int cols, int typ);
@@ -28,25 +28,38 @@ class Matrix: public node::ObjectWrap {
JSFUNC(Width)
JSFUNC(Height)
JSFUNC(Channels)
JSFUNC(Clone)
JSFUNC(Ellipse)
JSFUNC(Rectangle)
JSFUNC(Line)
JSFUNC(Empty)
JSFUNC(Save)
JSFUNC(SaveAsync)
JSFUNC(ToBuffer)
JSFUNC(ToBufferAsync)
JSFUNC(Resize)
JSFUNC(Rotate)
JSFUNC(PyrDown)
JSFUNC(PyrUp)
JSFUNC(ConvertGrayscale)
JSFUNC(ConvertHSVscale)
JSFUNC(GaussianBlur)
JSFUNC(Copy)
JSFUNC(Flip)
JSFUNC(ROI)
JSFUNC(Ptr)
JSFUNC(AbsDiff)
JSFUNC(AddWeighted)
JSFUNC(Split)
JSFUNC(BitwiseXor)
JSFUNC(CountNonZero)
//JSFUNC(Split)
JSFUNC(Canny)
JSFUNC(Dilate)
JSFUNC(Erode)
JSFUNC(FindContours)
JSFUNC(DrawContour)
@@ -56,6 +69,21 @@ class Matrix: public node::ObjectWrap {
JSFUNC(GoodFeaturesToTrack)
JSFUNC(HoughLinesP)
JSFUNC(inRange)
JSFUNC(LocateROI)
JSFUNC(AdjustROI)
JSFUNC(Threshold)
JSFUNC(MeanStdDev)
JSFUNC(CopyTo)
JSFUNC(CvtColor)
JSFUNC(Split)
JSFUNC(Merge)
JSFUNC(EqualizeHist)
JSFUNC(Pixel)
JSFUNC(FloodFill)
/*
static Handle<Value> Val(const Arguments& args);
static Handle<Value> RowRange(const Arguments& args);
@@ -77,16 +105,14 @@ class Matrix: public node::ObjectWrap {
// create, increment, release
static Handle<Value> PushBack(const Arguments& args);
static Handle<Value> PopBack(const Arguments& args);
static Handle<Value> LocateROI(const Arguments& args);
static Handle<Value> AdjustROI(const Arguments& args);
static Handle<Value> Total(const Arguments& args);
static Handle<Value> IsContinous(const Arguments& args);
static Handle<Value> Type(const Arguments& args);
static Handle<Value> Depth(const Arguments& args);
static Handle<Value> Channels(const Arguments& args);
static Handle<Value> StepOne(const Arguments& args);
*/
};
+15
Ver Arquivo
@@ -27,7 +27,22 @@ using namespace node;
#define JSFUNC(NAME) \
static Handle<Value> NAME(const Arguments& args);
#define JSTHROW_TYPE(ERR) \
return v8::ThrowException(v8::Exception::TypeError(v8::String::New(ERR)));
#define JSTHROW(ERR) \
return v8::ThrowException(v8::Exception::Error(v8::String::New(ERR)));
#define INT_FROM_ARGS(NAME, IND) \
if (args[IND]->IsInt32()){ \
NAME = args[IND]->Uint32Value(); \
}
#define DOUBLE_FROM_ARGS(NAME, IND) \
if (args[IND]->IsInt32()){ \
NAME = args[IND]->NumberValue(); \
}
class OpenCV: public node::ObjectWrap{
public:
+19 -5
Ver Arquivo
@@ -46,7 +46,10 @@ VideoCaptureWrap::New(const Arguments &args) {
if (args[0]->IsNumber()){
v = new VideoCaptureWrap(args[0]->NumberValue());
} else {}
} else {
//TODO - assumes that we have string, verify
v = new VideoCaptureWrap(std::string(*v8::String::AsciiValue(args[0]->ToString())));
}
v->Wrap(args.This());
@@ -64,6 +67,16 @@ VideoCaptureWrap::VideoCaptureWrap(int device){
}
}
VideoCaptureWrap::VideoCaptureWrap(const std::string& filename){
HandleScope scope;
cap.open(filename);
// TODO! At the moment this only takes a full path - do relative too.
if(!cap.isOpened()){
v8::ThrowException(v8::Exception::Error(String::New("Video file could not be opened (opencv reqs. non relative paths)")));
}
}
Handle<Value>
VideoCaptureWrap::Read(const Arguments &args) {
@@ -79,7 +92,7 @@ VideoCaptureWrap::Read(const Arguments &args) {
baton->im = new Matrix();
baton->request.data = baton;
uv_queue_work(uv_default_loop(), &baton->request, AsyncRead, AfterAsyncRead);
uv_queue_work(uv_default_loop(), &baton->request, AsyncRead, (uv_after_work_cb)AfterAsyncRead);
return Undefined();
}
@@ -103,11 +116,12 @@ void AfterAsyncRead(uv_work_t *req) {
mat = baton->im->mat;
img->mat = mat;
Local<Value> argv[1];
Local<Value> argv[2];
argv[0] = im_to_return;
argv[0] = Local<Value>::New(Null());
argv[1] = im_to_return;
baton->cb->Call(Context::GetCurrent()->Global(), 1, argv);
baton->cb->Call(Context::GetCurrent()->Global(), 2, argv);
baton->cb.Dispose();
delete baton;
+11 -1
Ver Arquivo
@@ -4,6 +4,9 @@
#include "CascadeClassifierWrap.h"
#include "VideoCaptureWrap.h"
#include "Contours.h"
#include "CamShift.h"
#include "HighGUI.h"
#include "FaceRecognizer.h"
extern "C" void
@@ -14,7 +17,14 @@ init(Handle<Object> target) {
Matrix::Init(target);
CascadeClassifierWrap::Init(target);
VideoCaptureWrap::Init(target);
Contour::Init(target);
Contour::Init(target);
TrackedObject::Init(target);
NamedWindow::Init(target);
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
FaceRecognizerWrap::Init(target);
#endif
};
NODE_MODULE(opencv, init)
+115 -4
Ver Arquivo
@@ -9,6 +9,16 @@ assertDeepSimilar = function(res, exp){
assert.deepEqual(res, exp)
}
assertWithinRange = function(res, exp, range){
assert.ok((res - exp) < range || (res - exp) > -range, "Not within range:" + res + " (" + exp + "+- " + range + ")")
}
assertWithinRanges = function(res, exp, range){
for (var i =0; i<res.length; i++){
assertWithinRange(res[i], exp[i], range);
}
}
vows.describe('Smoke Tests OpenCV').addBatch({
"Importing": {
@@ -29,6 +39,13 @@ vows.describe('Smoke Tests OpenCV').addBatch({
, '.Matrix imports': function(topic){
assert.ok(!!topic.Matrix)
}
, 'importing library multiple times is ok' : function(){
var cv1 = require('../lib/opencv')
, cv2 = require('../lib/opencv')
cv1.readImage('./examples/mona.png', function(){});
cv2.readImage('./examples/mona.png', function(){});
}
}
, "Point" : {
@@ -137,6 +154,23 @@ vows.describe('Smoke Tests OpenCV').addBatch({
})
}
, "toBuffer Async": {
topic: function(cv){
var buf = fs.readFileSync('./examples/mona.png')
, cb = this.callback
cv.readImage(buf.slice(0), function(err, mat){
var buff = mat.toBuffer(function(){
cb.apply(this, arguments)
})
})
}
, 'gives a buffer' : function(e, res){
assert.ok(!e)
assert.ok(res);
assert.ok(res.length > 100);
}
}
, "detectObject": {
@@ -145,7 +179,7 @@ vows.describe('Smoke Tests OpenCV').addBatch({
, cb = this.callback
cv.readImage("./examples/mona.png", function(err, im){
im.detectObject("./data/haarcascade_frontalface_alt.xml", {}, cb)
im.detectObject(cv.FACE_CASCADE, {}, cb)
})
}
@@ -156,7 +190,34 @@ vows.describe('Smoke Tests OpenCV').addBatch({
}
}
, ".absDiff and .countNonZero" : function(cv) {
cv.readImage("./examples/mona.png", function(err, im) {
cv.readImage("./examples/mona.png", function(err, im2){
assert.ok(im);
assert.ok(im2);
var diff = new cv.Matrix(im.width(), im.height());
diff.absDiff(im, im2);
diff.convertGrayscale();
assert.equal(diff.countNonZero(), 0);
});
});
}
, ".bitwiseXor" : function(cv) {
var mat1 = new cv.Matrix(1,1);
mat1.set(0,0, 1);
var mat2 = new cv.Matrix(1,1);
mat2.set(0,0, 1);
var xored = new cv.Matrix(1,1);
xored.bitwiseXor(mat1, mat2);
assert.equal(xored.get(0,0), 0);
}
}
@@ -216,12 +277,12 @@ vows.describe('Smoke Tests OpenCV').addBatch({
}
, "ImageStream" : {
, "ImageDataStream" : {
topic : require('../lib/opencv')
, "pipe" : {
topic : function(cv){
var s = new cv.ImageStream()
var s = new cv.ImageDataStream()
, self = this
s.on('load', function(im){
assert.ok(im)
@@ -239,6 +300,56 @@ vows.describe('Smoke Tests OpenCV').addBatch({
}
, "ImageStream" :{
topic : require('../lib/opencv')
, "write" : {
topic: function(cv){
var s = new cv.ImageStream()
, im = fs.readFileSync('./examples/mona.png')
, self = this;
s.on('data', function(m){
self.callback(null, m)
})
s.write(im);
}
, "receives data" : function(mat){
assert.deepEqual(mat.size(), [756,500])
}
}
}
, "ObjectDetectionStream" :{
topic : require('../lib/opencv')
}
, "CamShift" : {
"Can Create and Track" : {
topic : function(){
var cv = require('../lib/opencv')
, self = this
cv.readImage('./examples/coin1.jpg', function(e, im){
cv.readImage('./examples/coin2.jpg', function(e, im2){
self.callback(im, im2, cv)
})
})
}
, "create TrackedObject" : function(im, im2, cv){
var tracked = new cv.TrackedObject(im, [420, 110, 490, 170]);
assert.ok(tracked);
}
, "use TrackedObject.track" : function(im, im2, cv){
var tracked = new cv.TrackedObject(im, [420, 110, 490, 170], {channel: 'v'});
assertWithinRanges(tracked.track(im2), [386, 112, 459, 166], 10);
}
}
}
-45
Ver Arquivo
@@ -1,45 +0,0 @@
im.calcHistograms(function(err, hist){})
im.calcHistograms(mask, function(err, hist){})
## Face recognition TODO
// Load Database
// TODO<
cv.loadImage('test.jpg', function(err, im){
im.detectObject("front-face.xml", {}, function(err, faces){
_.each(faces, function(v){
// TODO {
var section = im.slice(v.x, v.y, v.x + v.width, v.y + v.height);
section.convertGrayscale()
section.resize(WID, HEIGHT);
section.equaliseHistogram();
// } TODO
})
})
})
-----
http://www.athile.net/library/wiki/index.php?title=Library/V8/Tutorial#Wrapping_a_Javascript_function_as_a_std::function.3C.3E
https://www.cloudkick.com/blog/2010/aug/23/writing-nodejs-native-extensions/