I am fairly new to openCV libraries and I am trying to do real time object detection for a school project on an android app. followed this tutorial (https://www.youtube.com/watch?v=bSeFrPrqZ2A) and I am able to detect object by color on my android phone. Now I am trying to map out the trajectory of the object just like in this video (https://www.youtube.com/watch?v=QTYSRZD4vyI).
Following is some of the source code provided in the first youtube video.
void searchForMovement(int& x, int& y, Mat& mRgb1, Mat& threshold){
morphOps(threshold);
Mat temp;
threshold.copyTo(temp);
//these two vectors needed for output of findContours
vector< vector<Point> > contours;
vector<Vec4i> hierarchy;
//find contours of filtered image using openCV findContours function
//In OpenCV, finding contours is like finding white object from black background.
// So remember, object to be found should be white and background should be black.
//CV_CHAIN_APPROX_SIMPLE to draw 4 points of the contour
findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );
double refArea = 0;
bool objectFound = false;
if (hierarchy.size() > 0) {
int numObjects = hierarchy.size();
//if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter
if(numObjects<MAX_NUM_OBJECTS){
for (int index = 0; index >= 0; index = hierarchy[index][0]) {
Moments moment = moments((cv::Mat)contours[index]);
double area = moment.m00;
//if the area is less than 20 px by 20px then it is probably just noise
//if the area is the same as the 3/2 of the image size, probably just a bad filter
//we only want the object with the largest area so we safe a reference area each
//iteration and compare it to the area in the next iteration.
if(area>MIN_OBJECT_AREA && area<MAX_OBJECT_AREA && area>refArea){
x = moment.m10/area;
y = moment.m01/area;
objectFound = true;
refArea = area;
}else objectFound = false;
}
//let user know you found an object
if(objectFound ==true){
putText(mRgb1,"Tracking Object",Point(0,50),2,1,Scalar(0,255,0),2);
//draw object location on screen
drawObject(x,y,mRgb1);}
}else putText(mRgb1,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2);
}
}
void drawObject(int x, int y,Mat &frame){
Mat traj;
traj = frame;
//use some of the openCV drawing functions to draw crosshairs
//on your tracked image!
//UPDATE:JUNE 18TH, 2013
//added 'if' and 'else' statements to prevent
//memory errors from writing off the screen (ie. (-25,-25) is not within the window!)
circle(frame,Point(x,y),20,Scalar(0,255,0),2);
if(y-25>0)
line(frame,Point(x,y),Point(x,y-25),Scalar(0,255,0),2);
else line(traj,Point(x,y),Point(x,0),Scalar(0,255,0),2);
if(y+25<FRAME_HEIGHT)
line(frame,Point(x,y),Point(x,y+25),Scalar(0,255,0),2);
else line(frame,Point(x,y),Point(x,FRAME_HEIGHT),Scalar(0,255,0),2);
if(x-25>0)
line(traj,Point(x,y),Point(x-25,y),Scalar(0,255,0),2);
else line(frame,Point(x,y),Point(0,y),Scalar(0,255,0),2);
if(x+25<FRAME_WIDTH)
line(frame,Point(x,y),Point(x+25,y),Scalar(0,255,0),2);
else line(frame,Point(x,y),Point(FRAME_WIDTH,y),Scalar(0,255,0),2);
// add(traj, frame, frame);
putText(frame,intToString(x)+","+intToString(y),Point(x,y+30),1,1,Scalar(0,255,0),2);
}
How can I add onto this code to get the trajectory of an object showed in the 2nd video? Any suggestion would be much appreciated. Thank you.
http://opencv-srf.blogspot.co.uk/2010/09/object-detection-using-color-seperation.html
Found it. When doing it in android, need to make sure the lastX and lastY are updating as well.
I am looking for tips and hints on "the best way" to approach something. I want to either import, or create, geometry (initially a cylinder), isolate half of it, and move the vertices around, then export it again as an .obj or .stl. I realise there are libraries that will do this but I need this to work on Android and the libraries (as far as I know) don't. I made these images in 3DMax to explain what I mean. I can handle much of the coding, BUT the geometry mathematics I just cannot get my head around.
I have adapted this method for creating a cylinder from an example in the book: Processing 2: Creative Coding Hotshot...
float[][] vertx;
float[][] verty;
void setup() {
size(800, 600, P3D);
vertx = new float[36][36];//36 triangle strips, 36 vertices
verty = new float[36][36];
}
void draw() {
hint( ENABLE_DEPTH_TEST );
pushMatrix();
background(125);
fill(255);
strokeWeight(0.5);
translate( width/2, height/2, 200);
rotateX(radians(-45));
scale( 1 );
translate(0, -50, 0);
initPoints();
beginShape(TRIANGLE_STRIP );
for ( int h = 1; h < 36; h++) {
for ( int a = 0; a<37; a++ ) {
int aa = a % 36;
// normal( vertx[h][aa], 0, verty[h][aa]);
vertex( vertx[h][aa], h*5.0, verty[h][aa] );
//normal( vertx[h-1][aa], 0, verty[h-1][aa]);
vertex( vertx[h-1][aa], (h-1)*5.0, verty[h-1][aa] );
}
}
endShape();
beginShape(TRIANGLE_FAN); //bottom
int h = 35;
vertex( 0, h*5, 0 );
for ( int a = 0; a<37; a++ ) {
int aa = a % 36;
vertex( vertx[h][aa], h*5, verty[h][aa] );
}
endShape();
popMatrix();
hint(DISABLE_DEPTH_TEST);
}
float getR( float a, float h ) {
float r = 50;
return r;
}
void initPoints() {
for ( int h = 0; h < 36; h++) {
for ( int a = 0; a<36; a++) {
float r = getR( a*10.0, h*5.0 ); //a = 10 (360/36)
vertx[h][a] = cos( radians( a*10.0 )) * r;
verty[h][a] = sin( radians( a*10.0 )) * r;
}
}
}
...and I am assuming it is possible to isolate/grab certain vertices from the array?
Any other approaches, or any advice on how to develop this? Is the import > transform method even possible? #Spektre - might there be a better approach than this?
This is a very general question, so I'll give you a general answer.
Your first step is to really digest the code you posted: what do each of the calls to vertex() do? Where is each vertex being placed? You should be able to write your own code that draws a cylinder without copy-pasting anything from this code. You should be able to draw other shapes. Start by only drawing a few vertexes to see where they're showing up, then add a few more, then a few more, until you understand exactly what this code is doing.
There are a ton of tutorials that can help you understand the code. Here is a 2D tutorial to get you started (read (and understand) that one first), and here is a 3D version.
Once you have that working it should be pretty easy to manipulate the vertexes however you want. If you want the user to be able to select a vertex, google something like "3d point picking" for a ton of resources.
Finally, I'm not sure Processing provides an easy way to export a .obj file. But again, google is your friend- try googling something like "Processing export obj file" for a handful of libraries that seem to help with your goal.
If you get stuck on a specific step, post an MCVE and ask a specific question. Good luck!
The dst = signum(src) function set the values of all positive elements in src to 1, and the values of all negative elements to -1.
However, it seems that it is not possible to implement the signum() function by applying the OpenCV function threshold(). I do not want to traverse src neither, because it is inefficient.
I don't know which language you are using, but in OpenCV C++, signum function can be implemented as follows:
Mat signum(Mat src)
{
Mat dst = (src >= 0) & 1;
dst.convertTo(dst,CV_32F, 2.0, -1.0);
return dst;
}
Of-course, the returned matrix would have floating point or a signed type to store the value of -1.
Update:
The previous implementation returns only 1 or -1 depending on the input values, but according to signum definition, 0 should remain 0 in the output. So getting reference from this answer, the standard signum function can be implemented as follows using OpenCV:
Mat signum(Mat src)
{
Mat z = Mat::zeros(src.size(), src.type());
Mat a = (z < src) & 1;
Mat b = (src < z) & 1;
Mat dst;
addWeighted(a,1.0,b,-1.0,0.0,dst, CV_32F);
return dst;
}
I'm writing an image processing app on android, and I'm trying to speed it up using the NDK. I have the following for-loop:
int x, y, c, idx;
const int pitch3 = pitch * 3;
float adj, result;
...
// px, py, u, u_bar are all float arrays of size nx*ny*3
// theta, tau, denom are float constants
// idx >= pitch3
for(y=1;y<ny;++y)
{
for(x=1;x<nx;++x)
{
for(c=0;c<3;++c)
{
adj = -px[idx] - py[idx] + px[idx - 3] + py[idx - pitch3];
result = ((u[idx] - tau * adj) + tau * f[idx]) * denom;
u_bar[idx] = result + theta * (result - u[idx]);
u[idx] = result;
++idx;
}
}
}
I'm wondering if it is possible to speed up this loop?
I'm thinking that using fixed-point arithmetic wouldn't do much, except on really old android phone (which I'm not going to target). Would writing it in assembly give a big improvement?
EDIT: I know I could use SIMD/NEON instructions, but they are not so common I think ...
Since you're accessing the array as a flat structure, the 3 levels of looping is only increasing the value used for idx. You can loop for (idx = pitch3; idx < nx*ny*3; idx++).
Another option is to move to fixed-point math. Do you really need more than 64 bits of dynamic range?
I'am actually working in a project on android in which I want to extract some specific pixel values (according to a condition, using the threshold method , I have set some pixels to a certain values and all the others to zero) I want to extract all these values different from zero in a vector. I will use this vector of the chosen pixels to do some operation ( the mean value for exemple ) , Is there a method in OpenCV that can help me doing this ?
Thank you :)
I don't know such function but actually it's not hard to implement it (c++):
//'in' should be CV_8UC3
vector<int>& getNonZero(const Mat& in)
{
//get size of result vector
//this is all non-zero pixels:
int count = countNonZero(in);
vector<int>& result(count);
int k = 0;
for (int r = 0; r < in.rows; ++r)
{
for (int c = 0; c < in.cols; ++c)
{
if (in.at<int>(r, c))
{
result[k++] = in.at<int>(r, c);
}
}
}
return result;
}
And also many OpenCV functions have InputArray mask parameter so use it! For example:
void meanStdDev(InputArray src, OutputArray mean, OutputArray stddev, InputArray mask=noArray())