OpenCv and Visual C++ Eyedetection - visual-c++

I'm writing a software for eye detection in a webcam stream. I'm using OpenCV in Visual Studio but when I load the haarcascade file, I get an unhandled exception and in the output:
OpenCV error: NULL pointer <NULL or empty buffer> in unknow function,
file ....persistence.cpp
Here is the code:
#include <opencv2/core/core.hpp>
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
/** Function Headers */
void detectAndDisplay( Mat frame );
/** Global variables */
String face_cascade_name = "C:/opencv/data/haarcascades/haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "C:/opencv/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
/** #function main */
int main( int argc, const char** argv )
{
CvCapture* capture;
Mat frame;
int a;
//-- 1. Load the cascades
if (!face_cascade.load( face_cascade_name) ) {
cout << "Couldn't load face_cascade" << endl;
exit(-1);
}
if (!eyes_cascade.load( eyes_cascade_name) ) {
cout << "Couldn't load face_cascade" << endl;
exit(-1);
}
cout << "Loaded cascade" << endl;
//-- 2. Read the video stream
capture = cvCaptureFromCAM( -1 );
if( capture )
{
while( true )
{
frame = cvQueryFrame( capture );
//-- 3. Apply the classifier to the frame
if( !frame.empty() )
{ detectAndDisplay( frame ); }
else
{ printf(" --(!) No captured frame -- Break!"); break; }
int c = waitKey(10);
if( (char)c == 'c' ) { break; }
}
}
return 0;
}
/** #function detectAndDisplay */
void detectAndDisplay( Mat frame )
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Detect faces
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( int i = 0; i < faces.size(); i++ )
{
Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360,
Scalar( 255, 0, 255 ), 4, 8, 0 );
Mat faceROI = frame_gray( faces[i] );
std::vector<Rect> eyes;
//-- In each face, detect eyes
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30,30) );
for( int j = 0; j < eyes.size(); j++ )
{
Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );
}
}
//-- Show what you got
imshow( window_name, frame );
}
I've done all the inclusion to make OpenCV working with Visual Studio and the cascade classifier are in the correct path so I don't know why this code don't work.
Ah, I've exception too when I try the sample facerecognition.cpp.
Any help is appreciated.
EDIT:
I've tried with the help of Barnabas but the exception is the same.
But maybe I found out something. If I delete the code
if (!eyes_cascade.load( eyes_cascade_name) ) {
cout << "Couldn't load face_cascade" << endl;
exit(-1);
}
The exception comes after the opening of webcam's software and if I continue the result is a frame (only one) where I can see my face recognized. So if I delete the control on the loading of the eye cascade classifier, the problem delay.
New ideas?

Basically, the problem is that you are mixing up the C++ and the C interface.
The camera capture is not CvCapture*. Here is how to capture from webcam (or from video-stream) correctly:
using namespace cv;
VideoCapture cap(0); // 0 for webcam input
if(cap.isOpened()) // use this instead of if( capture )
cap >> frame; // instead of cvQueryFrame

This issue was driving me insane when I realised it was possibly something to do with the program using the wrong dlls for some reason; I haven't figured out why yet. My hunch was that my OPENCV_DIR enviroment variable was set to on older version of OpenCV but having checked I have set it to the newer version.
Any how, to get working code in VS 2012 (vc11) I did the following:
open the properties page and go to Configuration Properties > Debugging and add to the Environement variable "path=C:/OpenCV2_4_5/build/x86/vc11/bin;%PATH%" without the quotation marks. Obviously, your path to that bin folder may be different.
Hope this helps.

Related

Unhandled exception at 0x000007FEDF2C9120 (gdal202.dll) in GdalTest.exe: 0xC0000005: Access violation reading location 0x0000000000000058

