Load an OpenCV::Mat as a .pgm - opencv

I have a program which loads a .PGM image file into std::vector m_data :
void LoadPgm( std::string const& filename ){
std::ifstream in( filename.c_str(), std::ios::binary );
if ( !in ){
std::cerr << "Error in Image::LoadPgm: Could not open file " << filename << std::endl;
std::exit(1);
}
std::string data = std::string( std::istreambuf_iterator< char >( in ),
std::istreambuf_iterator< char >() );
if ( ( data[0] != 'p' && data[0] != 'P' ) || data[1] != '5' ){
std::cerr << "Error in Image::LoadPgm: Unsupported image format " << filename << std::endl;
std::exit(1);
}
unsigned char const* p = reinterpret_cast< unsigned char* >(&data[2]);
m_width = ReadNumber( p );
m_height = ReadNumber( p );
if ( ReadNumber( p ) > 255 )
{
std::cerr << "Error in Image::LoadPgm: Unsupported image deep "
<< filename << std::endl;
std::exit(1);
}
p++;
m_data.assign( p, p + m_width * m_height );
}
Where the ReadNumber() is :
unsigned long ReadNumber(unsigned char const*&buffer){
do{
if ( *(buffer++) == '#' ){
while ( *(buffer++) != 10 );
}
switch (*buffer)
{
case 9 :
case 10 :
case 13 :
case ' ' :
case '#' :
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' : break;
default :
{
std::cerr << "Error in Image::LoadPgm: invalid data" << std::endl;
exit( 1 );
}
}
}
while ( (*buffer < '0') || (*buffer > '9') );
unsigned long value = 0;
do
{
value = 10 * value;
value += *(buffer++) - '0';
}
while ( (*buffer>='0') && (*buffer<='9') );
return value;
}
My question is how can I load, instead of .pgm file, an OpenCV Mat into m_data (without creating a file).
EDIT
Here is my solution (thanks to ypnos) :
void LoadPgm(cv::Mat1b &cvimg ){
Mat1b matimage;
cvtColor(cvimg, matimage, CV_RGB2GRAY);
// Create a pgm object
std::vector<unsigned char> dest(matimage.rows*matimage.cols);
std::copy(matimage.begin(), matimage.end(), dest.begin());
std::stringstream in;
in << "P5" << std::endl;
in << matimage.cols << std::endl;
in << matimage.rows << std::endl;
in << "255" << std::endl;
in.write( reinterpret_cast<char*>( &dest[0] ), matimage.cols * matimage.rows );
std::string data = std::string( std::istreambuf_iterator< char >( in ), std::istreambuf_iterator< char >() );
if ( ( data[0] != 'p' && data[0] != 'P' ) || data[1] != '5' ){
std::cerr << "Error in Image::LoadPgm: Unsupported image format " << std::endl;
std::exit(1);
}
unsigned char const* p = reinterpret_cast< unsigned char* >(&data[2]);
m_width = ReadNumber( p );
m_height = ReadNumber( p );
if ( ReadNumber( p ) > 255 ){
std::cerr << "Error in Image::LoadPgm: Unsupported image deep" << std::endl;
std::exit(1);
}
p++;
m_data.assign( p, p + m_width * m_height );
}

If you want to reliably copy all pixels of a 1 channel unsigned char matrix into an array, do this:
cv::Mat1u source = …
std::vector<unsigned char> dest(source.rows*source.cols);
std::copy(source.begin(), source.end(), dest.begin());

Related

How to track the 2d points over the images for 3d-reconstruction as specified in opencv sfm pipeline?

