I'm doing "photo" processing application using C with OpenCV.
My computer will constantly survey its surroundings using its
webcam. When it detects movement, it will write the current
webcam image to a file (notify).
This is how I have written the code , but it is very slow, I'm not good in doing the notify....could you give me please some good advice concerning the code?
#include <stdio.h>
#include "cv.h"
#include "highgui.h"
#include <dos.h>
#include <conio.h>
CvCapture *capture;
int key;
IplImage *oldFrame;
IplImage *currentFrame;
IplImage *res;
int f=0,x,y,idx,idy;
int currentFrame_width, currentFrame_height;
int oldFrame_width, oldFrame_height;
int res_width, res_height;
int main( int argc, char** argv )
{
while( key != 'q' )
{
capture = cvCaptureFromCAM( 0 );
if( !capture ) return 1;
key = cvWaitKey( 1 );
cvNamedWindow( "FrameController", CV_WINDOW_AUTOSIZE );
if(f==0){
oldFrame = cvQueryFrame( capture );
cvShowImage( "FrameController", oldFrame );
f=1;
}
else{
CvMemStorage* storage = cvCreateMemStorage(0);
currentFrame = cvQueryFrame( capture );
for ( x=0;x<currentFrame->width;x++)
{
for ( y=0;y<currentFrame->height;y++)
{
idx = y*currentFrame->widthStep + currentFrame->nChannels*x;
idy = y*oldFrame->widthStep + oldFrame->nChannels*x;
}
}
uchar R= (uchar) currentFrame->imageData [idx+0];
uchar G = (uchar) currentFrame->imageData [idx+1];
uchar B = (uchar) currentFrame->imageData [idx+2];
uchar R1= (uchar) oldFrame->imageData [idy+0];
uchar G1 = (uchar) oldFrame->imageData [idy+1];
uchar B1 = (uchar) oldFrame->imageData [idy+2];
if(!((R==R1) || (G==G1) || (B==B1))){
f=0;
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "C:\\OpenCV2.1\\data\\haarcascades\\haarcascade_frontalface_alt2.xml" );
double scale = 1.3;
static CvScalar colors[] = {CV_RGB(rand()&255, rand()&255, rand()&255 )};
cvClearMemStorage( storage );
CvSeq* objects = cvHaarDetectObjects( currentFrame, cascade, storage, 1.1, 4, 0, cvSize( 40, 50 ));
CvRect* r;
for( int i = 0; i < (objects ? objects->total : 0 ); i++ ){
r = ( CvRect* )cvGetSeqElem( objects, i );
cvRectangle( currentFrame, cvPoint( r->x, r->y ), cvPoint( r->x + r->width, r->y + r->height ),
colors[i%8]);
cvShowImage( "FrameController", currentFrame );
}
}
}
}
cvDestroyWindow( "FrameController" );
cvReleaseCapture( &capture );
cvReleaseImage( ¤tFrame);
cvReleaseImage( &oldFrame);
return 0;
}
Seems like you're doing unnecessary initializations inside your while loop. For example
capture = cvCaptureFromCAM( 0 ); << is that necessary to be in the loop?
cvNamedWindow( "FrameController", CV_WINDOW_AUTOSIZE ); << this?
for ( x=0;x<currentFrame->width;x++)
{
for ( y=0;y<currentFrame->height;y++)
{
idx = y*currentFrame->widthStep + currentFrame->nChannels*x;
idy = y*oldFrame->widthStep + oldFrame->nChannels*x;
}
} << that's a loop over the WHOLE IMAGE that does NOTHING.
What is the storage used for?
Hope that helped you clean up your code a bit.
Related
I have written code which is continuously calculating and drawing its output:
#include "plplot/plplot.h"
#include <math.h>
#include <windows.h>
#define NSIZE 101
int
main( int argc, char *argv[] )
{
PLFLT x[NSIZE], y[NSIZE];
PLFLT xmin = 0., xmax = 1., ymin = 0., ymax = 100.;
int i;
// Prepare data to be plotted.
for ( i = 0; i < NSIZE; i++ )
{
x[i] = (PLFLT) ( i ) / (PLFLT) ( NSIZE - 1 );
y[i] = ymax * x[i] * x[i];
}
// Parse and process command line arguments
plparseopts( &argc, argv, PL_PARSE_FULL );
// Initialize plplot
plinit();
// Create a labelled box to hold the plot.
plenv( xmin, xmax, ymin, ymax, 0, 0 );
pllab( "x", "y=100 x#u2#d", "Simple PLplot demo of a 2D line plot" );
// Plot the data that was prepared above.
for(int i=0;i<20;i++)
{
plline( NSIZE, x, y );
y[40+i]=0;
Sleep(400);
c_plclear();
plflush();
}
// Close PLplot library
plend();
exit( 0 );
}
But output updates only few time and after that the windows goes into not responding.
I'm use Windows 10 64bit + minGW64 (MSYS2) + eclipse.
Is there some correct way to do this? Or maybe this is PLplot limitation.
i m reading path from textbox and then tried to open image
String^ P = path->Text;
IplImage* img = cvLoadImage(P);
It gives me the following error
Error 1 error C2664: 'cvLoadImage' : cannot convert parameter 1 from 'System::String ^' to 'const char *'
Can anyone tell me how to convert it to char *.
System::String ^ str = path->Text ;
char* str2 = (char*)Marshal::StringToHGlobalAnsi(str).ToPointer();
printf(str2);
Include the following header files
#using <mscorlib.dll>
using namespace System::Runtime::InteropServices;
It is Never TOO late.
here is code I am using
And Do not forget to include the header file in basic file #include "saveImg.h"
call this by
saveImg () ;
saveImg.h
int saveImg (){ // int argc , char* argv[] ) { // (int argc, char** argv) {
IplImage* img;
// if( argc == 2 && (img=cvLoadImage(argv[1], 1))!= 0) {
img=cvLoadImage("hello.jpg") ;
IplImage* gray = cvCreateImage( cvGetSize(img), 8, 1 );
IplImage* net1 = cvCreateImage( cvGetSize(img), 8, 3 );
CvMemStorage* storage = cvCreateMemStorage(0);
cvCvtColor( img, gray, CV_BGR2GRAY );
cvSmooth( gray, gray, CV_GAUSSIAN, 9, 9 ); // smooth it, otherwise a lot of false circles may be detected
CvSeq* circles = cvHoughCircles( gray, storage, CV_HOUGH_GRADIENT, 2, gray->height/4, 200, 100 );
int i;
for( i = 0; i < circles->total; i++ ) {
float* p = (float*)cvGetSeqElem( circles, i );
cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), 3, CV_RGB(0,255,0), -1, 8, 0 );
cvCircle( img, cvPoint(cvRound(p[1]),cvRound(p[2])), cvRound(p[3]), CV_RGB(50,0,100), 3, 8, 0 );
// cvWaitKey(0);
}
cvNamedWindow( "Original", 1 );
cvShowImage( "Original", img );
cvWaitKey(0);
cvNamedWindow( "circles", 1 );
cvShowImage( "circles", gray );
cvWaitKey(0);
return 0;
}
Char * to String ^ in Visual Studio C++ 10 and above
I tested this and OK while making a small Calculator....
// Variables :
char * number1 ;
double num1 ;
String ^ no1 ;
number1 = (char*)Marshal::StringToHGlobalAnsi(no1).ToPointer(); num1 = atof (number1) ;
I am a new to CUDA programming and I need help in writing a program to store images in a memory buffer. I tried modifying the code in the CUDA-OpenGL interop example, given in the CUDA-By Example book, to store 2 images one after another in a buffer. How should I write the program if I tried to avoid infinite loops but I am not sure if I succeeded? Any help in writing a correct program would be very much appreciated!
#include "book.h"
#include "cpu_bitmap.h"
#include "cuda.h"
#include <cuda_gl_interop.h>
PFNGLBINDBUFFERARBPROC glBindBuffer = NULL;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers = NULL;
PFNGLGENBUFFERSARBPROC glGenBuffers = NULL;
PFNGLBUFFERDATAARBPROC glBufferData = NULL;
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) system ("pause");
}
}
#define DIM 512
#define IMAGESIZE_MAX (DIM*DIM)
GLuint bufferObj;
cudaGraphicsResource *resource;
// based on ripple code, but uses uchar4 which is the type of data
// graphic inter op uses. see screenshot - basic2.png
__global__ void kernel( uchar4 *ptr1)
{
// map from threadIdx/BlockIdx to pixel position
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x ;
// now calculate the value at that position
float fx = x/(float)DIM - 0.5f;
float fy = y/(float)DIM - 0.5f;
unsigned char green = 128 + 127 * tan( abs(fx*100) - abs(fy*100) );
// accessing uchar4 vs unsigned char*
ptr1[offset].x = 0;
ptr1[offset].y = green;
ptr1[offset].z = 0;
ptr1[offset].w = 255;
}
__global__ void kernel2( uchar4 *ptr2)
{
// map from threadIdx/BlockIdx to pixel position
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x ;
// now calculate the value at that position
float fx = x/(float)DIM - 0.5f;
float fy = y/(float)DIM - 0.5f;
unsigned char green = 128 + 127 * tan( abs(fx*100) - abs(fy*100) );
unsigned char orange = 1000;
// accessing uchar4 vs unsigned char*
ptr2[offset].x = orange;
ptr2[offset].y = green;
ptr2[offset].z = 0;
ptr2[offset].w = 255;
}
__global__ void copy ( uchar4 *pBuffer, uchar4 *Ptr )
{
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int idx = x + y * blockDim.x * gridDim.x ;
while ( idx != DIM*DIM)
{
pBuffer[idx] = Ptr[idx] ;
__syncthreads();
}
}
__global__ void copy2 ( uchar4 *pBuffer, uchar4 *Ptr2 )
{
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int idx = x + y * blockDim.x * gridDim.x ;
int bdx = idx;
while ( (idx < DIM*DIM) && (bdx < DIM*DIM) )
{
uchar4 temp = Ptr2[bdx];
__syncthreads();
pBuffer[idx+4] = temp;
__syncthreads();
if ((idx==DIM*DIM) && (bdx==DIM*DIM))
{
break;
}
}
}
void key_func( unsigned char key, int x, int y ) {
switch (key) {
case 27:
// clean up OpenGL and CUDA
( cudaGraphicsUnregisterResource( resource ) );
glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0 );
glDeleteBuffers( 1, &bufferObj );
exit(0);
}
}
void draw_func( void ) {
// we pass zero as the last parameter, because out bufferObj is now
// the source, and the field switches from being a pointer to a
// bitmap to now mean an offset into a bitmap object
glDrawPixels( DIM, DIM, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
glutSwapBuffers();
}
int main( int argc, char **argv ) {
cudaDeviceProp prop;
int dev;
(memset( &prop, 0, sizeof( cudaDeviceProp ) ));
prop.major = 1;
prop.minor = 0;
HANDLE_ERROR( cudaChooseDevice( &dev, &prop ) );
// tell CUDA which dev we will be using for graphic interop
// from the programming guide: Interoperability with OpenGL
// requires that the CUDA device be specified by
// cudaGLSetGLDevice() before any other runtime calls.
HANDLE_ERROR( cudaGLSetGLDevice( dev ) );
// these GLUT calls need to be made before the other OpenGL
// calls, else we get a seg fault
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
glutInitWindowSize( DIM, DIM );
glutCreateWindow( "bitmap" );
glBindBuffer = (PFNGLBINDBUFFERARBPROC)GET_PROC_ADDRESS("glBindBuffer");
glDeleteBuffers = (PFNGLDELETEBUFFERSARBPROC)GET_PROC_ADDRESS("glDeleteBuffers");
glGenBuffers = (PFNGLGENBUFFERSARBPROC)GET_PROC_ADDRESS("glGenBuffers");
glBufferData = (PFNGLBUFFERDATAARBPROC)GET_PROC_ADDRESS("glBufferData");
// the first three are standard OpenGL, the 4th is the CUDA reg
// of the bitmap these calls exist starting in OpenGL 1.5
glGenBuffers( 1, &bufferObj );
glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj );
glBufferData( GL_PIXEL_UNPACK_BUFFER_ARB, DIM * DIM * 4 ,
NULL, GL_DYNAMIC_DRAW_ARB );
// REGISTER THE GL BufferObj and CUDA Resource
HANDLE_ERROR(( cudaGraphicsGLRegisterBuffer( &resource,
bufferObj,
cudaGraphicsMapFlagsNone ) ));
// do work with the memory dst being on the GPU, gotten via mapping
HANDLE_ERROR( cudaGraphicsMapResources( 1, &resource, NULL ) );
uchar4* devPtr;
size_t size = DIM*DIM;
size_t sizet = 2*DIM*DIM;
gpuErrchk(cudaMalloc ( (uchar4 **)&devPtr, size));
uchar4 *devPtr2;
gpuErrchk(cudaMalloc ( (uchar4 **)&devPtr2, size));
uchar4 *pBuffer;
gpuErrchk(cudaMalloc ( (uchar4 **)&pBuffer, size));
uchar4 *pBufferCurrent;
gpuErrchk(cudaMalloc ( (uchar4 **)&pBuffer, size));
uchar4 *pBufferImage;
gpuErrchk(cudaMalloc ( (uchar4 **)&pBufferImage, sizet));
// REGISTER THE C BUFFER and CUDA Resource
HANDLE_ERROR( cudaGraphicsResourceGetMappedPointer( (void**)&pBufferImage,
&size,
resource) );
dim3 grids(DIM/16,DIM/16);
dim3 threads(16,16);
kernel<<<grids,threads>>>( devPtr );
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
kernel2<<<grids,threads>>>(devPtr2);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
int a = 1;
do
{
if (a==1)
{
copy<<< 512, 512>>>(pBufferImage, devPtr);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
}
if(a==2)
{
copy2<<< 512, 512>>>(pBufferImage, devPtr2);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
}
a++;
} while (a<=2);
HANDLE_ERROR ( cudaGraphicsUnmapResources( 1, &resource, NULL ) );
// set up GLUT and kick off main loop
glutKeyboardFunc( key_func );
glutDisplayFunc( draw_func );
glutMainLoop();
}
Here's some code I wrote that is a modification of the CUDA by examples code contained here which I believe is effectively what you started with. I used two kernels, just as you have, to generate either a green or an orange image. It will initially start with the green image displayed, but you can toggle between green and orange images using the space bar. ESC key will exit the app.
#include "book.h"
#include "cpu_bitmap.h"
//#include "cuda.h"
#include <cuda_gl_interop.h>
int which_image;
PFNGLBINDBUFFERARBPROC glBindBuffer = NULL;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers = NULL;
PFNGLGENBUFFERSARBPROC glGenBuffers = NULL;
PFNGLBUFFERDATAARBPROC glBufferData = NULL;
#define DIM 512
GLuint bufferObj;
cudaGraphicsResource *resource;
dim3 mgrids(DIM/16,DIM/16);
dim3 mthreads(16,16);
// based on ripple code, but uses uchar4 which is the type of data
// graphic inter op uses. see screenshot - basic2.png
__global__ void kernel_gr( uchar4 *ptr ) {
// map from threadIdx/BlockIdx to pixel position
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x;
// now calculate the value at that position
float fx = x/(float)DIM - 0.5f;
float fy = y/(float)DIM - 0.5f;
unsigned char green = 128 + 127 *
sin( abs(fx*100) - abs(fy*100) );
// accessing uchar4 vs unsigned char*
ptr[offset].x = 0;
ptr[offset].y = green;
ptr[offset].z = 0;
ptr[offset].w = 255;
}
__global__ void kernel_or( uchar4 *ptr ) {
// map from threadIdx/BlockIdx to pixel position
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x;
// now calculate the value at that position
float fx = x/(float)DIM - 0.5f;
float fy = y/(float)DIM - 0.5f;
unsigned char orange = 128 + 127 *
sin( abs(fx*100) - abs(fy*100) );
// accessing uchar4 vs unsigned char*
ptr[offset].x = orange;
ptr[offset].y = orange/2;
ptr[offset].z = 0;
ptr[offset].w = 255;
}
static void draw_func( void ) {
// we pass zero as the last parameter, because out bufferObj is now
// the source, and the field switches from being a pointer to a
// bitmap to now mean an offset into a bitmap object
glDrawPixels( DIM, DIM, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
glutSwapBuffers();
}
static void key_func( unsigned char key, int x, int y ) {
switch (key) {
case 32:
// do work with the memory dst being on the GPU, gotten via mapping
HANDLE_ERROR( cudaGraphicsMapResources( 1, &resource, NULL ) );
uchar4* devPtr;
size_t size;
HANDLE_ERROR(
cudaGraphicsResourceGetMappedPointer( (void**)&devPtr,
&size,
resource) );
if (which_image == 1){
kernel_or<<<mgrids,mthreads>>>( devPtr );
HANDLE_ERROR(cudaPeekAtLastError());
HANDLE_ERROR(cudaDeviceSynchronize());
printf("orange\n");
which_image = 2;
}
else {
kernel_gr<<<mgrids,mthreads>>>( devPtr );
HANDLE_ERROR(cudaPeekAtLastError());
HANDLE_ERROR(cudaDeviceSynchronize());
printf("green\n");
which_image = 1;
}
HANDLE_ERROR( cudaGraphicsUnmapResources( 1, &resource, NULL ) );
draw_func();
break;
case 27:
// clean up OpenGL and CUDA
HANDLE_ERROR( cudaGraphicsUnregisterResource( resource ) );
glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0 );
glDeleteBuffers( 1, &bufferObj );
exit(0);
}
}
int main( int argc, char **argv ) {
cudaDeviceProp prop;
int dev;
memset( &prop, 0, sizeof( cudaDeviceProp ) );
prop.major = 1;
prop.minor = 0;
HANDLE_ERROR( cudaChooseDevice( &dev, &prop ) );
// tell CUDA which dev we will be using for graphic interop
// from the programming guide: Interoperability with OpenGL
// requires that the CUDA device be specified by
// cudaGLSetGLDevice() before any other runtime calls.
HANDLE_ERROR( cudaGLSetGLDevice( dev ) );
// these GLUT calls need to be made before the other OpenGL
// calls, else we get a seg fault
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
glutInitWindowSize( DIM, DIM );
glutCreateWindow( "bitmap" );
glBindBuffer = (PFNGLBINDBUFFERARBPROC)GET_PROC_ADDRESS("glBindBuffer");
glDeleteBuffers = (PFNGLDELETEBUFFERSARBPROC)GET_PROC_ADDRESS("glDeleteBuffers");
glGenBuffers = (PFNGLGENBUFFERSARBPROC)GET_PROC_ADDRESS("glGenBuffers");
glBufferData = (PFNGLBUFFERDATAARBPROC)GET_PROC_ADDRESS("glBufferData");
// the first three are standard OpenGL, the 4th is the CUDA reg
// of the bitmap these calls exist starting in OpenGL 1.5
glGenBuffers( 1, &bufferObj );
glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj );
glBufferData( GL_PIXEL_UNPACK_BUFFER_ARB, DIM * DIM * 4,
NULL, GL_DYNAMIC_DRAW_ARB );
HANDLE_ERROR(
cudaGraphicsGLRegisterBuffer( &resource,
bufferObj,
cudaGraphicsMapFlagsNone ) );
// do work with the memory dst being on the GPU, gotten via mapping
HANDLE_ERROR( cudaGraphicsMapResources( 1, &resource, NULL ) );
uchar4* devPtr;
size_t size;
HANDLE_ERROR(
cudaGraphicsResourceGetMappedPointer( (void**)&devPtr,
&size,
resource) );
dim3 grids(DIM/16,DIM/16);
dim3 threads(16,16);
kernel_gr<<<grids,threads>>>( devPtr );
HANDLE_ERROR( cudaGraphicsUnmapResources( 1, &resource, NULL ) );
which_image = 1;
// set up GLUT and kick off main loop
glutKeyboardFunc( key_func );
glutDisplayFunc( draw_func );
glutMainLoop();
}
Not sure if it will be useful, I'm still not understanding what you want to accomplish entirely. I don't really know what this means:
I just want to store both those images in a buffer and then render the buffer containing those two images in OpenGL.
You want to be able to see one image at a time, and switch images? Or you want to be able to see both images at the same time? If the latter, please explain. Do you want one at the top of the window and one at the bottom of the window? Both of them blended together?
EDIT: It seems to me that you may be wanting some sort of 3D visualization of multiple images, since the question and answer with you about what you want hasn't been productive (at least I still can't get a handle on what you want to see VISUALLY, ignoring what goes on under the hood.) You haven't tagged this question with OpenGL, so no OpenGL experts are looking at it. Furthermore, you've made statements like: "I will use OpenGL functions to rotate and translate the buffer. " If what you're trying to do is create a 3D visualization of a set of images that a user can interact with, this is not the sample code you want to start with. This is a basic 2D image display code. Trying to expand the buffer to hold multiple images is the least of your difficulties in creating some sort of 3D visualization in OpenGL. And you will not get to some kind of 3D multi-image display using this sample code.
I suspect that the CUDA-OpenGL interop portion of what you're trying to do is not difficult. I've shown with the example program how you can get 2 different images, generated by 2 different kernels, displayed under user control. So the problem of how to take an image from CUDA and display it, or get it into a buffer that can be displayed, I think is pretty well illustrated.
My suggestion is this: Leave the CUDA-OpenGL interop portion aside. Write an OpenGL program that does what you want, with arbitrary images (generate them however you like, no need to use CUDA.) If you need help with that, pose questions on SO, and tag them with OpenGL so that people who will know how to do it can help you. Then, when you have a prototype of what you want to display visually, you can inject the CUDA portion. And I suspect that part will be pretty simple at that point.
I have to find corner points of an image so that I can crop it in rectangular shape.I have already found the contour and used approxpoly() function on it.Now how to find the corner Co-ordinates of the contour ?
Here is my C code->
#include <cv.h>
#include <highgui.h>
int main(int argc, char** argv)
{
IplImage *img,*gray;
if((img = cvLoadImage("save.jpg", 1)) == NULL)
{
printf("A Img open error\n");
}
gray=cvCreateImage( cvGetSize(img), IPL_DEPTH_8U, 1 );
cvCvtColor(img,gray,CV_BGR2GRAY);
IplImage* out_median = cvCreateImage(cvGetSize(gray),IPL_DEPTH_8U,1);
cvSmooth( gray,out_median,CV_MEDIAN,3);
IplImage* out_threshold = cvCreateImage( cvGetSize(out_median), out_median->depth, 1);
cvThreshold(out_median,out_threshold,1,255,CV_THRESH_BINARY);
CvMemStorage* storage = cvCreateMemStorage();
CvSeq* first_contour = NULL;
cvFindContours(out_threshold,storage,&first_contour,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
CvSeq* approx_polygon = NULL;
approx_polygon=cvApproxPoly(first_contour,sizeof(CvContour),storage,CV_POLY_APPROX_DP,0.01*cvArcLength(first_contour,CV_WHOLE_SEQ, 1),0);
//cvDrawContours(out_threshold,approx_polygon,cvScalarAll(255),cvScalarAll(255),100);
//cvShowImage("Contours", out_threshold );
//cvSaveImage("save_approxpoly_contour.jpg",out_threshold);
cvWaitKey(0);
return 0;
}
This my Contour Image after applying the Approxpoly()
I recommend using cvBlob:
Get the blobs:
cvThreshold(&src, &dst, 10, 255, CV_THRESH_BINARY);
IplImage *labelImg = cvCreateImage(cvGetSize(&dst),IPL_DEPTH_LABEL,1);
CvBlobs blobs;
unsigned int result = cvLabel(&dst, labelImg, blobs);
If you have more than one item, find the limits
int borders[4];
borders[0] = 99999; //left
borders[1] = 99999; //top
borders[2] = 0; //right
borders[3] = 0; //bottom
for (CvBlobs::const_iterator it=blobs.begin(); it!=blobs.end(); ++it)
{
if((*it).second->maxx) < borders[0]){
borders[0] = (*it).second->maxx;
}
if(((*it).second->miny) < borders[1]){
borders[1] = (*it).second->miny;
}
if((*it).second->minx) > borders[2]){
borders[2] = (*it).second->minx;
}
if(((*it).second->maxy) > borders[3]){
borders[3] = (*it).second->maxy;
}
}
I am pasting code below to track both eyes and overlay an image when both eyes are tracked.
I am using haar xml files to track both eyes of faces and overlaying an image over it.
My problem is I get result like this.
Img 1
Img 2
Img 3
Img 4
Img 5
Img 6
Img 7
Img 8
Img 9
Img 10
I am posting my code below
#include "cv.h"
#include "highgui.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <sys/stat.h>
#include <ctype.h>
#include <string>
using namespace cv;
using namespace std;
void detectAndDisplay( Mat frame );
String face_cascade_name = "/root/opencv/newtutorial/haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "/root/opencv/newtutorial/haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
RNG rng(12345);
IplImage *disp,*neg_img,*cpy_img,*imga;
IplImage *pic;
IplImage *image_n = 0;
int make=0;
CvMat* warp_matrix = cvCreateMat(3,3,CV_32FC1);
namespace {
void makevdo(){
bool flag = false;
fstream fin;
char filename_new[200],filename_new_after[200];
int n=0;
Mat frame;
double frameRate = 25.0;
CvVideoWriter *vdowriter = cvCreateVideoWriter( "/root/opencv/newtutorial/test_converted_next.mov", CV_FOURCC('j','p','e','g'), frameRate, Size(640,480) );
VideoWriter(outputFile,CV_FOURCC('j','p','e','g'),frameRate,Size(640,480));
while(flag==false){
sprintf(filename_new,"/root/opencv/newtutorial/mydirnext/filename%.3d.jpg",n);
sprintf(filename_new_after,"/root/opencv/newtutorial/framesaftertrack/filename%.3d.jpg",n);
fin.open(filename_new,ios::in);
if( fin.is_open() )
{
frame = imread(filename_new);
pic = cvLoadImage("/root/opencv/newtutorial/pic.png");
image_n = cvLoadImage(filename_new,1);
disp = cvCreateImage( cvGetSize(image_n), 8, 3 );
cpy_img = cvCreateImage( cvGetSize(image_n), 8, 3 );
neg_img = cvCreateImage( cvGetSize(image_n), 8, 3 );
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
CvPoint2D32f q[4];
q[0].x= (float) pic->width * 0;
q[0].y= (float) pic->height * 0;
q[1].x= (float) pic->width;
q[1].y= (float) pic->height * 0;
q[2].x= (float) pic->width;
q[2].y= (float) pic->height;
q[3].x= (float) pic->width * 0;
q[3].y= (float) pic->height;
for( int i = 0; i < (int)faces.size(); i++ )
{
faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 2, 8, 0 );
Mat faceROI = frame_gray( faces[i] );
std::vector<Rect> eyes;
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );
if((int)eyes.size()==2 && (((eyes[0].x + eyes[0].width*0.5 ) < eyes[1].x) || ((eyes[1].x + eyes[1].width*0.5 ) < eyes[0].x))){
CvPoint2D32f p[4];
IplImage* blank = cvCreateImage( cvGetSize(pic), 8, 3);
cvZero(blank);
cvNot(blank,blank);
if(eyes[0].x<eyes[1].x){
Point center0( faces[i].x + eyes[0].x + eyes[0].width*0.5, faces[i].y + eyes[0].y + eyes[0].height*0.5 );
float radius0 = (eyes[0].width + eyes[0].height)*0.25 ;
Point center1( faces[i].x + eyes[1].x + eyes[1].width*0.5, faces[i].y + eyes[1].y + eyes[1].height*0.5 );
float radius1 = (eyes[1].width + eyes[1].height)*0.25 ;
p[2].x= (float) center0.x - radius0;
p[2].y= (float) center0.y + radius0;
p[1].x= (float) center0.x - radius0;
p[1].y= (float) center0.y - radius0;
p[3].x= (float) center1.x + radius1;
p[3].y= (float) center1.y + radius1;
p[0].x= (float) center1.x + radius1;
p[0].y= (float) center1.y - radius1;
}
else{
Point center0( faces[i].x + eyes[1].x + eyes[1].width*0.5, faces[i].y + eyes[1].y + eyes[1].height*0.5 );
float radius0 = (eyes[1].width + eyes[1].height)*0.25 ;
Point center1( faces[i].x + eyes[0].x + eyes[0].width*0.5, faces[i].y + eyes[0].y + eyes[0].height*0.5 );
float radius1 = (eyes[0].width + eyes[0].height)*0.25 ;
p[2].x= (float) center0.x - radius0;
p[2].y= (float) center0.y + radius0;
p[1].x= (float) center0.x - radius0;
p[1].y= (float) center0.y - radius0;
p[3].x= (float) center1.x + radius1;
p[3].y= (float) center1.y + radius1;
p[0].x= (float) center1.x + radius1;
p[0].y= (float) center1.y - radius1;
}
cvGetPerspectiveTransform(q,p,warp_matrix);
cvZero(neg_img);
cvZero(cpy_img);
cvWarpPerspective( pic, neg_img, warp_matrix);
cvWarpPerspective( blank, cpy_img, warp_matrix);
cvNot(cpy_img,cpy_img);
cvAnd(cpy_img,image_n,cpy_img);
cvOr(cpy_img,neg_img,image_n);
}
}
cvSaveImage(filename_new_after,image_n);
cvWriteFrame(vdowriter,image_n);
cout<<"Read file filename"<< n <<endl;
}
else{
flag=true;
}
fin.close();
n++;
}
cvReleaseVideoWriter(&vdowriter);
cvReleaseImage(&pic);
cvReleaseImage(&imga);
cvReleaseImage(&disp);
cvReleaseImage(&neg_img);
cvReleaseImage(&cpy_img);
cvReleaseImage(&image_n);
}
int process(VideoCapture& capture) {
char strFrame[]="/root/opencv/newtutorial/mydirnext";
if(mkdir(strFrame,0777)==-1)
{
cout<<"Error Trying to delete"<<endl;
if(system("rm -r /root/opencv/newtutorial/mydirnext")){
cout << "Directory successfully deleted"<<endl;
}
if(mkdir(strFrame,0777)==-1){
cout << "Error Again creating directory" << endl;
}
}
int n = 0;
char filename[200];
string window_name = "video | q or esc to quit";
cout << "press space to save a picture. q or esc to quit" << endl;
namedWindow(window_name, CV_WINDOW_KEEPRATIO);
Mat frame;
for (;;) {
capture >> frame;
if (frame.empty())
continue;
imshow(window_name, frame);
sprintf(filename,"/root/opencv/newtutorial/mydirnext/filename%.3d.jpg",n++);
imwrite(filename,frame);
char key = (char)waitKey(5);
switch (key) {
case 27:
if(make==0){
make=1;
makevdo();
}
return 0;
default:
break;
}
}
return 0;
}
}
int main(int ac, char** av) {
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
if (ac != 2) {
return 1;
}
std::string arg = av[1];
VideoCapture capture(arg);
if (!capture.isOpened())
capture.open(atoi(arg.c_str()));
if (!capture.isOpened()) {
cerr << "Failed to open a video device or video file!\n" << endl;
return 1;
}
return process(capture);
}
Sorry for posting so many Images SO, but No other way to explain my problem.
Start by extracting everything to methods/functions that you can be given a sensible name. We don't want to see methods longer than 10 lines. The images are not helpful at all. Remove the overlay and show what the algorithm claims to recognize, when it does so.
After you've done that, feed it sequences of the same images. First the ones where it recognizes, then those where it doesn't. That way you can get a better guess where the problem is. But first clean up the messy code.