mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1681 lines
48 KiB
1681 lines
48 KiB
/*M/////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
|
// |
|
// By downloading, copying, installing or using the software you agree to this license. |
|
// If you do not agree to this license, do not download, install, |
|
// copy or use the software. |
|
// |
|
// |
|
// Intel License Agreement |
|
// For Open Source Computer Vision Library |
|
// |
|
// Copyright (C) 2000, Intel Corporation, all rights reserved. |
|
// Third party copyrights are property of their respective owners. |
|
// |
|
// Redistribution and use in source and binary forms, with or without modification, |
|
// are permitted provided that the following conditions are met: |
|
// |
|
// * Redistribution's of source code must retain the above copyright notice, |
|
// this list of conditions and the following disclaimer. |
|
// |
|
// * Redistribution's in binary form must reproduce the above copyright notice, |
|
// this list of conditions and the following disclaimer in the documentation |
|
// and/or other materials provided with the distribution. |
|
// |
|
// * The name of Intel Corporation may not be used to endorse or promote products |
|
// derived from this software without specific prior written permission. |
|
// |
|
// This software is provided by the copyright holders and contributors "as is" and |
|
// any express or implied warranties, including, but not limited to, the implied |
|
// warranties of merchantability and fitness for a particular purpose are disclaimed. |
|
// In no event shall the Intel Corporation or contributors be liable for any direct, |
|
// indirect, incidental, special, exemplary, or consequential damages |
|
// (including, but not limited to, procurement of substitute goods or services; |
|
// loss of use, data, or profits; or business interruption) however caused |
|
// and on any theory of liability, whether in contract, strict liability, |
|
// or tort (including negligence or otherwise) arising in any way out of |
|
// the use of this software, even if advised of the possibility of such damage. |
|
// |
|
//M*/ |
|
|
|
#include <cstring> |
|
#include <ctime> |
|
|
|
#include <sys/stat.h> |
|
#include <sys/types.h> |
|
#ifdef _WIN32 |
|
#include <direct.h> |
|
#endif /* _WIN32 */ |
|
|
|
#include "utility.hpp" |
|
#include "opencv2/core.hpp" |
|
#include "opencv2/core/core_c.h" |
|
#include "opencv2/imgcodecs/imgcodecs_c.h" |
|
#include "opencv2/imgproc/imgproc_c.h" |
|
#include "opencv2/highgui/highgui_c.h" |
|
#include "opencv2/calib3d/calib3d_c.h" |
|
|
|
#ifndef PATH_MAX |
|
#define PATH_MAX 512 |
|
#endif /* PATH_MAX */ |
|
|
|
#define __BEGIN__ __CV_BEGIN__ |
|
#define __END__ __CV_END__ |
|
#define EXIT __CV_EXIT__ |
|
|
|
static int icvMkDir( const char* filename ) |
|
{ |
|
char path[PATH_MAX]; |
|
char* p; |
|
int pos; |
|
|
|
#ifdef _WIN32 |
|
struct _stat st; |
|
#else /* _WIN32 */ |
|
struct stat st; |
|
mode_t mode; |
|
|
|
mode = 0755; |
|
#endif /* _WIN32 */ |
|
|
|
strcpy( path, filename ); |
|
|
|
p = path; |
|
for( ; ; ) |
|
{ |
|
pos = (int)strcspn( p, "/\\" ); |
|
|
|
if( pos == (int) strlen( p ) ) break; |
|
if( pos != 0 ) |
|
{ |
|
p[pos] = '\0'; |
|
|
|
#ifdef _WIN32 |
|
if( p[pos-1] != ':' ) |
|
{ |
|
if( _stat( path, &st ) != 0 ) |
|
{ |
|
if( _mkdir( path ) != 0 ) return 0; |
|
} |
|
} |
|
#else /* _WIN32 */ |
|
if( stat( path, &st ) != 0 ) |
|
{ |
|
if( mkdir( path, mode ) != 0 ) return 0; |
|
} |
|
#endif /* _WIN32 */ |
|
} |
|
|
|
p[pos] = '/'; |
|
|
|
p += pos + 1; |
|
} |
|
|
|
return 1; |
|
} |
|
|
|
static void icvWriteVecHeader( FILE* file, int count, int width, int height ) |
|
{ |
|
int vecsize; |
|
short tmp; |
|
|
|
/* number of samples */ |
|
fwrite( &count, sizeof( count ), 1, file ); |
|
/* vector size */ |
|
vecsize = width * height; |
|
fwrite( &vecsize, sizeof( vecsize ), 1, file ); |
|
/* min/max values */ |
|
tmp = 0; |
|
fwrite( &tmp, sizeof( tmp ), 1, file ); |
|
fwrite( &tmp, sizeof( tmp ), 1, file ); |
|
} |
|
|
|
static void icvWriteVecSample( FILE* file, CvArr* sample ) |
|
{ |
|
CvMat* mat, stub; |
|
int r, c; |
|
short tmp; |
|
uchar chartmp; |
|
|
|
mat = cvGetMat( sample, &stub ); |
|
chartmp = 0; |
|
fwrite( &chartmp, sizeof( chartmp ), 1, file ); |
|
for( r = 0; r < mat->rows; r++ ) |
|
{ |
|
for( c = 0; c < mat->cols; c++ ) |
|
{ |
|
tmp = (short) (CV_MAT_ELEM( *mat, uchar, r, c )); |
|
fwrite( &tmp, sizeof( tmp ), 1, file ); |
|
} |
|
} |
|
} |
|
|
|
/* Calculates coefficients of perspective transformation |
|
* which maps <quad> into rectangle ((0,0), (w,0), (w,h), (h,0)): |
|
* |
|
* c00*xi + c01*yi + c02 |
|
* ui = --------------------- |
|
* c20*xi + c21*yi + c22 |
|
* |
|
* c10*xi + c11*yi + c12 |
|
* vi = --------------------- |
|
* c20*xi + c21*yi + c22 |
|
* |
|
* Coefficients are calculated by solving linear system: |
|
* / x0 y0 1 0 0 0 -x0*u0 -y0*u0 \ /c00\ /u0\ |
|
* | x1 y1 1 0 0 0 -x1*u1 -y1*u1 | |c01| |u1| |
|
* | x2 y2 1 0 0 0 -x2*u2 -y2*u2 | |c02| |u2| |
|
* | x3 y3 1 0 0 0 -x3*u3 -y3*u3 |.|c10|=|u3|, |
|
* | 0 0 0 x0 y0 1 -x0*v0 -y0*v0 | |c11| |v0| |
|
* | 0 0 0 x1 y1 1 -x1*v1 -y1*v1 | |c12| |v1| |
|
* | 0 0 0 x2 y2 1 -x2*v2 -y2*v2 | |c20| |v2| |
|
* \ 0 0 0 x3 y3 1 -x3*v3 -y3*v3 / \c21/ \v3/ |
|
* |
|
* where: |
|
* (xi, yi) = (quad[i][0], quad[i][1]) |
|
* cij - coeffs[i][j], coeffs[2][2] = 1 |
|
* (ui, vi) - rectangle vertices |
|
*/ |
|
static void cvGetPerspectiveTransform( CvSize src_size, double quad[4][2], double coeffs[3][3] ) |
|
{ |
|
//CV_FUNCNAME( "cvWarpPerspective" ); |
|
|
|
__BEGIN__; |
|
|
|
double a[8][8]; |
|
double b[8]; |
|
|
|
CvMat A = cvMat( 8, 8, CV_64FC1, a ); |
|
CvMat B = cvMat( 8, 1, CV_64FC1, b ); |
|
CvMat X = cvMat( 8, 1, CV_64FC1, coeffs ); |
|
|
|
int i; |
|
for( i = 0; i < 4; ++i ) |
|
{ |
|
a[i][0] = quad[i][0]; a[i][1] = quad[i][1]; a[i][2] = 1; |
|
a[i][3] = a[i][4] = a[i][5] = a[i][6] = a[i][7] = 0; |
|
b[i] = 0; |
|
} |
|
for( i = 4; i < 8; ++i ) |
|
{ |
|
a[i][3] = quad[i-4][0]; a[i][4] = quad[i-4][1]; a[i][5] = 1; |
|
a[i][0] = a[i][1] = a[i][2] = a[i][6] = a[i][7] = 0; |
|
b[i] = 0; |
|
} |
|
|
|
int u = src_size.width - 1; |
|
int v = src_size.height - 1; |
|
|
|
a[1][6] = -quad[1][0] * u; a[1][7] = -quad[1][1] * u; |
|
a[2][6] = -quad[2][0] * u; a[2][7] = -quad[2][1] * u; |
|
b[1] = b[2] = u; |
|
|
|
a[6][6] = -quad[2][0] * v; a[6][7] = -quad[2][1] * v; |
|
a[7][6] = -quad[3][0] * v; a[7][7] = -quad[3][1] * v; |
|
b[6] = b[7] = v; |
|
|
|
cvSolve( &A, &B, &X ); |
|
|
|
coeffs[2][2] = 1; |
|
|
|
__END__; |
|
} |
|
|
|
/* Warps source into destination by a perspective transform */ |
|
static void cvWarpPerspective( CvArr* src, CvArr* dst, double quad[4][2] ) |
|
{ |
|
CV_FUNCNAME( "cvWarpPerspective" ); |
|
|
|
__BEGIN__; |
|
|
|
#ifdef __IPL_H__ |
|
IplImage src_stub, dst_stub; |
|
IplImage* src_img; |
|
IplImage* dst_img; |
|
CV_CALL( src_img = cvGetImage( src, &src_stub ) ); |
|
CV_CALL( dst_img = cvGetImage( dst, &dst_stub ) ); |
|
iplWarpPerspectiveQ( src_img, dst_img, quad, IPL_WARP_R_TO_Q, |
|
IPL_INTER_CUBIC | IPL_SMOOTH_EDGE ); |
|
#else |
|
|
|
int fill_value = 0; |
|
|
|
double c[3][3]; /* transformation coefficients */ |
|
double q[4][2]; /* rearranged quad */ |
|
|
|
int left = 0; |
|
int right = 0; |
|
int next_right = 0; |
|
int next_left = 0; |
|
double y_min = 0; |
|
double y_max = 0; |
|
double k_left, b_left, k_right, b_right; |
|
|
|
uchar* src_data; |
|
int src_step; |
|
CvSize src_size; |
|
|
|
uchar* dst_data; |
|
int dst_step; |
|
CvSize dst_size; |
|
|
|
double d = 0; |
|
int direction = 0; |
|
int i; |
|
|
|
if( !src || (!CV_IS_IMAGE( src ) && !CV_IS_MAT( src )) || |
|
cvGetElemType( src ) != CV_8UC1 || |
|
cvGetDims( src ) != 2 ) |
|
{ |
|
CV_ERROR( CV_StsBadArg, |
|
"Source must be two-dimensional array of CV_8UC1 type." ); |
|
} |
|
if( !dst || (!CV_IS_IMAGE( dst ) && !CV_IS_MAT( dst )) || |
|
cvGetElemType( dst ) != CV_8UC1 || |
|
cvGetDims( dst ) != 2 ) |
|
{ |
|
CV_ERROR( CV_StsBadArg, |
|
"Destination must be two-dimensional array of CV_8UC1 type." ); |
|
} |
|
|
|
CV_CALL( cvGetRawData( src, &src_data, &src_step, &src_size ) ); |
|
CV_CALL( cvGetRawData( dst, &dst_data, &dst_step, &dst_size ) ); |
|
|
|
CV_CALL( cvGetPerspectiveTransform( src_size, quad, c ) ); |
|
|
|
/* if direction > 0 then vertices in quad follow in a CW direction, |
|
otherwise they follow in a CCW direction */ |
|
direction = 0; |
|
for( i = 0; i < 4; ++i ) |
|
{ |
|
int ni = i + 1; if( ni == 4 ) ni = 0; |
|
int pi = i - 1; if( pi == -1 ) pi = 3; |
|
|
|
d = (quad[i][0] - quad[pi][0])*(quad[ni][1] - quad[i][1]) - |
|
(quad[i][1] - quad[pi][1])*(quad[ni][0] - quad[i][0]); |
|
int cur_direction = CV_SIGN(d); |
|
if( direction == 0 ) |
|
{ |
|
direction = cur_direction; |
|
} |
|
else if( direction * cur_direction < 0 ) |
|
{ |
|
direction = 0; |
|
break; |
|
} |
|
} |
|
if( direction == 0 ) |
|
{ |
|
CV_ERROR( CV_StsBadArg, "Quadrangle is nonconvex or degenerated." ); |
|
} |
|
|
|
/* <left> is the index of the topmost quad vertice |
|
if there are two such vertices <left> is the leftmost one */ |
|
left = 0; |
|
for( i = 1; i < 4; ++i ) |
|
{ |
|
if( (quad[i][1] < quad[left][1]) || |
|
((quad[i][1] == quad[left][1]) && (quad[i][0] < quad[left][0])) ) |
|
{ |
|
left = i; |
|
} |
|
} |
|
/* rearrange <quad> vertices in such way that they follow in a CW |
|
direction and the first vertice is the topmost one and put them |
|
into <q> */ |
|
if( direction > 0 ) |
|
{ |
|
for( i = left; i < 4; ++i ) |
|
{ |
|
q[i-left][0] = quad[i][0]; |
|
q[i-left][1] = quad[i][1]; |
|
} |
|
for( i = 0; i < left; ++i ) |
|
{ |
|
q[4-left+i][0] = quad[i][0]; |
|
q[4-left+i][1] = quad[i][1]; |
|
} |
|
} |
|
else |
|
{ |
|
for( i = left; i >= 0; --i ) |
|
{ |
|
q[left-i][0] = quad[i][0]; |
|
q[left-i][1] = quad[i][1]; |
|
} |
|
for( i = 3; i > left; --i ) |
|
{ |
|
q[4+left-i][0] = quad[i][0]; |
|
q[4+left-i][1] = quad[i][1]; |
|
} |
|
} |
|
|
|
left = right = 0; |
|
/* if there are two topmost points, <right> is the index of the rightmost one |
|
otherwise <right> */ |
|
if( q[left][1] == q[left+1][1] ) |
|
{ |
|
right = 1; |
|
} |
|
|
|
/* <next_left> follows <left> in a CCW direction */ |
|
next_left = 3; |
|
/* <next_right> follows <right> in a CW direction */ |
|
next_right = right + 1; |
|
|
|
/* subtraction of 1 prevents skipping of the first row */ |
|
y_min = q[left][1] - 1; |
|
|
|
/* left edge equation: y = k_left * x + b_left */ |
|
k_left = (q[left][0] - q[next_left][0]) / |
|
(q[left][1] - q[next_left][1]); |
|
b_left = (q[left][1] * q[next_left][0] - |
|
q[left][0] * q[next_left][1]) / |
|
(q[left][1] - q[next_left][1]); |
|
|
|
/* right edge equation: y = k_right * x + b_right */ |
|
k_right = (q[right][0] - q[next_right][0]) / |
|
(q[right][1] - q[next_right][1]); |
|
b_right = (q[right][1] * q[next_right][0] - |
|
q[right][0] * q[next_right][1]) / |
|
(q[right][1] - q[next_right][1]); |
|
|
|
for(;;) |
|
{ |
|
int x, y; |
|
|
|
y_max = MIN( q[next_left][1], q[next_right][1] ); |
|
|
|
int iy_min = MAX( cvRound(y_min), 0 ) + 1; |
|
int iy_max = MIN( cvRound(y_max), dst_size.height - 1 ); |
|
|
|
double x_min = k_left * iy_min + b_left; |
|
double x_max = k_right * iy_min + b_right; |
|
|
|
/* walk through the destination quadrangle row by row */ |
|
for( y = iy_min; y <= iy_max; ++y ) |
|
{ |
|
int ix_min = MAX( cvRound( x_min ), 0 ); |
|
int ix_max = MIN( cvRound( x_max ), dst_size.width - 1 ); |
|
|
|
for( x = ix_min; x <= ix_max; ++x ) |
|
{ |
|
/* calculate coordinates of the corresponding source array point */ |
|
double div = (c[2][0] * x + c[2][1] * y + c[2][2]); |
|
double src_x = (c[0][0] * x + c[0][1] * y + c[0][2]) / div; |
|
double src_y = (c[1][0] * x + c[1][1] * y + c[1][2]) / div; |
|
|
|
int isrc_x = cvFloor( src_x ); |
|
int isrc_y = cvFloor( src_y ); |
|
double delta_x = src_x - isrc_x; |
|
double delta_y = src_y - isrc_y; |
|
|
|
uchar* s = src_data + isrc_y * src_step + isrc_x; |
|
|
|
int i00, i10, i01, i11; |
|
i00 = i10 = i01 = i11 = (int) fill_value; |
|
|
|
/* linear interpolation using 2x2 neighborhood */ |
|
if( isrc_x >= 0 && isrc_x <= src_size.width && |
|
isrc_y >= 0 && isrc_y <= src_size.height ) |
|
{ |
|
i00 = s[0]; |
|
} |
|
if( isrc_x >= -1 && isrc_x < src_size.width && |
|
isrc_y >= 0 && isrc_y <= src_size.height ) |
|
{ |
|
i10 = s[1]; |
|
} |
|
if( isrc_x >= 0 && isrc_x <= src_size.width && |
|
isrc_y >= -1 && isrc_y < src_size.height ) |
|
{ |
|
i01 = s[src_step]; |
|
} |
|
if( isrc_x >= -1 && isrc_x < src_size.width && |
|
isrc_y >= -1 && isrc_y < src_size.height ) |
|
{ |
|
i11 = s[src_step+1]; |
|
} |
|
|
|
double i0 = i00 + (i10 - i00)*delta_x; |
|
double i1 = i01 + (i11 - i01)*delta_x; |
|
|
|
((uchar*)(dst_data + y * dst_step))[x] = (uchar) (i0 + (i1 - i0)*delta_y); |
|
} |
|
x_min += k_left; |
|
x_max += k_right; |
|
} |
|
|
|
if( (next_left == next_right) || |
|
(next_left+1 == next_right && q[next_left][1] == q[next_right][1]) ) |
|
{ |
|
break; |
|
} |
|
|
|
if( y_max == q[next_left][1] ) |
|
{ |
|
left = next_left; |
|
next_left = left - 1; |
|
|
|
k_left = (q[left][0] - q[next_left][0]) / |
|
(q[left][1] - q[next_left][1]); |
|
b_left = (q[left][1] * q[next_left][0] - |
|
q[left][0] * q[next_left][1]) / |
|
(q[left][1] - q[next_left][1]); |
|
} |
|
if( y_max == q[next_right][1] ) |
|
{ |
|
right = next_right; |
|
next_right = right + 1; |
|
|
|
k_right = (q[right][0] - q[next_right][0]) / |
|
(q[right][1] - q[next_right][1]); |
|
b_right = (q[right][1] * q[next_right][0] - |
|
q[right][0] * q[next_right][1]) / |
|
(q[right][1] - q[next_right][1]); |
|
} |
|
y_min = y_max; |
|
} |
|
#endif /* #ifndef __IPL_H__ */ |
|
|
|
__END__; |
|
} |
|
|
|
static |
|
void icvRandomQuad( int width, int height, double quad[4][2], |
|
double maxxangle, |
|
double maxyangle, |
|
double maxzangle ) |
|
{ |
|
double distfactor = 3.0; |
|
double distfactor2 = 1.0; |
|
|
|
double halfw, halfh; |
|
int i; |
|
|
|
double rotVectData[3]; |
|
double vectData[3]; |
|
double rotMatData[9]; |
|
|
|
CvMat rotVect; |
|
CvMat rotMat; |
|
CvMat vect; |
|
|
|
double d; |
|
|
|
rotVect = cvMat( 3, 1, CV_64FC1, &rotVectData[0] ); |
|
rotMat = cvMat( 3, 3, CV_64FC1, &rotMatData[0] ); |
|
vect = cvMat( 3, 1, CV_64FC1, &vectData[0] ); |
|
|
|
rotVectData[0] = maxxangle * (2.0 * rand() / RAND_MAX - 1.0); |
|
rotVectData[1] = ( maxyangle - fabs( rotVectData[0] ) ) |
|
* (2.0 * rand() / RAND_MAX - 1.0); |
|
rotVectData[2] = maxzangle * (2.0 * rand() / RAND_MAX - 1.0); |
|
d = (distfactor + distfactor2 * (2.0 * rand() / RAND_MAX - 1.0)) * width; |
|
|
|
/* |
|
rotVectData[0] = maxxangle; |
|
rotVectData[1] = maxyangle; |
|
rotVectData[2] = maxzangle; |
|
|
|
d = distfactor * width; |
|
*/ |
|
|
|
cvRodrigues2( &rotVect, &rotMat ); |
|
|
|
halfw = 0.5 * width; |
|
halfh = 0.5 * height; |
|
|
|
quad[0][0] = -halfw; |
|
quad[0][1] = -halfh; |
|
quad[1][0] = halfw; |
|
quad[1][1] = -halfh; |
|
quad[2][0] = halfw; |
|
quad[2][1] = halfh; |
|
quad[3][0] = -halfw; |
|
quad[3][1] = halfh; |
|
|
|
for( i = 0; i < 4; i++ ) |
|
{ |
|
rotVectData[0] = quad[i][0]; |
|
rotVectData[1] = quad[i][1]; |
|
rotVectData[2] = 0.0; |
|
cvMatMulAdd( &rotMat, &rotVect, 0, &vect ); |
|
quad[i][0] = vectData[0] * d / (d + vectData[2]) + halfw; |
|
quad[i][1] = vectData[1] * d / (d + vectData[2]) + halfh; |
|
|
|
/* |
|
quad[i][0] += halfw; |
|
quad[i][1] += halfh; |
|
*/ |
|
} |
|
} |
|
|
|
|
|
typedef struct CvSampleDistortionData |
|
{ |
|
IplImage* src; |
|
IplImage* erode; |
|
IplImage* dilate; |
|
IplImage* mask; |
|
IplImage* img; |
|
IplImage* maskimg; |
|
int dx; |
|
int dy; |
|
int bgcolor; |
|
} CvSampleDistortionData; |
|
|
|
#if defined CV_OPENMP && (defined _MSC_VER || defined CV_ICC) |
|
#define CV_OPENMP 1 |
|
#else |
|
#undef CV_OPENMP |
|
#endif |
|
|
|
typedef struct CvBackgroundData |
|
{ |
|
int count; |
|
char** filename; |
|
int last; |
|
int round; |
|
CvSize winsize; |
|
} CvBackgroundData; |
|
|
|
typedef struct CvBackgroundReader |
|
{ |
|
CvMat src; |
|
CvMat img; |
|
CvPoint offset; |
|
float scale; |
|
float scalefactor; |
|
float stepfactor; |
|
CvPoint point; |
|
} CvBackgroundReader; |
|
|
|
/* |
|
* Background reader |
|
* Created in each thread |
|
*/ |
|
CvBackgroundReader* cvbgreader = NULL; |
|
|
|
#if defined CV_OPENMP |
|
#pragma omp threadprivate(cvbgreader) |
|
#endif |
|
|
|
CvBackgroundData* cvbgdata = NULL; |
|
|
|
static int icvStartSampleDistortion( const char* imgfilename, int bgcolor, int bgthreshold, |
|
CvSampleDistortionData* data ) |
|
{ |
|
memset( data, 0, sizeof( *data ) ); |
|
data->src = cvLoadImage( imgfilename, 0 ); |
|
if( data->src != NULL && data->src->nChannels == 1 |
|
&& data->src->depth == IPL_DEPTH_8U ) |
|
{ |
|
int r, c; |
|
uchar* pmask; |
|
uchar* psrc; |
|
uchar* perode; |
|
uchar* pdilate; |
|
uchar dd, de; |
|
|
|
data->dx = data->src->width / 2; |
|
data->dy = data->src->height / 2; |
|
data->bgcolor = bgcolor; |
|
|
|
data->mask = cvCloneImage( data->src ); |
|
data->erode = cvCloneImage( data->src ); |
|
data->dilate = cvCloneImage( data->src ); |
|
|
|
/* make mask image */ |
|
for( r = 0; r < data->mask->height; r++ ) |
|
{ |
|
for( c = 0; c < data->mask->width; c++ ) |
|
{ |
|
pmask = ( (uchar*) (data->mask->imageData + r * data->mask->widthStep) |
|
+ c ); |
|
if( bgcolor - bgthreshold <= (int) (*pmask) && |
|
(int) (*pmask) <= bgcolor + bgthreshold ) |
|
{ |
|
*pmask = (uchar) 0; |
|
} |
|
else |
|
{ |
|
*pmask = (uchar) 255; |
|
} |
|
} |
|
} |
|
|
|
/* extend borders of source image */ |
|
cvErode( data->src, data->erode, 0, 1 ); |
|
cvDilate( data->src, data->dilate, 0, 1 ); |
|
for( r = 0; r < data->mask->height; r++ ) |
|
{ |
|
for( c = 0; c < data->mask->width; c++ ) |
|
{ |
|
pmask = ( (uchar*) (data->mask->imageData + r * data->mask->widthStep) |
|
+ c ); |
|
if( (*pmask) == 0 ) |
|
{ |
|
psrc = ( (uchar*) (data->src->imageData + r * data->src->widthStep) |
|
+ c ); |
|
perode = |
|
( (uchar*) (data->erode->imageData + r * data->erode->widthStep) |
|
+ c ); |
|
pdilate = |
|
( (uchar*)(data->dilate->imageData + r * data->dilate->widthStep) |
|
+ c ); |
|
de = (uchar)(bgcolor - (*perode)); |
|
dd = (uchar)((*pdilate) - bgcolor); |
|
if( de >= dd && de > bgthreshold ) |
|
{ |
|
(*psrc) = (*perode); |
|
} |
|
if( dd > de && dd > bgthreshold ) |
|
{ |
|
(*psrc) = (*pdilate); |
|
} |
|
} |
|
} |
|
} |
|
|
|
data->img = cvCreateImage( cvSize( data->src->width + 2 * data->dx, |
|
data->src->height + 2 * data->dy ), |
|
IPL_DEPTH_8U, 1 ); |
|
data->maskimg = cvCloneImage( data->img ); |
|
|
|
return 1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static |
|
void icvPlaceDistortedSample( CvArr* background, |
|
int inverse, int maxintensitydev, |
|
double maxxangle, double maxyangle, double maxzangle, |
|
int inscribe, double maxshiftf, double maxscalef, |
|
CvSampleDistortionData* data ) |
|
{ |
|
double quad[4][2]; |
|
int r, c; |
|
uchar* pimg; |
|
uchar* pbg; |
|
uchar* palpha; |
|
uchar chartmp; |
|
int forecolordev; |
|
float scale; |
|
IplImage* img; |
|
IplImage* maskimg; |
|
CvMat stub; |
|
CvMat* bgimg; |
|
|
|
CvRect cr; |
|
CvRect roi; |
|
|
|
double xshift, yshift, randscale; |
|
|
|
icvRandomQuad( data->src->width, data->src->height, quad, |
|
maxxangle, maxyangle, maxzangle ); |
|
quad[0][0] += (double) data->dx; |
|
quad[0][1] += (double) data->dy; |
|
quad[1][0] += (double) data->dx; |
|
quad[1][1] += (double) data->dy; |
|
quad[2][0] += (double) data->dx; |
|
quad[2][1] += (double) data->dy; |
|
quad[3][0] += (double) data->dx; |
|
quad[3][1] += (double) data->dy; |
|
|
|
cvSet( data->img, cvScalar( data->bgcolor ) ); |
|
cvSet( data->maskimg, cvScalar( 0.0 ) ); |
|
|
|
cvWarpPerspective( data->src, data->img, quad ); |
|
cvWarpPerspective( data->mask, data->maskimg, quad ); |
|
|
|
cvSmooth( data->maskimg, data->maskimg, CV_GAUSSIAN, 3, 3 ); |
|
|
|
bgimg = cvGetMat( background, &stub ); |
|
|
|
cr.x = data->dx; |
|
cr.y = data->dy; |
|
cr.width = data->src->width; |
|
cr.height = data->src->height; |
|
|
|
if( inscribe ) |
|
{ |
|
/* quad's circumscribing rectangle */ |
|
cr.x = (int) MIN( quad[0][0], quad[3][0] ); |
|
cr.y = (int) MIN( quad[0][1], quad[1][1] ); |
|
cr.width = (int) (MAX( quad[1][0], quad[2][0] ) + 0.5F ) - cr.x; |
|
cr.height = (int) (MAX( quad[2][1], quad[3][1] ) + 0.5F ) - cr.y; |
|
} |
|
|
|
xshift = maxshiftf * rand() / RAND_MAX; |
|
yshift = maxshiftf * rand() / RAND_MAX; |
|
|
|
cr.x -= (int) ( xshift * cr.width ); |
|
cr.y -= (int) ( yshift * cr.height ); |
|
cr.width = (int) ((1.0 + maxshiftf) * cr.width ); |
|
cr.height = (int) ((1.0 + maxshiftf) * cr.height); |
|
|
|
randscale = maxscalef * rand() / RAND_MAX; |
|
cr.x -= (int) ( 0.5 * randscale * cr.width ); |
|
cr.y -= (int) ( 0.5 * randscale * cr.height ); |
|
cr.width = (int) ((1.0 + randscale) * cr.width ); |
|
cr.height = (int) ((1.0 + randscale) * cr.height); |
|
|
|
scale = MAX( ((float) cr.width) / bgimg->cols, ((float) cr.height) / bgimg->rows ); |
|
|
|
roi.x = (int) (-0.5F * (scale * bgimg->cols - cr.width) + cr.x); |
|
roi.y = (int) (-0.5F * (scale * bgimg->rows - cr.height) + cr.y); |
|
roi.width = (int) (scale * bgimg->cols); |
|
roi.height = (int) (scale * bgimg->rows); |
|
|
|
img = cvCreateImage( cvSize( bgimg->cols, bgimg->rows ), IPL_DEPTH_8U, 1 ); |
|
maskimg = cvCreateImage( cvSize( bgimg->cols, bgimg->rows ), IPL_DEPTH_8U, 1 ); |
|
|
|
cvSetImageROI( data->img, roi ); |
|
cvResize( data->img, img ); |
|
cvResetImageROI( data->img ); |
|
cvSetImageROI( data->maskimg, roi ); |
|
cvResize( data->maskimg, maskimg ); |
|
cvResetImageROI( data->maskimg ); |
|
|
|
forecolordev = (int) (maxintensitydev * (2.0 * rand() / RAND_MAX - 1.0)); |
|
|
|
for( r = 0; r < img->height; r++ ) |
|
{ |
|
for( c = 0; c < img->width; c++ ) |
|
{ |
|
pimg = (uchar*) img->imageData + r * img->widthStep + c; |
|
pbg = (uchar*) bgimg->data.ptr + r * bgimg->step + c; |
|
palpha = (uchar*) maskimg->imageData + r * maskimg->widthStep + c; |
|
chartmp = (uchar) MAX( 0, MIN( 255, forecolordev + (*pimg) ) ); |
|
if( inverse ) |
|
{ |
|
chartmp ^= 0xFF; |
|
} |
|
*pbg = (uchar) (( chartmp*(*palpha )+(255 - (*palpha) )*(*pbg) ) / 255); |
|
} |
|
} |
|
|
|
cvReleaseImage( &img ); |
|
cvReleaseImage( &maskimg ); |
|
} |
|
|
|
static |
|
void icvEndSampleDistortion( CvSampleDistortionData* data ) |
|
{ |
|
if( data->src ) |
|
{ |
|
cvReleaseImage( &data->src ); |
|
} |
|
if( data->mask ) |
|
{ |
|
cvReleaseImage( &data->mask ); |
|
} |
|
if( data->erode ) |
|
{ |
|
cvReleaseImage( &data->erode ); |
|
} |
|
if( data->dilate ) |
|
{ |
|
cvReleaseImage( &data->dilate ); |
|
} |
|
if( data->img ) |
|
{ |
|
cvReleaseImage( &data->img ); |
|
} |
|
if( data->maskimg ) |
|
{ |
|
cvReleaseImage( &data->maskimg ); |
|
} |
|
} |
|
|
|
static |
|
CvBackgroundData* icvCreateBackgroundData( const char* filename, CvSize winsize ) |
|
{ |
|
CvBackgroundData* data = NULL; |
|
|
|
const char* dir = NULL; |
|
char full[PATH_MAX]; |
|
char* imgfilename = NULL; |
|
size_t datasize = 0; |
|
int count = 0; |
|
FILE* input = NULL; |
|
char* tmp = NULL; |
|
int len = 0; |
|
|
|
assert( filename != NULL ); |
|
|
|
dir = strrchr( filename, '\\' ); |
|
if( dir == NULL ) |
|
{ |
|
dir = strrchr( filename, '/' ); |
|
} |
|
if( dir == NULL ) |
|
{ |
|
imgfilename = &(full[0]); |
|
} |
|
else |
|
{ |
|
strncpy( &(full[0]), filename, (dir - filename + 1) ); |
|
imgfilename = &(full[(dir - filename + 1)]); |
|
} |
|
|
|
input = fopen( filename, "r" ); |
|
if( input != NULL ) |
|
{ |
|
count = 0; |
|
datasize = 0; |
|
|
|
/* count */ |
|
while( !feof( input ) ) |
|
{ |
|
*imgfilename = '\0'; |
|
if( !fgets( imgfilename, PATH_MAX - (int)(imgfilename - full) - 1, input )) |
|
break; |
|
len = (int)strlen( imgfilename ); |
|
for( ; len > 0 && isspace(imgfilename[len-1]); len-- ) |
|
imgfilename[len-1] = '\0'; |
|
if( len > 0 ) |
|
{ |
|
if( (*imgfilename) == '#' ) continue; /* comment */ |
|
count++; |
|
datasize += sizeof( char ) * (strlen( &(full[0]) ) + 1); |
|
} |
|
} |
|
if( count > 0 ) |
|
{ |
|
//rewind( input ); |
|
fseek( input, 0, SEEK_SET ); |
|
datasize += sizeof( *data ) + sizeof( char* ) * count; |
|
data = (CvBackgroundData*) cvAlloc( datasize ); |
|
memset( (void*) data, 0, datasize ); |
|
data->count = count; |
|
data->filename = (char**) (data + 1); |
|
data->last = 0; |
|
data->round = 0; |
|
data->winsize = winsize; |
|
tmp = (char*) (data->filename + data->count); |
|
count = 0; |
|
while( !feof( input ) ) |
|
{ |
|
*imgfilename = '\0'; |
|
if( !fgets( imgfilename, PATH_MAX - (int)(imgfilename - full) - 1, input )) |
|
break; |
|
len = (int)strlen( imgfilename ); |
|
if( len > 0 && imgfilename[len-1] == '\n' ) |
|
imgfilename[len-1] = 0, len--; |
|
if( len > 0 ) |
|
{ |
|
if( (*imgfilename) == '#' ) continue; /* comment */ |
|
data->filename[count++] = tmp; |
|
strcpy( tmp, &(full[0]) ); |
|
tmp += strlen( &(full[0]) ) + 1; |
|
} |
|
} |
|
} |
|
fclose( input ); |
|
} |
|
|
|
return data; |
|
} |
|
|
|
static |
|
void icvReleaseBackgroundData( CvBackgroundData** data ) |
|
{ |
|
assert( data != NULL && (*data) != NULL ); |
|
|
|
cvFree( data ); |
|
} |
|
|
|
static |
|
CvBackgroundReader* icvCreateBackgroundReader() |
|
{ |
|
CvBackgroundReader* reader = NULL; |
|
|
|
reader = (CvBackgroundReader*) cvAlloc( sizeof( *reader ) ); |
|
memset( (void*) reader, 0, sizeof( *reader ) ); |
|
reader->src = cvMat( 0, 0, CV_8UC1, NULL ); |
|
reader->img = cvMat( 0, 0, CV_8UC1, NULL ); |
|
reader->offset = cvPoint( 0, 0 ); |
|
reader->scale = 1.0F; |
|
reader->scalefactor = 1.4142135623730950488016887242097F; |
|
reader->stepfactor = 0.5F; |
|
reader->point = reader->offset; |
|
|
|
return reader; |
|
} |
|
|
|
static |
|
void icvReleaseBackgroundReader( CvBackgroundReader** reader ) |
|
{ |
|
assert( reader != NULL && (*reader) != NULL ); |
|
|
|
if( (*reader)->src.data.ptr != NULL ) |
|
{ |
|
cvFree( &((*reader)->src.data.ptr) ); |
|
} |
|
if( (*reader)->img.data.ptr != NULL ) |
|
{ |
|
cvFree( &((*reader)->img.data.ptr) ); |
|
} |
|
|
|
cvFree( reader ); |
|
} |
|
|
|
static |
|
void icvGetNextFromBackgroundData( CvBackgroundData* data, |
|
CvBackgroundReader* reader ) |
|
{ |
|
IplImage* img = NULL; |
|
size_t datasize = 0; |
|
int round = 0; |
|
int i = 0; |
|
CvPoint offset = cvPoint(0,0); |
|
|
|
assert( data != NULL && reader != NULL ); |
|
|
|
if( reader->src.data.ptr != NULL ) |
|
{ |
|
cvFree( &(reader->src.data.ptr) ); |
|
reader->src.data.ptr = NULL; |
|
} |
|
if( reader->img.data.ptr != NULL ) |
|
{ |
|
cvFree( &(reader->img.data.ptr) ); |
|
reader->img.data.ptr = NULL; |
|
} |
|
|
|
#ifdef CV_OPENMP |
|
#pragma omp critical(c_background_data) |
|
#endif /* CV_OPENMP */ |
|
{ |
|
for( i = 0; i < data->count; i++ ) |
|
{ |
|
round = data->round; |
|
|
|
#ifdef CV_VERBOSE |
|
printf( "Open background image: %s\n", data->filename[data->last] ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
data->last = rand() % data->count; |
|
data->last %= data->count; |
|
img = cvLoadImage( data->filename[data->last], 0 ); |
|
if( !img ) |
|
continue; |
|
data->round += data->last / data->count; |
|
data->round = data->round % (data->winsize.width * data->winsize.height); |
|
|
|
offset.x = round % data->winsize.width; |
|
offset.y = round / data->winsize.width; |
|
|
|
offset.x = MIN( offset.x, img->width - data->winsize.width ); |
|
offset.y = MIN( offset.y, img->height - data->winsize.height ); |
|
|
|
if( img != NULL && img->depth == IPL_DEPTH_8U && img->nChannels == 1 && |
|
offset.x >= 0 && offset.y >= 0 ) |
|
{ |
|
break; |
|
} |
|
if( img != NULL ) |
|
cvReleaseImage( &img ); |
|
img = NULL; |
|
} |
|
} |
|
if( img == NULL ) |
|
{ |
|
/* no appropriate image */ |
|
|
|
#ifdef CV_VERBOSE |
|
printf( "Invalid background description file.\n" ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
assert( 0 ); |
|
exit( 1 ); |
|
} |
|
datasize = sizeof( uchar ) * img->width * img->height; |
|
reader->src = cvMat( img->height, img->width, CV_8UC1, (void*) cvAlloc( datasize ) ); |
|
cvCopy( img, &reader->src, NULL ); |
|
cvReleaseImage( &img ); |
|
img = NULL; |
|
|
|
//reader->offset.x = round % data->winsize.width; |
|
//reader->offset.y = round / data->winsize.width; |
|
reader->offset = offset; |
|
reader->point = reader->offset; |
|
reader->scale = MAX( |
|
((float) data->winsize.width + reader->point.x) / ((float) reader->src.cols), |
|
((float) data->winsize.height + reader->point.y) / ((float) reader->src.rows) ); |
|
|
|
reader->img = cvMat( (int) (reader->scale * reader->src.rows + 0.5F), |
|
(int) (reader->scale * reader->src.cols + 0.5F), |
|
CV_8UC1, (void*) cvAlloc( datasize ) ); |
|
cvResize( &(reader->src), &(reader->img) ); |
|
} |
|
|
|
/* |
|
* icvGetBackgroundImage |
|
* |
|
* Get an image from background |
|
* <img> must be allocated and have size, previously passed to icvInitBackgroundReaders |
|
* |
|
* Usage example: |
|
* icvInitBackgroundReaders( "bg.txt", cvSize( 24, 24 ) ); |
|
* ... |
|
* #pragma omp parallel |
|
* { |
|
* ... |
|
* icvGetBackgourndImage( cvbgdata, cvbgreader, img ); |
|
* ... |
|
* } |
|
* ... |
|
* icvDestroyBackgroundReaders(); |
|
*/ |
|
static |
|
void icvGetBackgroundImage( CvBackgroundData* data, |
|
CvBackgroundReader* reader, |
|
CvMat* img ) |
|
{ |
|
CvMat mat; |
|
|
|
assert( data != NULL && reader != NULL && img != NULL ); |
|
assert( CV_MAT_TYPE( img->type ) == CV_8UC1 ); |
|
assert( img->cols == data->winsize.width ); |
|
assert( img->rows == data->winsize.height ); |
|
|
|
if( reader->img.data.ptr == NULL ) |
|
{ |
|
icvGetNextFromBackgroundData( data, reader ); |
|
} |
|
|
|
mat = cvMat( data->winsize.height, data->winsize.width, CV_8UC1 ); |
|
cvSetData( &mat, (void*) (reader->img.data.ptr + reader->point.y * reader->img.step |
|
+ reader->point.x * sizeof( uchar )), reader->img.step ); |
|
|
|
cvCopy( &mat, img, 0 ); |
|
if( (int) ( reader->point.x + (1.0F + reader->stepfactor ) * data->winsize.width ) |
|
< reader->img.cols ) |
|
{ |
|
reader->point.x += (int) (reader->stepfactor * data->winsize.width); |
|
} |
|
else |
|
{ |
|
reader->point.x = reader->offset.x; |
|
if( (int) ( reader->point.y + (1.0F + reader->stepfactor ) * data->winsize.height ) |
|
< reader->img.rows ) |
|
{ |
|
reader->point.y += (int) (reader->stepfactor * data->winsize.height); |
|
} |
|
else |
|
{ |
|
reader->point.y = reader->offset.y; |
|
reader->scale *= reader->scalefactor; |
|
if( reader->scale <= 1.0F ) |
|
{ |
|
reader->img = cvMat( (int) (reader->scale * reader->src.rows), |
|
(int) (reader->scale * reader->src.cols), |
|
CV_8UC1, (void*) (reader->img.data.ptr) ); |
|
cvResize( &(reader->src), &(reader->img) ); |
|
} |
|
else |
|
{ |
|
icvGetNextFromBackgroundData( data, reader ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
|
* icvInitBackgroundReaders |
|
* |
|
* Initialize background reading process. |
|
* <cvbgreader> and <cvbgdata> are initialized. |
|
* Must be called before any usage of background |
|
* |
|
* filename - name of background description file |
|
* winsize - size of images will be obtained from background |
|
* |
|
* return 1 on success, 0 otherwise. |
|
*/ |
|
static int icvInitBackgroundReaders( const char* filename, CvSize winsize ) |
|
{ |
|
if( cvbgdata == NULL && filename != NULL ) |
|
{ |
|
cvbgdata = icvCreateBackgroundData( filename, winsize ); |
|
} |
|
|
|
if( cvbgdata ) |
|
{ |
|
|
|
#ifdef CV_OPENMP |
|
#pragma omp parallel |
|
#endif /* CV_OPENMP */ |
|
{ |
|
#ifdef CV_OPENMP |
|
#pragma omp critical(c_create_bg_data) |
|
#endif /* CV_OPENMP */ |
|
{ |
|
if( cvbgreader == NULL ) |
|
{ |
|
cvbgreader = icvCreateBackgroundReader(); |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
return (cvbgdata != NULL); |
|
} |
|
|
|
/* |
|
* icvDestroyBackgroundReaders |
|
* |
|
* Finish backgournd reading process |
|
*/ |
|
static |
|
void icvDestroyBackgroundReaders() |
|
{ |
|
/* release background reader in each thread */ |
|
#ifdef CV_OPENMP |
|
#pragma omp parallel |
|
#endif /* CV_OPENMP */ |
|
{ |
|
#ifdef CV_OPENMP |
|
#pragma omp critical(c_release_bg_data) |
|
#endif /* CV_OPENMP */ |
|
{ |
|
if( cvbgreader != NULL ) |
|
{ |
|
icvReleaseBackgroundReader( &cvbgreader ); |
|
cvbgreader = NULL; |
|
} |
|
} |
|
} |
|
|
|
if( cvbgdata != NULL ) |
|
{ |
|
icvReleaseBackgroundData( &cvbgdata ); |
|
cvbgdata = NULL; |
|
} |
|
} |
|
|
|
void cvCreateTrainingSamples( const char* filename, |
|
const char* imgfilename, int bgcolor, int bgthreshold, |
|
const char* bgfilename, int count, |
|
int invert, int maxintensitydev, |
|
double maxxangle, double maxyangle, double maxzangle, |
|
int showsamples, |
|
int winwidth, int winheight ) |
|
{ |
|
CvSampleDistortionData data; |
|
|
|
assert( filename != NULL ); |
|
assert( imgfilename != NULL ); |
|
|
|
if( !icvMkDir( filename ) ) |
|
{ |
|
fprintf( stderr, "Unable to create output file: %s\n", filename ); |
|
return; |
|
} |
|
if( icvStartSampleDistortion( imgfilename, bgcolor, bgthreshold, &data ) ) |
|
{ |
|
FILE* output = NULL; |
|
|
|
output = fopen( filename, "wb" ); |
|
if( output != NULL ) |
|
{ |
|
int hasbg; |
|
int i; |
|
CvMat sample; |
|
int inverse; |
|
|
|
hasbg = 0; |
|
hasbg = (bgfilename != NULL && icvInitBackgroundReaders( bgfilename, |
|
cvSize( winwidth,winheight ) ) ); |
|
|
|
sample = cvMat( winheight, winwidth, CV_8UC1, cvAlloc( sizeof( uchar ) * |
|
winheight * winwidth ) ); |
|
|
|
icvWriteVecHeader( output, count, sample.cols, sample.rows ); |
|
|
|
if( showsamples ) |
|
{ |
|
cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE ); |
|
} |
|
|
|
inverse = invert; |
|
for( i = 0; i < count; i++ ) |
|
{ |
|
if( hasbg ) |
|
{ |
|
icvGetBackgroundImage( cvbgdata, cvbgreader, &sample ); |
|
} |
|
else |
|
{ |
|
cvSet( &sample, cvScalar( bgcolor ) ); |
|
} |
|
|
|
if( invert == CV_RANDOM_INVERT ) |
|
{ |
|
inverse = (rand() > (RAND_MAX/2)); |
|
} |
|
icvPlaceDistortedSample( &sample, inverse, maxintensitydev, |
|
maxxangle, maxyangle, maxzangle, |
|
0 /* nonzero means placing image without cut offs */, |
|
0.0 /* nozero adds random shifting */, |
|
0.0 /* nozero adds random scaling */, |
|
&data ); |
|
|
|
if( showsamples ) |
|
{ |
|
cvShowImage( "Sample", &sample ); |
|
if( cvWaitKey( 0 ) == 27 ) |
|
{ |
|
showsamples = 0; |
|
} |
|
} |
|
|
|
icvWriteVecSample( output, &sample ); |
|
|
|
#ifdef CV_VERBOSE |
|
if( i % 500 == 0 ) |
|
{ |
|
printf( "\r%3d%%", 100 * i / count ); |
|
} |
|
#endif /* CV_VERBOSE */ |
|
} |
|
icvDestroyBackgroundReaders(); |
|
cvFree( &(sample.data.ptr) ); |
|
fclose( output ); |
|
} /* if( output != NULL ) */ |
|
|
|
icvEndSampleDistortion( &data ); |
|
} |
|
|
|
#ifdef CV_VERBOSE |
|
printf( "\r \r" ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
} |
|
|
|
#define CV_INFO_FILENAME "info.dat" |
|
|
|
void cvCreateTestSamples( const char* infoname, |
|
const char* imgfilename, int bgcolor, int bgthreshold, |
|
const char* bgfilename, int count, |
|
int invert, int maxintensitydev, |
|
double maxxangle, double maxyangle, double maxzangle, |
|
int showsamples, |
|
int winwidth, int winheight ) |
|
{ |
|
CvSampleDistortionData data; |
|
|
|
assert( infoname != NULL ); |
|
assert( imgfilename != NULL ); |
|
assert( bgfilename != NULL ); |
|
|
|
if( !icvMkDir( infoname ) ) |
|
{ |
|
|
|
#if CV_VERBOSE |
|
fprintf( stderr, "Unable to create directory hierarchy: %s\n", infoname ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
return; |
|
} |
|
if( icvStartSampleDistortion( imgfilename, bgcolor, bgthreshold, &data ) ) |
|
{ |
|
char fullname[PATH_MAX]; |
|
char* filename; |
|
CvMat win; |
|
FILE* info; |
|
|
|
if( icvInitBackgroundReaders( bgfilename, cvSize( 10, 10 ) ) ) |
|
{ |
|
int i; |
|
int x, y, width, height; |
|
float scale; |
|
float maxscale; |
|
int inverse; |
|
|
|
if( showsamples ) |
|
{ |
|
cvNamedWindow( "Image", CV_WINDOW_AUTOSIZE ); |
|
} |
|
|
|
info = fopen( infoname, "w" ); |
|
strcpy( fullname, infoname ); |
|
filename = strrchr( fullname, '\\' ); |
|
if( filename == NULL ) |
|
{ |
|
filename = strrchr( fullname, '/' ); |
|
} |
|
if( filename == NULL ) |
|
{ |
|
filename = fullname; |
|
} |
|
else |
|
{ |
|
filename++; |
|
} |
|
|
|
count = MIN( count, cvbgdata->count ); |
|
inverse = invert; |
|
for( i = 0; i < count; i++ ) |
|
{ |
|
icvGetNextFromBackgroundData( cvbgdata, cvbgreader ); |
|
|
|
maxscale = MIN( 0.7F * cvbgreader->src.cols / winwidth, |
|
0.7F * cvbgreader->src.rows / winheight ); |
|
if( maxscale < 1.0F ) continue; |
|
|
|
scale = (maxscale - 1.0F) * rand() / RAND_MAX + 1.0F; |
|
width = (int) (scale * winwidth); |
|
height = (int) (scale * winheight); |
|
x = (int) ((0.1+0.8 * rand()/RAND_MAX) * (cvbgreader->src.cols - width)); |
|
y = (int) ((0.1+0.8 * rand()/RAND_MAX) * (cvbgreader->src.rows - height)); |
|
|
|
cvGetSubArr( &cvbgreader->src, &win, cvRect( x, y ,width, height ) ); |
|
if( invert == CV_RANDOM_INVERT ) |
|
{ |
|
inverse = (rand() > (RAND_MAX/2)); |
|
} |
|
icvPlaceDistortedSample( &win, inverse, maxintensitydev, |
|
maxxangle, maxyangle, maxzangle, |
|
1, 0.0, 0.0, &data ); |
|
|
|
|
|
sprintf( filename, "%04d_%04d_%04d_%04d_%04d.jpg", |
|
(i + 1), x, y, width, height ); |
|
|
|
if( info ) |
|
{ |
|
fprintf( info, "%s %d %d %d %d %d\n", |
|
filename, 1, x, y, width, height ); |
|
} |
|
|
|
cvSaveImage( fullname, &cvbgreader->src ); |
|
if( showsamples ) |
|
{ |
|
cvShowImage( "Image", &cvbgreader->src ); |
|
if( cvWaitKey( 0 ) == 27 ) |
|
{ |
|
showsamples = 0; |
|
} |
|
} |
|
} |
|
if( info ) fclose( info ); |
|
icvDestroyBackgroundReaders(); |
|
} |
|
icvEndSampleDistortion( &data ); |
|
} |
|
} |
|
|
|
|
|
int cvCreateTrainingSamplesFromInfo( const char* infoname, const char* vecfilename, |
|
int num, |
|
int showsamples, |
|
int winwidth, int winheight ) |
|
{ |
|
char fullname[PATH_MAX]; |
|
char* filename; |
|
|
|
FILE* info; |
|
FILE* vec; |
|
IplImage* src=0; |
|
IplImage* sample; |
|
int line; |
|
int error; |
|
int i; |
|
int x, y, width, height; |
|
int total; |
|
|
|
assert( infoname != NULL ); |
|
assert( vecfilename != NULL ); |
|
|
|
total = 0; |
|
if( !icvMkDir( vecfilename ) ) |
|
{ |
|
|
|
#if CV_VERBOSE |
|
fprintf( stderr, "Unable to create directory hierarchy: %s\n", vecfilename ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
return total; |
|
} |
|
|
|
info = fopen( infoname, "r" ); |
|
if( info == NULL ) |
|
{ |
|
|
|
#if CV_VERBOSE |
|
fprintf( stderr, "Unable to open file: %s\n", infoname ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
return total; |
|
} |
|
|
|
vec = fopen( vecfilename, "wb" ); |
|
if( vec == NULL ) |
|
{ |
|
|
|
#if CV_VERBOSE |
|
fprintf( stderr, "Unable to open file: %s\n", vecfilename ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
fclose( info ); |
|
|
|
return total; |
|
} |
|
|
|
sample = cvCreateImage( cvSize( winwidth, winheight ), IPL_DEPTH_8U, 1 ); |
|
|
|
icvWriteVecHeader( vec, num, sample->width, sample->height ); |
|
|
|
if( showsamples ) |
|
{ |
|
cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE ); |
|
} |
|
|
|
strcpy( fullname, infoname ); |
|
filename = strrchr( fullname, '\\' ); |
|
if( filename == NULL ) |
|
{ |
|
filename = strrchr( fullname, '/' ); |
|
} |
|
if( filename == NULL ) |
|
{ |
|
filename = fullname; |
|
} |
|
else |
|
{ |
|
filename++; |
|
} |
|
|
|
for( line = 1, error = 0, total = 0; total < num ;line++ ) |
|
{ |
|
int count; |
|
|
|
error = ( fscanf( info, "%s %d", filename, &count ) != 2 ); |
|
if( !error ) |
|
{ |
|
src = cvLoadImage( fullname, 0 ); |
|
error = ( src == NULL ); |
|
if( error ) |
|
{ |
|
|
|
#if CV_VERBOSE |
|
fprintf( stderr, "Unable to open image: %s\n", fullname ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
} |
|
} |
|
for( i = 0; (i < count) && (total < num); i++, total++ ) |
|
{ |
|
error = ( fscanf( info, "%d %d %d %d", &x, &y, &width, &height ) != 4 ); |
|
if( error ) break; |
|
cvSetImageROI( src, cvRect( x, y, width, height ) ); |
|
cvResize( src, sample, width >= sample->width && |
|
height >= sample->height ? CV_INTER_AREA : CV_INTER_LINEAR ); |
|
|
|
if( showsamples ) |
|
{ |
|
cvShowImage( "Sample", sample ); |
|
if( cvWaitKey( 0 ) == 27 ) |
|
{ |
|
showsamples = 0; |
|
} |
|
} |
|
icvWriteVecSample( vec, sample ); |
|
} |
|
|
|
if( src ) |
|
{ |
|
cvReleaseImage( &src ); |
|
} |
|
|
|
if( error ) |
|
{ |
|
|
|
#if CV_VERBOSE |
|
fprintf( stderr, "%s(%d) : parse error", infoname, line ); |
|
#endif /* CV_VERBOSE */ |
|
|
|
break; |
|
} |
|
} |
|
|
|
if( sample ) |
|
{ |
|
cvReleaseImage( &sample ); |
|
} |
|
|
|
fclose( vec ); |
|
fclose( info ); |
|
|
|
return total; |
|
} |
|
|
|
typedef struct CvVecFile |
|
{ |
|
FILE* input; |
|
int count; |
|
int vecsize; |
|
int last; |
|
short* vector; |
|
} CvVecFile; |
|
|
|
static |
|
int icvGetTraininDataFromVec( CvMat* img, void* userdata ) |
|
{ |
|
uchar tmp = 0; |
|
int r = 0; |
|
int c = 0; |
|
|
|
assert( img->rows * img->cols == ((CvVecFile*) userdata)->vecsize ); |
|
|
|
size_t elements_read = fread( &tmp, sizeof( tmp ), 1, ((CvVecFile*) userdata)->input ); |
|
CV_Assert(elements_read == 1); |
|
elements_read = fread( ((CvVecFile*) userdata)->vector, sizeof( short ), |
|
((CvVecFile*) userdata)->vecsize, ((CvVecFile*) userdata)->input ); |
|
CV_Assert(elements_read == (size_t)((CvVecFile*) userdata)->vecsize); |
|
|
|
if( feof( ((CvVecFile*) userdata)->input ) || |
|
(((CvVecFile*) userdata)->last)++ >= ((CvVecFile*) userdata)->count ) |
|
{ |
|
return 0; |
|
} |
|
|
|
for( r = 0; r < img->rows; r++ ) |
|
{ |
|
for( c = 0; c < img->cols; c++ ) |
|
{ |
|
CV_MAT_ELEM( *img, uchar, r, c ) = |
|
(uchar) ( ((CvVecFile*) userdata)->vector[r * img->cols + c] ); |
|
} |
|
} |
|
|
|
return 1; |
|
} |
|
void cvShowVecSamples( const char* filename, int winwidth, int winheight, |
|
double scale ) |
|
{ |
|
CvVecFile file; |
|
short tmp; |
|
int i; |
|
CvMat* sample; |
|
|
|
tmp = 0; |
|
file.input = fopen( filename, "rb" ); |
|
|
|
if( file.input != NULL ) |
|
{ |
|
size_t elements_read1 = fread( &file.count, sizeof( file.count ), 1, file.input ); |
|
size_t elements_read2 = fread( &file.vecsize, sizeof( file.vecsize ), 1, file.input ); |
|
size_t elements_read3 = fread( &tmp, sizeof( tmp ), 1, file.input ); |
|
size_t elements_read4 = fread( &tmp, sizeof( tmp ), 1, file.input ); |
|
CV_Assert(elements_read1 == 1 && elements_read2 == 1 && elements_read3 == 1 && elements_read4 == 1); |
|
|
|
if( file.vecsize != winwidth * winheight ) |
|
{ |
|
int guessed_w = 0; |
|
int guessed_h = 0; |
|
|
|
fprintf( stderr, "Warning: specified sample width=%d and height=%d " |
|
"does not correspond to .vec file vector size=%d.\n", |
|
winwidth, winheight, file.vecsize ); |
|
if( file.vecsize > 0 ) |
|
{ |
|
guessed_w = cvFloor( sqrt( (float) file.vecsize ) ); |
|
if( guessed_w > 0 ) |
|
{ |
|
guessed_h = file.vecsize / guessed_w; |
|
} |
|
} |
|
|
|
if( guessed_w <= 0 || guessed_h <= 0 || guessed_w * guessed_h != file.vecsize) |
|
{ |
|
fprintf( stderr, "Error: failed to guess sample width and height\n" ); |
|
fclose( file.input ); |
|
|
|
return; |
|
} |
|
else |
|
{ |
|
winwidth = guessed_w; |
|
winheight = guessed_h; |
|
fprintf( stderr, "Guessed width=%d, guessed height=%d\n", |
|
winwidth, winheight ); |
|
} |
|
} |
|
|
|
if( !feof( file.input ) && scale > 0 ) |
|
{ |
|
CvMat* scaled_sample = 0; |
|
|
|
file.last = 0; |
|
file.vector = (short*) cvAlloc( sizeof( *file.vector ) * file.vecsize ); |
|
sample = scaled_sample = cvCreateMat( winheight, winwidth, CV_8UC1 ); |
|
if( scale != 1.0 ) |
|
{ |
|
scaled_sample = cvCreateMat( MAX( 1, cvCeil( scale * winheight ) ), |
|
MAX( 1, cvCeil( scale * winwidth ) ), |
|
CV_8UC1 ); |
|
} |
|
cvNamedWindow( "Sample", CV_WINDOW_AUTOSIZE ); |
|
for( i = 0; i < file.count; i++ ) |
|
{ |
|
icvGetTraininDataFromVec( sample, &file ); |
|
if( scale != 1.0 ) cvResize( sample, scaled_sample, CV_INTER_LINEAR); |
|
cvShowImage( "Sample", scaled_sample ); |
|
if( cvWaitKey( 0 ) == 27 ) break; |
|
} |
|
if( scaled_sample && scaled_sample != sample ) cvReleaseMat( &scaled_sample ); |
|
cvReleaseMat( &sample ); |
|
cvFree( &file.vector ); |
|
} |
|
fclose( file.input ); |
|
} |
|
} |