I am trying to do 3D reconstruction using this code from opencv. As far as I understood, I need a textfile with the 2D points as per the given format. I am wondering if anyone could help me in getting these 2D points they mention in this program. I have a set of images with the calibration parameters but I have been not able to understand how could I track and save these 2D points e.g. the first point in frame 1 is the same point in frame 2 in the format they specified .
#include <opencv2/core.hpp>
#include <opencv2/sfm.hpp>
#include <opencv2/viz.hpp>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
using namespace cv;
using namespace cv::sfm;
static void help() {
cout
<< "\n------------------------------------------------------------\n"
<< " This program shows the camera trajectory reconstruction capabilities\n"
<< " in the OpenCV Structure From Motion (SFM) module.\n"
<< " \n"
<< " Usage:\n"
<< " example_sfm_trajectory_reconstruction <path_to_tracks_file> <f> <cx> <cy>\n"
<< " where: is the tracks file absolute path into your system. \n"
<< " \n"
<< " The file must have the following format: \n"
<< " row1 : x1 y1 x2 y2 ... x36 y36 for track 1\n"
<< " row2 : x1 y1 x2 y2 ... x36 y36 for track 2\n"
<< " etc\n"
<< " \n"
<< " i.e. a row gives the 2D measured position of a point as it is tracked\n"
<< " through frames 1 to 36. If there is no match found in a view then x\n"
<< " and y are -1.\n"
<< " \n"
<< " Each row corresponds to a different point.\n"
<< " \n"
<< " f is the focal lenght in pixels. \n"
<< " cx is the image principal point x coordinates in pixels. \n"
<< " cy is the image principal point y coordinates in pixels. \n"
<< "------------------------------------------------------------------\n\n"
<< endl;
}
/* Build the following structure data
*
* frame1 frame2 frameN
* track1 | (x11,y11) | -> | (x12,y12) | -> | (x1N,y1N) |
* track2 | (x21,y11) | -> | (x22,y22) | -> | (x2N,y2N) |
* trackN | (xN1,yN1) | -> | (xN2,yN2) | -> | (xNN,yNN) |
*
*
* In case a marker (x,y) does not appear in a frame its
* values will be (-1,-1).
*/
void
parser_2D_tracks(const string &_filename, std::vector<Mat> &points2d )
{
ifstream myfile(_filename.c_str());
if (!myfile.is_open())
{
cout << "Unable to read file: " << _filename << endl;
exit(0);
} else {
double x, y;
string line_str;
int n_frames = 0, n_tracks = 0;
// extract data from text file
vector<vector<Vec2d> > tracks;
for ( ; getline(myfile,line_str); ++n_tracks)
{
istringstream line(line_str);
vector<Vec2d> track;
for ( n_frames = 0; line >> x >> y; ++n_frames)
{
if ( x > 0 && y > 0)
track.push_back(Vec2d(x,y));
else
track.push_back(Vec2d(-1));
}
tracks.push_back(track);
}
// embed data in reconstruction api format
for (int i = 0; i < n_frames; ++i)
{
Mat_<double> frame(2, n_tracks);
for (int j = 0; j < n_tracks; ++j)
{
frame(0,j) = tracks[j][i][0];
frame(1,j) = tracks[j][i][1];
}
points2d.push_back(Mat(frame));
}
myfile.close();
}
}
/* Keyboard callback to control 3D visualization
*/
bool camera_pov = false;
void keyboard_callback(const viz::KeyboardEvent &event, void* cookie)
{
if ( event.action == 0 &&!event.symbol.compare("s") )
camera_pov = !camera_pov;
}
/* Sample main code
*/
int main(int argc, char** argv)
{
// Read input parameters
if ( argc != 5 )
{
help();
exit(0);
}
// Read 2D points from text file
std::vector<Mat> points2d;
parser_2D_tracks( argv[1], points2d );
// Set the camera calibration matrix
const double f = atof(argv[2]),
cx = atof(argv[3]), cy = atof(argv[4]);
Matx33d K = Matx33d( f, 0, cx,
0, f, cy,
0, 0, 1);
bool is_projective = true;
vector<Mat> Rs_est, ts_est, points3d_estimated;
reconstruct(points2d, Rs_est, ts_est, K, points3d_estimated, is_projective);
// Print output
cout << "\n----------------------------\n" << endl;
cout << "Reconstruction: " << endl;
cout << "============================" << endl;
cout << "Estimated 3D points: " << points3d_estimated.size() << endl;
cout << "Estimated cameras: " << Rs_est.size() << endl;
cout << "Refined intrinsics: " << endl << K << endl << endl;
cout << "3D Visualization: " << endl;
cout << "============================" << endl;
viz::Viz3d window_est("Estimation Coordinate Frame");
window_est.setBackgroundColor(); // black by default
window_est.registerKeyboardCallback(&keyboard_callback);
// Create the pointcloud
cout << "Recovering points ... ";
// recover estimated points3d
vector<Vec3f> point_cloud_est;
for (int i = 0; i < points3d_estimated.size(); ++i)
point_cloud_est.push_back(Vec3f(points3d_estimated[i]));
cout << "[DONE]" << endl;
cout << "Recovering cameras ... ";
vector<Affine3d> path_est;
for (size_t i = 0; i < Rs_est.size(); ++i)
path_est.push_back(Affine3d(Rs_est[i],ts_est[i]));
cout << "[DONE]" << endl;
cout << "Rendering Trajectory ... ";
cout << endl << "Press: " << endl;
cout << " 's' to switch the camera pov" << endl;
cout << " 'q' to close the windows " << endl;
if ( path_est.size() > 0 )
{
// animated trajectory
int idx = 0, forw = -1, n = static_cast<int>(path_est.size());
while(!window_est.wasStopped())
{
for (size_t i = 0; i < point_cloud_est.size(); ++i)
{
Vec3d point = point_cloud_est[i];
Affine3d point_pose(Mat::eye(3,3,CV_64F), point);
char buffer[50];
sprintf (buffer, "%d", static_cast<int>(i));
viz::WCube cube_widget(Point3f(0.1,0.1,0.0), Point3f(0.0,0.0,-0.1), true, viz::Color::blue());
cube_widget.setRenderingProperty(viz::LINE_WIDTH, 2.0);
window_est.showWidget("Cube"+string(buffer), cube_widget, point_pose);
}
Affine3d cam_pose = path_est[idx];
viz::WCameraPosition cpw(0.25); // Coordinate axes
viz::WCameraPosition cpw_frustum(K, 0.3, viz::Color::yellow()); // Camera frustum
if ( camera_pov )
window_est.setViewerPose(cam_pose);
else
{
// render complete trajectory
window_est.showWidget("cameras_frames_and_lines_est", viz::WTrajectory(path_est, viz::WTrajectory::PATH, 1.0, viz::Color::green()));
window_est.showWidget("CPW", cpw, cam_pose);
window_est.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
}
// update trajectory index (spring effect)
forw *= (idx==n || idx==0) ? -1: 1; idx += forw;
// frame rate 1s
window_est.spinOnce(1, true);
window_est.removeAllWidgets();
}
}
return 0;
}
I would be really grateful if someone can help me through this. Thank you.

