mirror of
https://github.com/peterbraden/node-opencv.git
synced 2025-12-08 19:45:55 +00:00
Merge pull request #495 from madshall/master
CalcOpticalFlowPyrLK added and GoodFeaturesToTrack fixed
This commit is contained in:
commit
7d0631ba3e
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@ examples/*.avi
|
|||||||
examples/tmp/*
|
examples/tmp/*
|
||||||
vagrant/.vagrant
|
vagrant/.vagrant
|
||||||
coverage/
|
coverage/
|
||||||
|
.idea
|
||||||
|
|||||||
67
examples/optical-flow.js
Executable file
67
examples/optical-flow.js
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
var cv = require('../lib/opencv');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
var cap = new cv.VideoCapture(path.join(__dirname, 'files', 'motion.mov'));
|
||||||
|
|
||||||
|
// Parameters for lucas kanade optical flow
|
||||||
|
var lk_params = {
|
||||||
|
winSize: [15, 15],
|
||||||
|
maxLevel: 2,
|
||||||
|
criteria: [cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 30, 0.03]
|
||||||
|
};
|
||||||
|
|
||||||
|
feature_params = {
|
||||||
|
maxCorners: 100,
|
||||||
|
qualityLevel: 0.1,
|
||||||
|
minDistance: 10
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create some random colors
|
||||||
|
var color = [255, 0, 0];
|
||||||
|
|
||||||
|
/*
|
||||||
|
var window = new cv.NamedWindow('Video', 0);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Take first frame and find corners in it
|
||||||
|
cap.read(function(err, firstFrame) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
var old_frame = firstFrame;
|
||||||
|
|
||||||
|
// Create a mask image for drawing purposes
|
||||||
|
function read() {
|
||||||
|
var out = old_frame.copy();
|
||||||
|
cap.read(function(err, newFrame) {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
var frameSize = newFrame.size();
|
||||||
|
|
||||||
|
if ( frameSize[0] > 0 && frameSize[1] > 0) {
|
||||||
|
var goodFeatures = old_frame.goodFeaturesToTrack(feature_params.maxCorners, feature_params.qualityLevel, feature_params.minDistance);
|
||||||
|
|
||||||
|
// calculate optical flow
|
||||||
|
var flow = old_frame.calcOpticalFlowPyrLK(newFrame, goodFeatures, lk_params.winSize, lk_params.maxLevel, lk_params.criteria);
|
||||||
|
|
||||||
|
// Select good points
|
||||||
|
|
||||||
|
// draw the tracks
|
||||||
|
for(var i = 0; i < flow.old_points.length; i++){
|
||||||
|
if(flow.found[i]){
|
||||||
|
out.line(flow.old_points[i], flow.new_points[i], color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
window.show(out);
|
||||||
|
window.blockingWaitKey(0, 50);
|
||||||
|
*/
|
||||||
|
|
||||||
|
old_frame = newFrame.copy();
|
||||||
|
read();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
read();
|
||||||
|
});
|
||||||
@ -101,6 +101,9 @@ void Constants::Init(Local<Object> target) {
|
|||||||
CONST_INT(CV_DIST_MASK_5);
|
CONST_INT(CV_DIST_MASK_5);
|
||||||
CONST_INT(CV_DIST_MASK_PRECISE);
|
CONST_INT(CV_DIST_MASK_PRECISE);
|
||||||
|
|
||||||
|
target->Set(Nan::New("TERM_CRITERIA_EPS").ToLocalChecked(), Nan::New<Integer>((int)cv::TermCriteria::EPS));
|
||||||
|
target->Set(Nan::New("TERM_CRITERIA_COUNT").ToLocalChecked(), Nan::New<Integer>((int)cv::TermCriteria::COUNT));
|
||||||
|
|
||||||
target->Set(Nan::New("Constants").ToLocalChecked(), obj);
|
target->Set(Nan::New("Constants").ToLocalChecked(), obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -82,6 +82,7 @@ void Matrix::Init(Local<Object> target) {
|
|||||||
Nan::SetPrototypeMethod(ctor, "drawContour", DrawContour);
|
Nan::SetPrototypeMethod(ctor, "drawContour", DrawContour);
|
||||||
Nan::SetPrototypeMethod(ctor, "drawAllContours", DrawAllContours);
|
Nan::SetPrototypeMethod(ctor, "drawAllContours", DrawAllContours);
|
||||||
Nan::SetPrototypeMethod(ctor, "goodFeaturesToTrack", GoodFeaturesToTrack);
|
Nan::SetPrototypeMethod(ctor, "goodFeaturesToTrack", GoodFeaturesToTrack);
|
||||||
|
Nan::SetPrototypeMethod(ctor, "calcOpticalFlowPyrLK", CalcOpticalFlowPyrLK);
|
||||||
Nan::SetPrototypeMethod(ctor, "houghLinesP", HoughLinesP);
|
Nan::SetPrototypeMethod(ctor, "houghLinesP", HoughLinesP);
|
||||||
Nan::SetPrototypeMethod(ctor, "houghCircles", HoughCircles);
|
Nan::SetPrototypeMethod(ctor, "houghCircles", HoughCircles);
|
||||||
Nan::SetPrototypeMethod(ctor, "inRange", inRange);
|
Nan::SetPrototypeMethod(ctor, "inRange", inRange);
|
||||||
@ -1596,13 +1597,17 @@ NAN_METHOD(Matrix::GoodFeaturesToTrack) {
|
|||||||
Nan::HandleScope scope;
|
Nan::HandleScope scope;
|
||||||
|
|
||||||
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
|
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
|
||||||
|
int maxCorners = info.Length() >= 1 ? info[0]->IntegerValue() : 500;
|
||||||
|
double qualityLevel = info.Length() >= 2 ? (double) info[1]->NumberValue() : 0.01;
|
||||||
|
double minDistance = info.Length() >= 3 ? (double) info[2]->NumberValue() : 10;
|
||||||
|
|
||||||
std::vector<cv::Point2f> corners;
|
std::vector<cv::Point2f> corners;
|
||||||
cv::Mat gray;
|
cv::Mat gray;
|
||||||
|
|
||||||
cvtColor(self->mat, gray, CV_BGR2GRAY);
|
cvtColor(self->mat, gray, CV_BGR2GRAY);
|
||||||
equalizeHist(gray, gray);
|
equalizeHist(gray, gray);
|
||||||
|
|
||||||
cv::goodFeaturesToTrack(gray, corners, 500, 0.01, 10);
|
cv::goodFeaturesToTrack(gray, corners, maxCorners, qualityLevel, minDistance);
|
||||||
v8::Local<v8::Array> arr = Nan::New<Array>(corners.size());
|
v8::Local<v8::Array> arr = Nan::New<Array>(corners.size());
|
||||||
|
|
||||||
for (unsigned int i=0; i<corners.size(); i++) {
|
for (unsigned int i=0; i<corners.size(); i++) {
|
||||||
@ -1615,6 +1620,83 @@ NAN_METHOD(Matrix::GoodFeaturesToTrack) {
|
|||||||
info.GetReturnValue().Set(arr);
|
info.GetReturnValue().Set(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NAN_METHOD(Matrix::CalcOpticalFlowPyrLK) {
|
||||||
|
Nan::HandleScope scope;
|
||||||
|
|
||||||
|
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
|
||||||
|
Matrix *newMatrix = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
|
||||||
|
Local<Array> points = Local<Array>::Cast(info[1]->ToObject());
|
||||||
|
std::vector<cv::Point2f> old_points;
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<points->Length(); i++) {
|
||||||
|
Local<Object> pt = points->Get(i)->ToObject();
|
||||||
|
old_points.push_back(cv::Point2f(pt->Get(0)->NumberValue(), pt->Get(1)->NumberValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Size winSize;
|
||||||
|
if (info.Length() >= 3 && info[2]->IsArray()) {
|
||||||
|
Local<Object> winSizeObj = info[2]->ToObject();
|
||||||
|
winSize = cv::Size(winSizeObj->Get(0)->IntegerValue(), winSizeObj->Get(1)->IntegerValue());
|
||||||
|
} else {
|
||||||
|
winSize = cv::Size(21, 21);
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxLevel = info.Length() >= 4 ? info[3]->IntegerValue() : 3;
|
||||||
|
|
||||||
|
cv::TermCriteria criteria;
|
||||||
|
if (info.Length() >= 5 && info[4]->IsArray()) {
|
||||||
|
Local<Object> criteriaObj = info[4]->ToObject();
|
||||||
|
criteria = cv::TermCriteria(criteriaObj->Get(0)->IntegerValue(), criteriaObj->Get(1)->IntegerValue(), (double) criteriaObj->Get(2)->NumberValue());
|
||||||
|
} else {
|
||||||
|
criteria = cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 30, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
int flags = info.Length() >= 6 ? info[5]->IntegerValue() : 0;
|
||||||
|
double minEigThreshold = info.Length() >= 7 ? info[6]->NumberValue() : 1e-4;
|
||||||
|
|
||||||
|
cv::Mat old_gray;
|
||||||
|
cv::cvtColor(self->mat, old_gray, CV_BGR2GRAY);
|
||||||
|
|
||||||
|
cv::Mat new_gray;
|
||||||
|
cv::cvtColor(newMatrix->mat, new_gray, CV_BGR2GRAY);
|
||||||
|
|
||||||
|
std::vector<cv::Point2f> new_points;
|
||||||
|
std::vector<uchar> status;
|
||||||
|
std::vector<float> err;
|
||||||
|
|
||||||
|
cv::calcOpticalFlowPyrLK(old_gray, new_gray, old_points, new_points, status, err, winSize, maxLevel, criteria, flags, minEigThreshold);
|
||||||
|
|
||||||
|
v8::Local<v8::Array> old_arr = Nan::New<Array>(old_points.size());
|
||||||
|
v8::Local<v8::Array> new_arr = Nan::New<Array>(new_points.size());
|
||||||
|
v8::Local<v8::Array> found = Nan::New<Array>(status.size());
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<old_points.size(); i++) {
|
||||||
|
v8::Local<v8::Array> pt = Nan::New<Array>(2);
|
||||||
|
pt->Set(0, Nan::New<Number>((double) old_points[i].x));
|
||||||
|
pt->Set(1, Nan::New<Number>((double) old_points[i].y));
|
||||||
|
old_arr->Set(i, pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<new_points.size(); i++) {
|
||||||
|
v8::Local<v8::Array> pt = Nan::New<Array>(2);
|
||||||
|
pt->Set(0, Nan::New<Number>((double) new_points[i].x));
|
||||||
|
pt->Set(1, Nan::New<Number>((double) new_points[i].y));
|
||||||
|
new_arr->Set(i, pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<status.size(); i++) {
|
||||||
|
v8::Local<v8::Integer> pt = Nan::New<Integer>((int)status[i]);
|
||||||
|
found->Set(i, pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
Local<Object> data = Nan::New<Object>();
|
||||||
|
data->Set(Nan::New<String>("old_points").ToLocalChecked(), old_arr);
|
||||||
|
data->Set(Nan::New<String>("new_points").ToLocalChecked(), new_arr);
|
||||||
|
data->Set(Nan::New<String>("found").ToLocalChecked(), found);
|
||||||
|
|
||||||
|
info.GetReturnValue().Set(data);
|
||||||
|
}
|
||||||
|
|
||||||
NAN_METHOD(Matrix::HoughLinesP) {
|
NAN_METHOD(Matrix::HoughLinesP) {
|
||||||
Nan::HandleScope scope;
|
Nan::HandleScope scope;
|
||||||
|
|
||||||
|
|||||||
@ -89,6 +89,7 @@ public:
|
|||||||
|
|
||||||
// Feature Detection
|
// Feature Detection
|
||||||
JSFUNC(GoodFeaturesToTrack)
|
JSFUNC(GoodFeaturesToTrack)
|
||||||
|
JSFUNC(CalcOpticalFlowPyrLK)
|
||||||
JSFUNC(HoughLinesP)
|
JSFUNC(HoughLinesP)
|
||||||
JSFUNC(HoughCircles)
|
JSFUNC(HoughCircles)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user