I try using CreateCopy(), it seem in thrown me an exception when i run the program
Unhandled exception at 0x000007FEDF2C9120 (gdal202.dll) in GdalTest.exe: 0xC0000005: Access violation reading location 0x0000000000000058.
It will display this output on the console:
I try debug on the exception occurs, on the call stack it will go to the new tab then display no symbol loaded
I hope someone can explain to me what file not be loaded and if the console can view raster map it is will throw an error or exception ?
Below is my code if someone want to copy and make reference it just i have issues on "Using CreateCopy()" part.
Thank you and best regards,
// GdalTest.cpp : Defines the entry point for the console application.
//
#include "cpl_conv.h" // for CPLMalloc()
#include "stdafx.h"
#include "gdal.h"
#include <stdlib.h>
#include <stdio.h>
#include "iostream"
#include "cpl_string.h"
#include "gdal_priv.h"
class GDALMajorObject;
class GDALDataset;
class GDALRasterBand;
class GDALDriver;
class GDALRasterAttributeTable;
class GDALProxyDataset;
class GDALProxyRasterBand;
class GDALAsyncReader;
int main(int argc,char* argv)
{
///*/*/*/*/*/*/*/*/*/*Getting Dataset Information*/*/*/*/*/*/*/*/*/*/
GDALDataset *poDataset;
//GDALDatasetH *poDatasetH;
const char* Raster = new char[256];
double adfGeoTransform[6];
GDALAllRegister();
Raster = "C:\\Users\\User\\Desktop\\DSI REFERENCE\\Map Data\\Raster\\4257.tif";
poDataset = (GDALDataset *) GDALOpen(Raster, GA_ReadOnly )CPL_WARN_UNUSED_RESULT;
//poDataset = (GDALDataset *) GDALOpen(Raster, GA_ReadOnly );
if( poDataset == NULL )
{
printf("Not found");
}
else
{
printf( "Driver: %s/%s\n",
poDataset->GetDriver()->GetDescription(),
poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );
printf( "Size is %dx%dx%d\n",
poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
poDataset->GetRasterCount() );
if( poDataset->GetProjectionRef() != NULL )
printf( "Projection is `%s'\n", poDataset->GetProjectionRef() );
if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
{
printf( "Origin = (%.6f,%.6f)\n",
adfGeoTransform[0], adfGeoTransform[3] );
printf( "Pixel Size = (%.6f,%.6f)\n",
adfGeoTransform[1], adfGeoTransform[5] );
}
}
///*/*/*/*/*/*/*/*/*/* Fetching a Raster Band*/*/*/*/*/*/*/*/*/*/
GDALRasterBand *poBand;
int nBlockXSize, nBlockYSize;
int bGotMin, bGotMax;
double adfMinMax[2];
poBand = poDataset->GetRasterBand( 1 );
poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
printf( "Block=%dx%d Type=%s, ColorInterp=%s\n", nBlockXSize, nBlockYSize,GDALGetDataTypeName(poBand->GetRasterDataType()),
GDALGetColorInterpretationName( poBand->GetColorInterpretation()) );
adfMinMax[0] = poBand->GetMinimum( &bGotMin );
adfMinMax[1] = poBand->GetMaximum( &bGotMax );
if( ! (bGotMin && bGotMax) )
GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
if( poBand->GetOverviewCount() > 0 )
printf( "Band has %d overviews.\n", poBand->GetOverviewCount() );
if( poBand->GetColorTable() != NULL )
printf( "Band has a color table with %d entries.\n",
poBand->GetColorTable()->GetColorEntryCount() );
// make it 256 bytes for a string length of 255 plus null (\0) terminator
///*/*/*/*/*/*/*/*/*/*/*Reading Raster Data*/*/*/*/*/*/*/*/*/*/*/
float *pafScanline;
int nXSize = poBand->GetXSize();
pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
poBand->RasterIO( GF_Read, 0, 0, nXSize, 1,pafScanline, nXSize, 1, GDT_Float32,0, 0 );
///*/*/*/*/*/*/*/*/*/*/*Techniques for Creating Files (determine whether it supports Create() and/or CreateCopy().) */*/*/*/*/*/*/*/*/*/*/
const char *pszFormat = "GTiff";
GDALDriver *poDriver;
char **papszMetadata;
poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
if( poDriver == NULL )
exit( 1 );
papszMetadata = poDriver->GetMetadata();
if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
printf( "Driver %s supports Create() method.\n", pszFormat );
if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
printf( "Driver %s supports CreateCopy() method.\n", pszFormat );
///*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*Using CreateCopy()*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
const char*pszDstFilename= new char[256];
GDALDataset *poSrcDS =(GDALDataset *) GDALOpen( pszDstFilename, GA_ReadOnly );
GDALDataset *poDstDS;
poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,NULL, NULL, NULL );
/* Once we're done, close properly the dataset */
if( poDstDS != NULL )
GDALClose( (GDALDatasetH) poDstDS );
GDALClose( (GDALDatasetH) poSrcDS );
std::cin.get();
//delete[] Raster;// release the memory VERY IMPORTANT
}
You haven't set the variable pszDstFilename to anything meaningful. You allocated it, but it just contains random junk. You need to put a valid existing dataset into it for anything useful to happen in the call to GDALOpen(). The documentation states:
Once the drivers are registered, the application should call the free standing GDALOpen() function to open a dataset, passing the name of the dataset and the access desired (GA_ReadOnly or GA_Update).