AES128 encrypt/decrypt using gcrypt in c++

i couldnt find a working good example so ive created one
you can change mykey ,and make the iv random using one of the gcrypt function.
sample
#include <iostream>
#include <gcrypt.h>
typedef unsigned char byte;
using namespace std;
#define BLOCK 16
const byte mykey []= {0x2d,0x65,0x20,0x74,0x69,0x6D,0x65,0x20,0x66,0x6F,0x72};
const byte end1[] ={0x0};
const byte message [] = {0x4E,0x6F,0x77,0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x74,0x69,0x6D,0x65,0x20,0x66,0x6F,0x72,0x20,0x61,0x6C,0x6C,0x20,0x67,0x6F,0x6F,0x64,0x20,0x6D,0x65,0x6E,0x20,0x74,0x6F,0x20,0x63,0x6F,0x6D,0x65,0x20,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x61,0x69,0x64,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x75,0x6E,0x74,0x72,0x79,0x2E,0x00 };
const byte end[] = {0x00};
// encrypt
// Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
// block in place.
#define roundup(x,n) \
n *((sizeof(x))/n + (((sizeof(x))%n)+1)/(((sizeof(x))%n)+1))
void verify ( gcry_error_t err, const char* msg ) {
if (err) {
cout << msg << " " << gcry_strsource(err)<< " / " << gcry_strerror(err) << endl;
exit(1);
}
}
/* PROGMA BEGIN
* encrypt decrypt
* using the GCRYPT */
int main (){
gcry_error_t err = 0;
// init the lib ..
if (!gcry_check_version (GCRYPT_VERSION))
{ cout << "gcrypt: library version mismatch" << endl; exit(1); }
err = gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
err |= gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
err |= gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
err |= gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
verify (err,"gcrypt: failed initialization");
//init the operation mode
#define GCRY_CIPHER GCRY_CIPHER_AES128
#define GCRY_MODE GCRY_CIPHER_MODE_ECB
//#define GCRY_FLAG GCRY_CIPHER_ENABLE_SYNC
#define GCRY_FLAG 0
gcry_cipher_hd_t handle;
err = gcry_cipher_open( &handle, GCRY_CIPHER, GCRY_MODE, GCRY_FLAG);
verify ( err, "gcry_cipher_open" ) ;
byte iv[BLOCK];
memset(iv,0x23,BLOCK); // just for example, we should get it from the cipher word, first 16 bytes
memset(iv, 0x89 , BLOCK -4);
err = gcry_cipher_setiv(handle,iv,BLOCK);
verify( err, "set iv ");
cout <<"iv seT: "<< BLOCK << ":"<< iv << endl;
err = gcry_cipher_setkey(handle, mykey, sizeof(mykey));
verify( err, "set KeY ");
cout << "KeY set: "<< sizeof(mykey) <<":";// << mykey << endl;
for ( int i = 0 ; i <sizeof(mykey) ; ++i ) cout << mykey[i];
cout << endl;
// init done
// in = message
// out - new
unsigned char out[ roundup(message,BLOCK) ];
memset(out,0,roundup(message,BLOCK) );
//memcpy( out, message, sizeof(message));
size_t outsize = sizeof(out);
err = gcry_cipher_encrypt( handle, out, outsize, message, outsize);
verify( err, "encrypt " );
cout <<endl<< "encrypt in: " << sizeof(message) << ":" << message << endl ;
cout << "encrypt out: " << outsize << ":"<< out << endl<<endl;
unsigned char decrypt[roundup(out,BLOCK)]; // to out
memset(decrypt, 0 , roundup(out,BLOCK) );
size_t dsize= sizeof(decrypt);
err = gcry_cipher_decrypt( handle, decrypt, dsize, out, outsize);
verify( err, "decrypt " );
cout << "decrypt in: " << outsize << ":";
for ( int i = 0 ; i < outsize ; ++i ) cout << out[i];
cout << endl;
cout << "decrypt out: " << dsize << ":"<< decrypt << endl;
gcry_cipher_close(handle);
return 0;
}
/* g++ -std=c++11 xxx.cpp -L/usr/lib64 -lgcrypt -lgpg-error*/
any comment is welcome
i know it doesn't look that good , tried to be concised

