12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463 |
- /*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/imgcodecs.hpp"
- #include "opencv2/imgproc.hpp"
- #include "opencv2/highgui.hpp"
- #include "opencv2/calib3d.hpp"
- #if defined __GNUC__ && __GNUC__ >= 8
- #pragma GCC diagnostic ignored "-Wclass-memaccess"
- #endif
- using namespace cv;
- #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, Mat sample )
- {
- uchar chartmp = 0;
- fwrite( &chartmp, sizeof( chartmp ), 1, file );
- for(int r = 0; r < sample.rows; r++ )
- {
- for(int c = 0; c < sample.cols; c++ )
- {
- short tmp = sample.at<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( Size src_size, double quad[4][2], double coeffs[3][3] )
- {
- double a[8][8];
- double b[8];
- Mat A( 8, 8, CV_64FC1, a );
- Mat B( 8, 1, CV_64FC1, b );
- Mat X( 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;
- solve( A, B, X );
- coeffs[2][2] = 1;
- }
- /* Warps source into destination by a perspective transform */
- static void cvWarpPerspective( Mat src, Mat dst, double quad[4][2] )
- {
- 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;
- double d = 0;
- int direction = 0;
- int i;
- if( src.type() != CV_8UC1 || src.dims != 2 )
- {
- CV_Error( Error::StsBadArg,
- "Source must be two-dimensional array of CV_8UC1 type." );
- }
- if( dst.type() != CV_8UC1 || dst.dims != 2 )
- {
- CV_Error( Error::StsBadArg,
- "Destination must be two-dimensional array of CV_8UC1 type." );
- }
- 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 = d > 0 ? 1 : d < 0 ? -1 : 0;
- if( direction == 0 )
- {
- direction = cur_direction;
- }
- else if( direction * cur_direction < 0 )
- {
- direction = 0;
- break;
- }
- }
- if( direction == 0 )
- {
- CV_Error(Error::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.rows - 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.cols - 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;
- int i00, i10, i01, i11;
- i00 = i10 = i01 = i11 = (int) fill_value;
- /* linear interpolation using 2x2 neighborhood */
- if( isrc_x >= 0 && isrc_x < src.cols &&
- isrc_y >= 0 && isrc_y < src.rows )
- {
- i00 = src.at<uchar>(isrc_y, isrc_x);
- }
- if( isrc_x >= -1 && isrc_x + 1 < src.cols &&
- isrc_y >= 0 && isrc_y < src.rows )
- {
- i10 = src.at<uchar>(isrc_y, isrc_x + 1);
- }
- if( isrc_x >= 0 && isrc_x < src.cols &&
- isrc_y >= -1 && isrc_y + 1 < src.rows )
- {
- i01 = src.at<uchar>(isrc_y + 1, isrc_x);
- }
- if( isrc_x >= -1 && isrc_x + 1 < src.cols &&
- isrc_y >= -1 && isrc_y + 1 < src.rows )
- {
- i11 = src.at<uchar>(isrc_y + 1, isrc_x + 1);
- }
- double i0 = i00 + (i10 - i00)*delta_x;
- double i1 = i01 + (i11 - i01)*delta_x;
- dst.at<uchar>(y, 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;
- }
- }
- 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];
- double d;
- Mat rotVect( 3, 1, CV_64FC1, &rotVectData[0] );
- Mat rotMat( 3, 3, CV_64FC1, &rotMatData[0] );
- Mat vect( 3, 1, CV_64FC1, &vectData[0] );
- rotVectData[0] = theRNG().uniform( -maxxangle, maxxangle );
- rotVectData[1] = ( maxyangle - fabs( rotVectData[0] ) ) * theRNG().uniform( -1.0, 1.0 );
- rotVectData[2] = theRNG().uniform( -maxzangle, maxzangle );
- d = ( distfactor + distfactor2 * theRNG().uniform( -1.0, 1.0 ) ) * width;
- Rodrigues( 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;
- gemm(rotMat, rotVect, 1., Mat(), 1., vect);
- quad[i][0] = vectData[0] * d / (d + vectData[2]) + halfw;
- quad[i][1] = vectData[1] * d / (d + vectData[2]) + halfh;
- }
- }
- typedef struct CvSampleDistortionData
- {
- Mat src;
- Mat erode;
- Mat dilate;
- Mat mask;
- Mat img;
- Mat 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;
- Size winsize;
- } CvBackgroundData;
- typedef struct CvBackgroundReader
- {
- Mat src;
- Mat img;
- Point offset;
- float scale;
- float scalefactor;
- float stepfactor;
- Point 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 = imread( imgfilename, IMREAD_GRAYSCALE );
- if( !(data->src.empty()) && data->src.type() == CV_8UC1 )
- {
- int r, c;
- data->dx = data->src.cols / 2;
- data->dy = data->src.rows / 2;
- data->bgcolor = bgcolor;
- data->mask = data->src.clone();
- data->erode = data->src.clone();
- data->dilate = data->src.clone();
- /* make mask image */
- for( r = 0; r < data->mask.rows; r++ )
- {
- for( c = 0; c < data->mask.cols; c++ )
- {
- uchar& pmask = data->mask.at<uchar>(r, c);
- if( bgcolor - bgthreshold <= (int)pmask &&
- (int)pmask <= bgcolor + bgthreshold )
- {
- pmask = (uchar) 0;
- }
- else
- {
- pmask = (uchar) 255;
- }
- }
- }
- /* extend borders of source image */
- erode( data->src, data->erode, Mat() );
- dilate( data->src, data->dilate, Mat() );
- for( r = 0; r < data->mask.rows; r++ )
- {
- for( c = 0; c < data->mask.cols; c++ )
- {
- uchar& pmask = data->mask.at<uchar>(r, c);
- if( pmask == 0 )
- {
- uchar& psrc = data->src.at<uchar>(r, c);
- uchar& perode = data->erode.at<uchar>(r, c);
- uchar& pdilate = data->dilate.at<uchar>(r, c);
- uchar de = (uchar)(bgcolor - perode);
- uchar dd = (uchar)(pdilate - bgcolor);
- if( de >= dd && de > bgthreshold )
- {
- psrc = perode;
- }
- if( dd > de && dd > bgthreshold )
- {
- psrc = pdilate;
- }
- }
- }
- }
- data->img = Mat(Size( data->src.cols + 2 * data->dx, data->src.rows + 2 * data->dy ), CV_8UC1);
- data->maskimg = Mat(Size(data->src.cols + 2 * data->dx, data->src.rows + 2 * data->dy), CV_8UC1);
- return 1;
- }
- return 0;
- }
- static
- void icvPlaceDistortedSample( Mat 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;
- int forecolordev;
- float scale;
- Rect cr;
- Rect roi;
- double xshift, yshift, randscale;
- icvRandomQuad( data->src.cols, data->src.rows, 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;
- data->img = data->bgcolor;
- data->maskimg = 0;
- cvWarpPerspective( data->src, data->img, quad );
- cvWarpPerspective( data->mask, data->maskimg, quad );
- GaussianBlur( data->maskimg, data->maskimg, Size(3, 3), 0, 0 );
- cr.x = data->dx;
- cr.y = data->dy;
- cr.width = data->src.cols;
- cr.height = data->src.rows;
- 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 = theRNG().uniform( 0., maxshiftf );
- yshift = theRNG().uniform( 0., maxshiftf );
- 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 = theRNG().uniform( 0., maxscalef );
- 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) / background.cols, ((float) cr.height) / background.rows );
- roi.x = (int) (-0.5F * (scale * background.cols - cr.width) + cr.x);
- roi.y = (int) (-0.5F * (scale * background.rows - cr.height) + cr.y);
- roi.width = (int) (scale * background.cols);
- roi.height = (int) (scale * background.rows);
- Mat img( background.size(), CV_8UC1 );
- Mat maskimg( background.size(), CV_8UC1 );
- resize( data->img(roi & Rect(Point(0,0), data->img.size())), img, img.size(), 0, 0, INTER_LINEAR_EXACT);
- resize( data->maskimg(roi & Rect(Point(0, 0), data->maskimg.size())), maskimg, maskimg.size(), 0, 0, INTER_LINEAR_EXACT);
- forecolordev = theRNG().uniform( -maxintensitydev, maxintensitydev );
- for( r = 0; r < img.rows; r++ )
- {
- for( c = 0; c < img.cols; c++ )
- {
- uchar& pbg = background.at<uchar>(r, c);
- uchar& palpha = maskimg.at<uchar>(r, c);
- uchar chartmp = (uchar) MAX( 0, MIN( 255, forecolordev + img.at<uchar>(r, c)) );
- if( inverse )
- {
- chartmp ^= 0xFF;
- }
- pbg = (uchar) ((chartmp*palpha + (255 - palpha)*pbg) / 255);
- }
- }
- }
- static
- CvBackgroundData* icvCreateBackgroundData( const char* filename, Size 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;
- CV_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*) fastMalloc( 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
- CvBackgroundReader* icvCreateBackgroundReader()
- {
- CvBackgroundReader* reader = NULL;
- reader = new CvBackgroundReader;
- reader->scale = 1.0F;
- reader->scalefactor = 1.4142135623730950488016887242097F;
- reader->stepfactor = 0.5F;
- return reader;
- }
- static
- void icvGetNextFromBackgroundData( CvBackgroundData* data,
- CvBackgroundReader* reader )
- {
- Mat img;
- int round = 0;
- int i = 0;
- Point offset;
- CV_Assert( data != NULL && reader != NULL );
- #ifdef CV_OPENMP
- #pragma omp critical(c_background_data)
- #endif /* CV_OPENMP */
- {
- for( i = 0; i < data->count; i++ )
- {
- round = data->round;
- data->last = theRNG().uniform( 0, RAND_MAX ) % data->count;
- #ifdef CV_VERBOSE
- printf( "Open background image: %s\n", data->filename[data->last] );
- #endif /* CV_VERBOSE */
- img = imread( data->filename[data->last], IMREAD_GRAYSCALE );
- if( img.empty() )
- 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.cols - data->winsize.width );
- offset.y = MIN( offset.y, img.rows - data->winsize.height );
- if( !img.empty() && img.type() == CV_8UC1 && offset.x >= 0 && offset.y >= 0 )
- {
- break;
- }
- img = Mat();
- }
- }
- if( img.empty() )
- {
- /* no appropriate image */
- #ifdef CV_VERBOSE
- printf( "Invalid background description file.\n" );
- #endif /* CV_VERBOSE */
- CV_Assert( 0 );
- exit( 1 );
- }
- reader->src = img;
- //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) );
- resize( reader->src, reader->img,
- Size((int)(reader->scale * reader->src.cols + 0.5F), (int)(reader->scale * reader->src.rows + 0.5F)), 0, 0, INTER_LINEAR_EXACT);
- }
- /*
- * 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
- * {
- * ...
- * icvGetBackgroundImage( cvbgdata, cvbgreader, img );
- * ...
- * }
- * ...
- * icvDestroyBackgroundReaders();
- */
- static
- void icvGetBackgroundImage( CvBackgroundData* data,
- CvBackgroundReader* reader,
- Mat& img )
- {
- CV_Assert( data != NULL && reader != NULL );
- if( reader->img.empty() )
- {
- icvGetNextFromBackgroundData( data, reader );
- }
- img = reader->img(Rect(reader->point.x, reader->point.y, data->winsize.width, data->winsize.height)).clone();
- 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 )
- {
- resize(reader->src, reader->img,
- Size((int)(reader->scale * reader->src.cols), (int)(reader->scale * reader->src.rows)), 0, 0, INTER_LINEAR_EXACT);
- }
- 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, Size 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 background 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 )
- {
- delete cvbgreader;
- cvbgreader = NULL;
- }
- }
- }
- if( cvbgdata != NULL )
- {
- fastFree(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;
- CV_Assert( filename != NULL );
- CV_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 i;
- int inverse;
- const int hasbg = (bgfilename != NULL && icvInitBackgroundReaders( bgfilename,
- Size( winwidth,winheight ) ) );
- Mat sample( winheight, winwidth, CV_8UC1 );
- icvWriteVecHeader( output, count, sample.cols, sample.rows );
- if( showsamples )
- {
- namedWindow( "Sample", WINDOW_AUTOSIZE );
- }
- inverse = invert;
- for( i = 0; i < count; i++ )
- {
- if( hasbg )
- {
- icvGetBackgroundImage( cvbgdata, cvbgreader, sample );
- }
- else
- {
- sample = bgcolor;
- }
- if( invert == CV_RANDOM_INVERT )
- {
- inverse = theRNG().uniform( 0, 2 );
- }
- icvPlaceDistortedSample( sample, inverse, maxintensitydev,
- maxxangle, maxyangle, maxzangle,
- 0 /* nonzero means placing image without cut offs */,
- 0.0 /* nonzero adds random shifting */,
- 0.0 /* nonzero adds random scaling */,
- &data );
- if( showsamples )
- {
- imshow( "Sample", sample );
- if( (waitKey( 0 ) & 0xFF) == 27 )
- {
- showsamples = 0;
- }
- }
- icvWriteVecSample( output, sample );
- #ifdef CV_VERBOSE
- if( i % 500 == 0 )
- {
- printf( "\r%3d%%", 100 * i / count );
- }
- #endif /* CV_VERBOSE */
- }
- icvDestroyBackgroundReaders();
- fclose( output );
- } /* if( output != NULL ) */
- }
- #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, double maxscale )
- {
- CvSampleDistortionData data;
- CV_Assert( infoname != NULL );
- CV_Assert( imgfilename != NULL );
- CV_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;
- FILE* info;
- if( icvInitBackgroundReaders( bgfilename, Size( 10, 10 ) ) )
- {
- int i;
- int x, y, width, height;
- float scale;
- int inverse;
- if( showsamples )
- {
- namedWindow( "Image", 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 );
- if( maxscale < 0.0 )
- {
- maxscale = MIN( 0.7F * cvbgreader->src.cols / winwidth,
- 0.7F * cvbgreader->src.rows / winheight );
- }
- if( maxscale < 1.0F ) continue;
- scale = theRNG().uniform( 1.0F, (float)maxscale );
- width = (int) (scale * winwidth);
- height = (int) (scale * winheight);
- x = (int) ( theRNG().uniform( 0.1, 0.8 ) * (cvbgreader->src.cols - width));
- y = (int) ( theRNG().uniform( 0.1, 0.8 ) * (cvbgreader->src.rows - height));
- if( invert == CV_RANDOM_INVERT )
- {
- inverse = theRNG().uniform( 0, 2 );
- }
- icvPlaceDistortedSample( cvbgreader->src(Rect(x, y, width, height)), 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 );
- }
- imwrite( fullname, cvbgreader->src );
- if( showsamples )
- {
- imshow( "Image", cvbgreader->src );
- if( (waitKey( 0 ) & 0xFF) == 27 )
- {
- showsamples = 0;
- }
- }
- }
- if( info ) fclose( info );
- icvDestroyBackgroundReaders();
- }
- }
- }
- 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;
- int line;
- int error;
- int i;
- int x, y, width, height;
- int total;
- CV_Assert( infoname != NULL );
- CV_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;
- }
- icvWriteVecHeader( vec, num, winwidth, winheight );
- if( showsamples )
- {
- namedWindow( "Sample", 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++ )
- {
- Mat src;
- int count;
- if(fscanf(info, "%s %d", filename, &count) == 2)
- {
- src = imread( fullname, IMREAD_GRAYSCALE );
- if(src.empty())
- {
- #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;
- Mat sample;
- resize( src(Rect(x, y, width, height)), sample, Size(winwidth, winheight), 0, 0,
- width >= winwidth && height >= winheight ? INTER_AREA : INTER_LINEAR_EXACT );
- if( showsamples )
- {
- imshow( "Sample", sample );
- if( (waitKey( 0 ) & 0xFF) == 27 )
- {
- showsamples = 0;
- }
- }
- icvWriteVecSample( vec, sample );
- }
- if( error )
- {
- #if CV_VERBOSE
- fprintf( stderr, "%s(%d) : parse error", infoname, line );
- #endif /* CV_VERBOSE */
- break;
- }
- }
- fclose( vec );
- fclose( info );
- return total;
- }
- typedef struct CvVecFile
- {
- FILE* input;
- int count;
- int vecsize;
- int last;
- } CvVecFile;
- static
- int icvGetTraininDataFromVec( Mat& img, CvVecFile& userdata )
- {
- AutoBuffer<short> vector(userdata.vecsize);
- uchar tmp = 0;
- int r = 0;
- int c = 0;
- CV_Assert( img.rows * img.cols == userdata.vecsize );
- size_t elements_read = fread( &tmp, sizeof( tmp ), 1, userdata.input );
- CV_Assert(elements_read == 1);
- elements_read = fread(vector.data(), sizeof(short), userdata.vecsize, userdata.input);
- CV_Assert(elements_read == (size_t)userdata.vecsize);
- if( feof( userdata.input ) || userdata.last++ >= userdata.count )
- {
- return 0;
- }
- for( r = 0; r < img.rows; r++ )
- {
- for( c = 0; c < img.cols; c++ )
- {
- img.at<uchar>(r, c) = (uchar) ( vector[r * img.cols + c] );
- }
- }
- return 1;
- }
- void cvShowVecSamples( const char* filename, int winwidth, int winheight,
- double scale )
- {
- CvVecFile file;
- short tmp;
- int i;
- 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 )
- {
- file.last = 0;
- namedWindow( "Sample", WINDOW_AUTOSIZE );
- for( i = 0; i < file.count; i++ )
- {
- Mat sample(winheight, winwidth, CV_8UC1);
- icvGetTraininDataFromVec( sample, file );
- if( scale != 1.0 )
- resize( sample, sample,
- Size(MAX(1, cvCeil(scale * winwidth)), MAX(1, cvCeil(scale * winheight))), 0, 0, INTER_LINEAR_EXACT);
- imshow( "Sample", sample );
- if( waitKey( 0 ) == 27 ) break;
- }
- }
- fclose( file.input );
- }
- }
|