Unhandled exception , access violation in opencv cvCaptureFromCAM using Visual c++

I am trying to build a program in Opencv that captures a video and saves it to a file. However, after repeated efforts I continue to get this error : Unhandled exception at 0x201e8efb in basic.exe: 0xC0000005 Access violation, where basic.cpp is my file name.
The same occurs when trying to capture an image.
I have already tried changing cvCaptureFromCAM parameters to CV_CAP_ANY/0/-1/-2/1/2..but none of these worked out.My webcam, works perfectly well for others applications and i have tested it online.
Any help would be greatly appreciated .Thanks in advance.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "C:\opencv\build\include\opencv2\core\core.hpp"
#include "C:\opencv\build\include\opencv2\highgui\highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void main( ){
CvCapture *capture = cvCaptureFromCAM( 0 );
int width = ( int )cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH );
int height = ( int )cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT );
CvVideoWriter *writer = cvCreateVideoWriter( "myCamCapture.avi", -1, 30, cvSize( width, height ) );
cvNamedWindow("camopen", CV_WINDOW_AUTOSIZE);
IplImage *frame = 0;
while( 1 )
{
frame = cvQueryFrame( capture );
cvShowImage("d",frame);
cvWriteFrame( writer, frame );
char c = cvWaitKey( 30 );
if( c == 27 ) break;
}
}
please, since you're a beginner, don't start with the deprecated c-api, use the c++ one instead.
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
using namespace cv;
int main()
{
VideoCapture cap(0);
while( cap.isOpened() )
{
Mat frame;
if ( ! cap.read(frame) )
break;
imshow("lalala",frame);
int k = waitKey(10);
if ( k==27 )
break;
}
return 0;
}
regarding your error: please triple-check the libs you're linking (compiler version, debug/release, 32/64bit). you're not allowed to mix different settings there

migrating code from Microsoft Visual C++ to debian (raspberry)