facedetect.cpp to detect eye in a cropped image

I am using OpenCV for face and eye detection. To start with, I tested the sample program in OpenCV/Samples/c/facedetect.cpp. I gave two images as an input to this facedetect.exe - one is full and the other is cropped face of the same person. Now, the facedetect.cpp works fine with full image whereas it is not even detecting the face with the cropped image as input.
Although the cropped image contains only the face which is cropped using OpenCV face detector, In some bad cases I will get only mouth or lips or only part of the face. So my requirement here is to check both the eyes are there in an image or not.
The below are the two sample pictures one is full image where I get proper output:
The below is the image where I need to detect the eyes using facedetect.cpp:
So my question here is how to detect the eyes in the cropped image?
The below is the code of sample facedetect.cpp
#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;
static void help()
{
cout << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n"
"This classifier can recognize many ~rigid objects, it's most known use is for faces.\n"
"Usage:\n"
"./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
" [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"
" [--scale=<image scale greater or equal to 1, try 1.3 for example>\n"
" [filename|camera_index]\n\n"
"see facedetect.cmd for one call:\n"
"./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye.xml\" --scale=1.3 \n"
"Hit any key to quit.\n"
"Using OpenCV version " << CV_VERSION << "\n" << endl;
}
void detectAndDraw( Mat& img,
CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
double scale);
String cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
String nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
int main( int argc, const char** argv )
{
CvCapture* capture = 0;
Mat frame, frameCopy, image;
const String scaleOpt = "--scale=";
size_t scaleOptLen = scaleOpt.length();
const String cascadeOpt = "--cascade=";
size_t cascadeOptLen = cascadeOpt.length();
const String nestedCascadeOpt = "--nested-cascade";
size_t nestedCascadeOptLen = nestedCascadeOpt.length();
String inputName;
help();
CascadeClassifier cascade, nestedCascade;
double scale = 1;
for( int i = 1; i < argc; i++ )
{
cout << "Processing " << i << " " << argv[i] << endl;
if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 )
{
cascadeName.assign( argv[i] + cascadeOptLen );
cout << " from which we have cascadeName= " << cascadeName << endl;
}
else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 )
{
if( argv[i][nestedCascadeOpt.length()] == '=' )
nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 );
if( !nestedCascade.load( nestedCascadeName ) )
cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
}
else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 )
{
if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 )
scale = 1;
cout << " from which we read scale = " << scale << endl;
}
else if( argv[i][0] == '-' )
{
cerr << "WARNING: Unknown option %s" << argv[i] << endl;
}
else
inputName.assign( argv[i] );
}
if( !cascade.load( cascadeName ) )
{
cerr << "ERROR: Could not load classifier cascade" << endl;
cerr << "Usage: facedetect [--cascade=<cascade_path>]\n"
" [--nested-cascade[=nested_cascade_path]]\n"
" [--scale[=<image scale>\n"
" [filename|camera_index]\n" << endl ;
return -1;
}
if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )
{
capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' );
int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ;
if(!capture) cout << "Capture from CAM " << c << " didn't work" << endl;
}
else if( inputName.size() )
{
image = imread( inputName, 1 );
if( image.empty() )
{
capture = cvCaptureFromAVI( inputName.c_str() );
if(!capture) cout << "Capture from AVI didn't work" << endl;
}
}
else
{
image = imread( "lena.jpg", 1 );
if(image.empty()) cout << "Couldn't read lena.jpg" << endl;
}
cvNamedWindow( "result", 1 );
if( capture )
{
cout << "In capture ..." << endl;
for(;;)
{
IplImage* iplImg = cvQueryFrame( capture );
frame = iplImg;
if( frame.empty() )
break;
if( iplImg->origin == IPL_ORIGIN_TL )
frame.copyTo( frameCopy );
else
flip( frame, frameCopy, 0 );
detectAndDraw( frameCopy, cascade, nestedCascade, scale );
if( waitKey( 10 ) >= 0 )
goto _cleanup_;
}
waitKey(0);
_cleanup_:
cvReleaseCapture( &capture );
}
else
{
cout << "In image read" << endl;
if( !image.empty() )
{
detectAndDraw( image, cascade, nestedCascade, scale );
waitKey(0);
}
else if( !inputName.empty() )
{
/* assume it is a text file containing the
list of the image filenames to be processed - one per line */
FILE* f = fopen( inputName.c_str(), "rt" );
if( f )
{
char buf[1000+1];
while( fgets( buf, 1000, f ) )
{
int len = (int)strlen(buf), c;
while( len > 0 && isspace(buf[len-1]) )
len--;
buf[len] = '\0';
cout << "file " << buf << endl;
image = imread( buf, 1 );
if( !image.empty() )
{
detectAndDraw( image, cascade, nestedCascade, scale );
c = waitKey(0);
if( c == 27 || c == 'q' || c == 'Q' )
break;
}
else
{
cerr << "Aw snap, couldn't read image " << buf << endl;
}
}
fclose(f);
}
}
}
cvDestroyWindow("result");
return 0;
}
void detectAndDraw( Mat& img,
CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
double scale)
{
int i = 0;
double t = 0;
vector<Rect> faces;
const static Scalar colors[] = { CV_RGB(0,0,255),
CV_RGB(0,128,255),
CV_RGB(0,255,255),
CV_RGB(0,255,0),
CV_RGB(255,128,0),
CV_RGB(255,255,0),
CV_RGB(255,0,0),
CV_RGB(255,0,255)} ;
Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
cvtColor( img, gray, CV_BGR2GRAY );
resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
equalizeHist( smallImg, smallImg );
t = (double)cvGetTickCount();
cascade.detectMultiScale( smallImg, faces,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
|CV_HAAR_SCALE_IMAGE
,
Size(30, 30) );
t = (double)cvGetTickCount() - t;
printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
{
Mat smallImgROI;
vector<Rect> nestedObjects;
Point center;
Scalar color = colors[i%8];
int radius;
center.x = cvRound((r->x + r->width*0.5)*scale);
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
circle( img, center, radius, color, 3, 8, 0 );
if( nestedCascade.empty() )
continue;
smallImgROI = smallImg(*r);
nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
//|CV_HAAR_DO_CANNY_PRUNING
|CV_HAAR_SCALE_IMAGE
,
Size(30, 30) );
for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
{
center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
radius = cvRound((nr->width + nr->height)*0.25*scale);
circle( img, center, radius, color, 3, 8, 0 );
}
}
cv::imshow( "result", img );
}
The original example detects faces first by cascade.detectMultiScale, then finds eyes in the detected faces by nestedCascade.detectMultiScale.
If you only need to detect the eyes, just use nestedCascade.detectMultiScale on the full image.
If you have a detected face (frontal face) a rough positions of the left and right eye regions are then estimated using anthropometric relations as show below.
Change the cascade classifier name:
String cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
change this to
String cascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
and pass the location of the image as the argument.

Face-detection in bash: Simply return number of faces found

I need to count the number of faces in a picture on the commandline (to be used in a bash script: do-something-if-picture-passed-contains-faces, else try next picture).
So far I have the facedetect OpenCV example working, but this example continuously displays the picture - all I'd need is a number returned (or, simply an errorcode: 0 if no face found, 1 if a face has been found).
Sadly my C++ skills are abysmal, could someone point me in the right direction?
I'd use python or ruby, but the bindings to OpenCV seem to be more then broken in Ubuntu 12.04, none of the examples work right (or at all).
Thank you!
Edit: The example I was talking about as installed by OpenCV under Ubuntu
cat /usr/share/doc/opencv-doc/examples/c/facedetect.cpp:
#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;
void help()
{
cout << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n"
"This classifier can recognize many ~rigid objects, it's most known use is for faces.\n"
"Usage:\n"
"./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
" [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"
" [--scale=<image scale greater or equal to 1, try 1.3 for example>\n"
" [filename|camera_index]\n\n"
"see facedetect.cmd for one call:\n"
"./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye.xml\" --scale=1.3 \n"
"Hit any key to quit.\n"
"Using OpenCV version " << CV_VERSION << "\n" << endl;
}
void detectAndDraw( Mat& img,
CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
double scale);
String cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
String nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
int main( int argc, const char** argv )
{
CvCapture* capture = 0;
Mat frame, frameCopy, image;
const String scaleOpt = "--scale=";
size_t scaleOptLen = scaleOpt.length();
const String cascadeOpt = "--cascade=";
size_t cascadeOptLen = cascadeOpt.length();
const String nestedCascadeOpt = "--nested-cascade";
size_t nestedCascadeOptLen = nestedCascadeOpt.length();
String inputName;
help();
CascadeClassifier cascade, nestedCascade;
double scale = 1;
for( int i = 1; i < argc; i++ )
{
cout << "Processing " << i << " " << argv[i] << endl;
if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 )
{
cascadeName.assign( argv[i] + cascadeOptLen );
cout << " from which we have cascadeName= " << cascadeName << endl;
}
else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 )
{
if( argv[i][nestedCascadeOpt.length()] == '=' )
nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 );
if( !nestedCascade.load( nestedCascadeName ) )
cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
}
else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 )
{
if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 )
scale = 1;
cout << " from which we read scale = " << scale << endl;
}
else if( argv[i][0] == '-' )
{
cerr << "WARNING: Unknown option %s" << argv[i] << endl;
}
else
inputName.assign( argv[i] );
}
if( !cascade.load( cascadeName ) )
{
cerr << "ERROR: Could not load classifier cascade" << endl;
cerr << "Usage: facedetect [--cascade=<cascade_path>]\n"
" [--nested-cascade[=nested_cascade_path]]\n"
" [--scale[=<image scale>\n"
" [filename|camera_index]\n" << endl ;
return -1;
}
if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )
{
capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' );
int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ;
if(!capture) cout << "Capture from CAM " << c << " didn't work" << endl;
}
else if( inputName.size() )
{
image = imread( inputName, 1 );
if( image.empty() )
{
capture = cvCaptureFromAVI( inputName.c_str() );
if(!capture) cout << "Capture from AVI didn't work" << endl;
}
}
else
{
image = imread( "lena.jpg", 1 );
if(image.empty()) cout << "Couldn't read lena.jpg" << endl;
}
cvNamedWindow( "result", 1 );
if( capture )
{
cout << "In capture ..." << endl;
for(;;)
{
IplImage* iplImg = cvQueryFrame( capture );
frame = iplImg;
if( frame.empty() )
break;
if( iplImg->origin == IPL_ORIGIN_TL )
frame.copyTo( frameCopy );
else
flip( frame, frameCopy, 0 );
detectAndDraw( frameCopy, cascade, nestedCascade, scale );
if( waitKey( 10 ) >= 0 )
goto _cleanup_;
}
waitKey(0);
_cleanup_:
cvReleaseCapture( &capture );
}
else
{
cout << "In image read" << endl;
if( !image.empty() )
{
detectAndDraw( image, cascade, nestedCascade, scale );
waitKey(0);
}
else if( !inputName.empty() )
{
/* assume it is a text file containing the
list of the image filenames to be processed - one per line */
FILE* f = fopen( inputName.c_str(), "rt" );
if( f )
{
char buf[1000+1];
while( fgets( buf, 1000, f ) )
{
int len = (int)strlen(buf), c;
while( len > 0 && isspace(buf[len-1]) )
len--;
buf[len] = '\0';
cout << "file " << buf << endl;
image = imread( buf, 1 );
if( !image.empty() )
{
detectAndDraw( image, cascade, nestedCascade, scale );
c = waitKey(0);
if( c == 27 || c == 'q' || c == 'Q' )
break;
}
else
{
cerr << "Aw snap, couldn't read image " << buf << endl;
}
}
fclose(f);
}
}
}
cvDestroyWindow("result");
return 0;
}
void detectAndDraw( Mat& img,
CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
double scale)
{
int i = 0;
double t = 0;
vector<Rect> faces;
const static Scalar colors[] = { CV_RGB(0,0,255),
CV_RGB(0,128,255),
CV_RGB(0,255,255),
CV_RGB(0,255,0),
CV_RGB(255,128,0),
CV_RGB(255,255,0),
CV_RGB(255,0,0),
CV_RGB(255,0,255)} ;
Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
cvtColor( img, gray, CV_BGR2GRAY );
resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
equalizeHist( smallImg, smallImg );
t = (double)cvGetTickCount();
cascade.detectMultiScale( smallImg, faces,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
|CV_HAAR_SCALE_IMAGE
,
Size(30, 30) );
t = (double)cvGetTickCount() - t;
printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
{
Mat smallImgROI;
vector<Rect> nestedObjects;
Point center;
Scalar color = colors[i%8];
int radius;
center.x = cvRound((r->x + r->width*0.5)*scale);
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
circle( img, center, radius, color, 3, 8, 0 );
if( nestedCascade.empty() )
continue;
smallImgROI = smallImg(*r);
nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
//|CV_HAAR_DO_CANNY_PRUNING
|CV_HAAR_SCALE_IMAGE
,
Size(30, 30) );
for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
{
center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
radius = cvRound((nr->width + nr->height)*0.25*scale);
circle( img, center, radius, color, 3, 8, 0 );
}
}
cv::imshow( "result", img );
}
Change the void detectAndDraw to int detectAndDraw
The int detectAndDraw will return faces.end()-faces.begin();
and you will get the number of faces in a picture. hope this will help