My English is not very good (im from Chile) but will try to explain in the best way possible (+ google translator :P)
well im working in Microsoft Visual C++ 2010 express and I need to migrate my opencv code to Linux to work on a rapsberry
Here the code:
#include "StdAfx.h"
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv\cv.h>
//#include <iostream>
using namespace cv;
int main( int argc, char** argv )
{
//Variable
CvCapture* capture = 0;
IplImage* frame = 0;
IplImage* frame_black = 0;
IplImage* frame_blue = 0;
IplImage* frame_red = 0;
//IplImage* red_gray = 0;
//Verifica Camara
capture = cvCaptureFromCAM(1);
if( !cvGrabFrame( capture )){
printf("error cámara");
exit(0);
}
//Comienza
for(;;){
// Captura imagen from camara
frame = cvQueryFrame(capture);
if( !frame ) break;
// filtro negro
frame_black = cvCreateImage(cvGetSize(frame),8,3);
CvScalar r,g;
for(int i=0;i<(frame->height);i++){
for(int j=0;j<(frame->width);j++){
r=cvGet2D(frame,i,j);
if((r.val[2]<80)&&(r.val[1]<80)&&(r.val[0]<80)){
g.val[2]=0;
g.val[1]=0;
g.val[0]=0;
cvSet2D(frame_black,i,j,g);
}
else{
g.val[2]=255;
g.val[1]=255;
g.val[0]=255;
cvSet2D(frame_black,i,j,g);
}
}
}
// filtro azul
frame_blue = cvCreateImage(cvGetSize(frame),8,3);
CvScalar s,c;
for(int i=0;i<(frame->height);i++){
for(int j=0;j<(frame->width);j++){
s=cvGet2D(frame,i,j);
if((s.val[2]<100)&&(s.val[1]<100)&&(s.val[0]>100)){
c.val[2]=0;
c.val[1]=0;
c.val[0]=255;
cvSet2D(frame_blue,i,j,c);
}
else{
c.val[2]=255;
c.val[1]=255;
c.val[0]=255;
cvSet2D(frame_blue,i,j,c);
}
}
}
// filtro rojo
frame_red = cvCreateImage(cvGetSize(frame),8,3);
CvScalar p,q;
for(int i=0;i<(frame->height);i++){
for(int j=0;j<(frame->width);j++){
p=cvGet2D(frame,i,j);
if((p.val[2]>100)&&(p.val[1]<100)&&(p.val[0]<100)){
q.val[2]=255;
q.val[1]=0;
q.val[0]=0;
cvSet2D(frame_red,i,j,q);
}
else{
q.val[2]=255;
q.val[1]=255;
q.val[0]=255;
cvSet2D(frame_red,i,j,q);
}
}
}
/* filtro hough
red_gray = cvCreateImage(cvGetSize(frame),8,1);
cvCvtColor( frame_red, red_gray, CV_BGR2GRAY);
cvSmooth(red_gray, red_gray, CV_BLUR,3);
CvMemStorage* storage_var = cvCreateMemStorage(0);
CvSeq* results = cvHoughCircles(red_gray, storage_var , CV_HOUGH_GRADIENT , 2, red_gray->height/3 );
// reemplaza
for( int i = 0; i < results->total; i++ ){
float* p = (float*) cvGetSeqElem( results, i );
CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] ));
cvCircle(red_gray,pt,cvRound( p[2] ),cvScalar(0,0,255),1.8);
}
*/
// mostrar en ventana
cvShowImage("ventana",frame_black);
if( cvWaitKey( 10 ) >= 0 )
break;
}
//Libera de memoria
cvReleaseCapture( &capture);
cvReleaseImage( &frame);
cvReleaseImage( &frame_black);
cvReleaseImage( &frame_blue);
cvReleaseImage( &frame_red);
//cvReleaseImage( &red_gray);
return 0;
}
copying and pasting the code into a file "codigo.c" and compiling (in linux terminal) with
gcc codigo.c -o codigo $(pkg-config --cflags --libs opencv)
I have the following error
codigo.c:3:21 fatal error: StdAfx.h: No such file or directory
compilation terminated.
well, google told me that StdAfx.h is a header of microsoft visual c++
and here i crash :l
i dont know what can i do now
I hope someone can tell me some way to go to fix this problem
thx to all
As your code does not depend on anything other than opencv, you can just leave out the stdafx header. it's a feature of visual studio that you dont need here.
( see Purpose of stdafx.h )
it compiles fine on my machine. with:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv/cv.h>
note the "/". please use these instead of backslashes here, or unix machines will complain.
also: use g++ to compile this code, not gcc.

Problems with SDL Audio (No output)

I'm facing some problems with understanding how the SDL audio callback works.
I have this simple code, which should generate a simple square wave:
#include "SDL.h"
#include "SDL_audio.h"
#include <stdlib.h>
#include <math.h>
SDL_Surface *screen;
SDL_AudioSpec spec;
Uint32 sound_len=512;
Uint8 *sound_buffer;
int sound_pos = 0;
int counter;
unsigned int phase_delta=600;
unsigned int phase;
unsigned char out;
//Initialization
void init_sdl (void)
{
if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0)
exit (-1);
atexit (SDL_Quit);
screen = SDL_SetVideoMode (640, 480, 16, SDL_HWSURFACE);
if (screen == NULL)
exit (-1);
}
//Generates a new sample and outputs it to the audio card
void Callback (void *userdata, Uint8 *stream, int len)
{
Uint8 *waveptr;
//Generates a new sample
phase+=phase_delta;
if ((phase>>8)<127) out=255; else out=0;
//End
//Output the current sample to the audio card
waveptr = sound_buffer;
SDL_MixAudio(stream, waveptr, 1, SDL_MIX_MAXVOLUME);
}
void play (void)
{
sound_buffer = new Uint8[512];
sound_len= 512;
spec.freq = 22050;
spec.format = AUDIO_S16SYS;
spec.channels = 1;
spec.silence = 0;
spec.samples = 512;
spec.padding = 0;
spec.size = 0;
spec.userdata = 0;
spec.callback = Callback;
if (SDL_OpenAudio (&spec, NULL) < 0)
{ //Throw an error
printf ("I don't think you like this: %s\n", SDL_GetError ());
exit (-1);
}
SDL_PauseAudio (0);//Start the audio
}
int main(int argc, char* argv[])
{
init_sdl ();
play ();
SDL_Delay (250);
return 0;
}
I know that the callback is not done right, because I have no idea how to output to the buffer. Each time the callback is called, the first part of the callback function code generates the new sample, and stores it in the variabile Out.
Can anyone here modify this code so that the new samples go from Out to the correct position in the audio buffer?
Also, I don't want to have the code modified in a very super-complex way just to generate the square wave - I have already taken care of that. The wave is generated correctly, each new sample appearing in the variable Out. I just need these samples to be routed correctly to the audio buffer.
You need to cast stream to a actual.format-appropriate datatype and then overwrite the values in stream with len / sizeof( <format's datatype> ) samples.
The square-wave will be kinda hard to hear because the given algorithm will only generate a brief high pulse every ~7.1 million samples (~5 minutes #22050Hz) when phase wraps around.
Try something like this:
#include <SDL.h>
#include <SDL_audio.h>
#include <iostream>
using namespace std;
//Generates new samples and outputs them to the audio card
void Callback( void* userdata, Uint8* stream, int len )
{
// the format of stream depends on actual.format in main()
// we're assuming it's AUDIO_S16SYS
short* samples = reinterpret_cast< short* >( stream );
size_t numSamples = len / sizeof( short );
const unsigned int phase_delta = 600;
static unsigned int phase = 0;
// loop over all our samples
for( size_t i = 0; i < numSamples; ++i )
{
phase+=phase_delta;
short out = 0;
if ((phase>>8)<127) out=SHRT_MAX; else out=0;
samples[i] = out;
}
}
int main( int argc, char* argv[] )
{
if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) < 0 )
return -1;
atexit( SDL_Quit );
SDL_Surface* screen = SDL_SetVideoMode( 640, 480, 16, SDL_ANYFORMAT );
if( screen == NULL)
return -1;
SDL_AudioSpec spec;
spec.freq = 22050;
spec.format = AUDIO_S16SYS;
spec.channels = 1;
spec.samples = 4096;
spec.callback = Callback;
spec.userdata = NULL;
SDL_AudioSpec actual;
if( SDL_OpenAudio( &spec, &actual ) < 0 )
{
cerr << "I don't think you like this: " << SDL_GetError() << endl;
return -1;
}
if( spec.format != actual.format )
{
cerr << "format mismatch!" << endl;
return -1;
}
SDL_PauseAudio( 0 );
SDL_Event ev;
while( SDL_WaitEvent( &ev ) )
{
if( ev.type == SDL_QUIT )
break;
}
SDL_CloseAudio();
SDL_Quit();
return 0;
}

opencv draw point and line between 2 points