FaceDetect OpenCV2.1 sample, Access violation writing location 0x00000000

I try to run facedetect opencv sample with vs2010.
debug result "Unhandled exception at 0x53fa42bf in facedetect.exe: 0xC0000005: Access violation writing location 0x00000000."
Here is the code
txt file: http://ebooks-libs.com/backup/facedetect-opencv2.1.txt
cpp file: http://ebooks-libs.com/backup/facedetect.cpp
#include "stdafx.h"
#include <iostream>
#include <cstdio>
#define CV_NO_BACKWARD_COMPATIBILITY
#include "cv.h"
#include "highgui.h"
#ifdef _EiC
#define WIN32
#endif
using namespace std;
using namespace cv;
void detectAndDraw( Mat& img,
CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
double scale);
String cascadeName ="./data/haarcascades/haarcascade_frontalface_alt.xml";
String nestedCascadeName ="./data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
int main( int argc, const char** argv )
{
CvCapture* capture = 0;
Mat frame, frameCopy, image;
const String scaleOpt = "--scale=";
size_t scaleOptLen = scaleOpt.length();
const String cascadeOpt = "--cascade=";
size_t cascadeOptLen = cascadeOpt.length();
const String nestedCascadeOpt = "--nested-cascade";
size_t nestedCascadeOptLen = nestedCascadeOpt.length();
String inputName;
CascadeClassifier cascade, nestedCascade;
double scale = 1;
for( int i = 1; i < argc; i++ )
{
if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 )
cascadeName.assign( argv[i] + cascadeOptLen );
else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 )
{
if( argv[i][nestedCascadeOpt.length()] == '=' )
nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 );
if( !nestedCascade.load( nestedCascadeName ) )
cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
}
else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 )
{
if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 )
scale = 1;
}
else if( argv[i][0] == '-' )
{
cerr << "WARNING: Unknown option %s" << argv[i] << endl;
}
else
inputName.assign( argv[i] );
}
if( !cascade.load( cascadeName ) )
{
cerr << "ERROR: Could not load classifier cascade" << endl;
cerr << "Usage: facedetect [--cascade=\"<cascade_path>\"]\n"
" [--nested-cascade[=\"nested_cascade_path\"]]\n"
" [--scale[=<image scale>\n"
" [filename|camera_index]\n" ;
return -1;
}
if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )
capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' );
else if( inputName.size() )
{
image = imread( inputName, 1 );
if( image.empty() )
capture = cvCaptureFromAVI( inputName.c_str() );
}
else
image = imread( "lena.jpg", 1 );
cvNamedWindow( "result", 1 );
if( capture )
{
for(;;)
{
IplImage* iplImg = cvQueryFrame( capture );
frame = iplImg;
if( frame.empty() )
break;
if( iplImg->origin == IPL_ORIGIN_TL )
frame.copyTo( frameCopy );
else
flip( frame, frameCopy, 0 );
detectAndDraw( frameCopy, cascade, nestedCascade, scale );
if( waitKey( 10 ) >= 0 )
goto _cleanup_;
}
waitKey(0);
_cleanup_:
cvReleaseCapture( &capture );
}
else
{
if( !image.empty() )
{
detectAndDraw( image, cascade, nestedCascade, scale );
waitKey(0);
}
else if( !inputName.empty() )
{
/* assume it is a text file containing the
list of the image filenames to be processed - one per line */
FILE* f = fopen( inputName.c_str(), "rt" );
if( f )
{
char buf[1000+1];
while( fgets( buf, 1000, f ) )
{
int len = (int)strlen(buf), c;
while( len > 0 && isspace(buf[len-1]) )
len--;
buf[len] = '\0';
cout << "file " << buf << endl;
image = imread( buf, 1 );
if( !image.empty() )
{
detectAndDraw( image, cascade, nestedCascade, scale );
c = waitKey(0);
if( c == 27 || c == 'q' || c == 'Q' )
break;
}
}
fclose(f);
}
}
}
cvDestroyWindow("result");
return 0;
}
void detectAndDraw( Mat& img,
CascadeClassifier& cascade, CascadeClassifier& nestedCascade,
double scale)
{
int i = 0;
double t = 0;
vector<Rect> faces;
const static Scalar colors[] = { CV_RGB(0,0,255),
CV_RGB(0,128,255),
CV_RGB(0,255,255),
CV_RGB(0,255,0),
CV_RGB(255,128,0),
CV_RGB(255,255,0),
CV_RGB(255,0,0),
CV_RGB(255,0,255)} ;
Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
cvtColor( img, gray, CV_BGR2GRAY );
resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
equalizeHist( smallImg, smallImg );
t = (double)cvGetTickCount();
cascade.detectMultiScale( smallImg, faces,1.1, 2, 0 |CV_HAAR_SCALE_IMAGE,Size(30, 30) );
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
t = (double)cvGetTickCount() - t;
printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
{
Mat smallImgROI;
vector<Rect> nestedObjects;
Point center;
Scalar color = colors[i%8];
int radius;
center.x = cvRound((r->x + r->width*0.5)*scale);
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
circle( img, center, radius, color, 3, 8, 0 );
if( nestedCascade.empty() )
continue;
smallImgROI = smallImg(*r);
nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
//|CV_HAAR_DO_CANNY_PRUNING
|CV_HAAR_SCALE_IMAGE
,
Size(30, 30) );
for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
{
center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
radius = cvRound((nr->width + nr->height)*0.25*scale);
circle( img, center, radius, color, 3, 8, 0 );
}
}
cv::imshow( "result", img );
}
Need some help how to resolve it...
The access violation error probably means you are accessing a pointer that you haven't set the value for.
If you don't understand how to use the debugger (learn!) put printf("ok1,2,3 ....\n"); liberally through the code and work out how far it's gettign so you can narrow down where the error happens
I got this error too with OpenCV 2.3 on VS2010, even after adjusting the code so that cascadeName uses the full path to haarcascade_frontalface_alt.xml.
I was able to pinpoint the problem to the line that crashes the application:
if( !cascade.load( cascadeName ) )
The crash is coming from OpenCV's code and I don't know why it happens.

Resources