how to draw point and line between 2 points in opencv??? Would like by clicking in image using mouse draw points and connect them.
See Drawing Functions specifically cv::Line
look at the included samples called drawing.py and inpaint.py or their c++ equivalents.
The Sketcher class inside inpaint.py is probably what you are looking for.
Using the Mouse functions in opencv is a real chore. If it helps, here is my code example of drawing rectangles on video. Its fully functional so you can just cut and paste the whole thing. You should be able to pick it apart and see how mouse handling works.
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#define SSTR( x ) dynamic_cast< std::ostringstream & >(( std::ostringstream() << std::dec << x ) ).str()
using namespace std;
using namespace cv;
Rect box;
bool drawing_box = false;
struct mousecallbackstruct{
Mat* src;
Mat* overlay;
string windowname;
};
Mat srcoverlay,smallsrcoverlay;
void onMouse(int event, int x, int y, int flags, void* param) //it seems the only way to use this is by keeping different globals for different windows - meaning you have to set up all thise ahead of time, and keep track of it and not mix/match windows/frames!! horrible design here.
{
cout << event;
mousecallbackstruct mousestruct;
mousestruct = *((mousecallbackstruct*)param);
Mat* srcp = mousestruct.src;
Mat* overlayp = mousestruct.overlay;
Mat src = *srcp;
Mat overlay = *overlayp;
if(!src.data){
cout << "your void * cast didn't work :(\n";
return;
}
switch( event ){
case CV_EVENT_MOUSEMOVE:
if( drawing_box ){
box.width = x-box.x;
box.height = y-box.y;
}
break;
case CV_EVENT_LBUTTONDOWN: //start drawing
drawing_box = true;
box = cvRect( x, y, 0, 0 );
break;
case CV_EVENT_LBUTTONDBLCLK: //double click to clear
drawing_box = false;
overlay.setTo(cv::Scalar::all(0)); //clear it
break;
case CV_EVENT_LBUTTONUP: //draw what we created with Lbuttondown
drawing_box = false;
if( box.width < 0 ){
box.x += box.width;
box.width *= -1;
}
if( box.height < 0 ){
box.y += box.height;
box.height *= -1;
}
rectangle( overlay, Point(box.x, box.y), Point(box.x+box.width,box.y+box.height),CV_RGB(100,200,100),4); //draw rectangle. You can change this to line or circle or whatever. Maybe with the Right mouse button.
break;
}
}
void iimshow(mousecallbackstruct* mystructp){ //this is where we add the text/drawing created in the mouse handler to the actual image (since mouse handler events do not line up with the drawing events)
mousecallbackstruct mystruct = *mystructp; //custom struct made for the mouse callback - very handy for other functions too
Mat overlay, src;
Mat* srcp = mystruct.src;
Mat* overlayp = mystruct.overlay;
src = *srcp; // yeah, yeah, i use 9 lines where I could use 3, so sue me
overlay = *overlayp;
string name = mystruct.windowname;
Mat added,imageROI;
try{
//cout << "tch:" << overlay.rows << "," << src.rows << ";" << overlay.cols << "," << src.cols << ";" << src.channels() << "," << overlay.channels() <<"," << src.type() << "," << overlay.type() << "\n";
if(overlay.data && overlay.rows == src.rows && overlay.cols == src.cols && overlay.channels() == src.channels()){ //basic error checking
add(src,overlay,added);
}else{
//try to resize it
imageROI= overlay(Rect(0,0,src.cols,src.rows));
add(src,imageROI,added);
}
imshow(name,added);// the actual draw moment
}catch(...){ //if resize didn't work then this should catch it
cout << "Error. Mismatch:" << overlay.rows << "," << src.rows << ";" << overlay.cols << "," << src.cols << ";" << src.channels() << "," << overlay.channels() <<"," << src.type() << "," << overlay.type() << "\n";
imshow(name + "overlay",overlay);
imshow(name+"source",src);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) { // check if we succeeded
cout << "NO camera found \n";
return -1;
}
Mat src,smallsrc,overlay;
cap >> src; //grab 1 frame to build our preliminary Mats and overlays
srcoverlay.create(src.rows,src.cols,src.type()); //create overlays
smallsrcoverlay.create(src.rows,src.cols,src.type());
srcoverlay.setTo(cv::Scalar::all(0)); //clear it
smallsrcoverlay.setTo(cv::Scalar::all(0)); //clear it
namedWindow( "smallsrc", CV_WINDOW_AUTOSIZE );
namedWindow( "source", CV_WINDOW_AUTOSIZE ); //these must be created early for the setmousecallback, AND you have to know what Mats will be using them and not switch them around :(
moveWindow("smallsrc",2000,100); //create a small original capture off to the side of screen
////////////// for each window/mat that uses a mouse handler, you must create one of these structures for it and pass it into the mouse handler
mousecallbackstruct srcmousestruct,smallsrcmousestruct; //these get passed into the mouse callback function. Hopefully they update their contents automatically for the callback? :(
srcmousestruct.overlay = &srcoverlay; //fill our custom struct
srcmousestruct.src = &src;
srcmousestruct.windowname = "source";
smallsrcmousestruct.overlay = &smallsrcoverlay; //the small window
smallsrcmousestruct.src = &smallsrc;
smallsrcmousestruct.windowname = "smallsrc";
setMouseCallback(smallsrcmousestruct.windowname, onMouse, (void*)&smallsrcmousestruct); //the actual 'set mouse callback' call
setMouseCallback(srcmousestruct.windowname, onMouse, (void*)&srcmousestruct);
for(;;){ //main loop
/// Load an image
cap >> src;
if( !src.data )
{ return -1; }
resize(src,smallsrc,Size(),.5,.5); //smaller scale window of original
overlay = *srcmousestruct.overlay;
src = *srcmousestruct.src;
iimshow(&srcmousestruct); //my imshow replacement. uses structs
iimshow(&smallsrcmousestruct);
if(waitKey(30) == 27) cin.get(); //esc pauses
}
cin.get();
return 0;
}

Resources