bool brightRGB::getMax(const image& img,dvector& dest) const{ // image empty? if (img.empty()) { setStatusString("image empty"); dest.resize(0); return false; } const rgbPixel transColor = getParameters().transColor; ivector maxV(3,-1); image::const_iterator it = img.begin(); if(getParameters().transparent) { while(it != img.end()) { if(*it != transColor) { if((*it).getRed() > maxV.at(0)) maxV.at(0) = (*it).getRed(); if((*it).getGreen() > maxV.at(1)) maxV.at(1) = (*it).getGreen(); if((*it).getBlue() > maxV.at(2)) maxV.at(2) = (*it).getBlue(); } it++; } // only transparent pixels? if (maxV.at(0)==-1) { setStatusString("only transparent pixels"); dest.resize(0); return false; } } else { // no transparent color while(it != img.end()) { if((*it).getRed() > maxV.at(0)) maxV.at(0) = (*it).getRed(); if((*it).getGreen() > maxV.at(1)) maxV.at(1) = (*it).getGreen(); if((*it).getBlue() > maxV.at(2)) maxV.at(2) = (*it).getBlue(); it++; } } if(maxV.at(0) == -1) return false; dest.castFrom(maxV); // normalize to 0..1 dest.divide(255); return true; };
bool brightRGB::getAverage(const image& img,dvector& dest) const{ const rgbPixel transColor = getParameters().transColor; dvector avg(3,0.0); image::const_iterator it = img.begin(); // check for empty image if (img.columns()==0 || img.rows()==0) { setStatusString("image empty"); dest.resize(0); return false; } if(getParameters().transparent) { int counter = 0; while(it != img.end()) { if(*it != transColor) { avg.at(0) += (*it).getRed(); avg.at(1) += (*it).getGreen(); avg.at(2) += (*it).getBlue(); ++counter; } it++; } // check for completely transparent image if (counter==0) { setStatusString("only transparent pixels"); dest.resize(0); return false; } avg.divide(counter); } else { // no transparent color while(it != img.end()) { avg.at(0) += (*it).getRed(); avg.at(1) += (*it).getGreen(); avg.at(2) += (*it).getBlue(); it++; } avg.divide(img.columns()*img.rows()); } // values between 0 and 1 dest.divide(avg, 255.); return true; };
/* * compute mat*vct' where vct' is a vector with one additional element * (1.0) at the beginning of vct. */ bool MLP::biasMultiply(const dmatrix& mat, const dvector& vct, dvector& res) const { int j; dmatrix::const_iterator it,eit; dvector::iterator rit; dvector::const_iterator vit,evit; res.resize(mat.rows(),0.0,false,false); it = mat.begin(); eit = mat.end(); rit = res.begin(); evit = vct.end(); for (j=0;j<mat.rows();++j,++rit) { *rit = *it; ++it; for (vit=vct.begin();vit!=evit;++it,++vit) { *rit += (*vit)*(*it); } } return true; }
/** solve linear equation using LU decomposition by lapack library DGESVX (_a must be square matrix) */ int solveLinearEquationLU(const dmatrix &_a, const dvector &_b, dvector &_x) { assert(_a.cols() == _a.rows() && _a.cols() == _b.size() ); int n = (int)_a.cols(); int nrhs = 1; int lda = n; std::vector<int> ipiv(n); int ldb = n; int info; // compute the solution #ifndef USE_CLAPACK_INTERFACE char fact = 'N'; char transpose = 'N'; double *af = new double[n*n]; int ldaf = n; char equed = 'N'; double *r = new double[n]; double *c = new double[n]; int ldx = n; double rcond; double *ferr = new double[nrhs]; double *berr = new double[nrhs]; double *work = new double[4*n]; int *iwork = new int[n]; _x.resize(n); // memory allocation for the return vector dgesvx_(&fact, &transpose, &n, &nrhs, const_cast<double *>(&(_a(0,0))), &lda, af, &ldaf, &(ipiv[0]), &equed, r, c, const_cast<double *>(&(_b(0))), &ldb, &(_x(0)), &ldx, &rcond, ferr, berr, work, iwork, &info); delete [] iwork; delete [] work; delete [] berr; delete [] ferr; delete [] c; delete [] r; delete [] af; #else _x = _b; info = clapack_dgesv(CblasColMajor, n, nrhs, const_cast<double *>(&(a(0,0))), lda, &(ipiv[0]), &(_x(0)), ldb); #endif return info; }
/** solve linear equation using SVD(Singular Value Decomposition) by lapack library DGESVD (_a can be non-square matrix) */ int solveLinearEquationSVD(const dmatrix &_a, const dvector &_b, dvector &_x, double _sv_ratio) { const int m = _a.rows(); const int n = _a.cols(); assert( m == static_cast<int>(_b.size()) ); _x.resize(n); int i, j; char jobu = 'A'; char jobvt = 'A'; int max_mn = max(m,n); int min_mn = min(m,n); dmatrix a(m,n); a = _a; int lda = m; double *s = new double[max_mn]; // singular values int ldu = m; double *u = new double[ldu*m]; int ldvt = n; double *vt = new double[ldvt*n]; int lwork = max(3*min_mn+max_mn, 5*min_mn); // for CLAPACK ver.2 & ver.3 double *work = new double[lwork]; int info; for(i = 0; i < max_mn; i++) s[i] = 0.0; dgesvd_(&jobu, &jobvt, &m, &n, &(a(0,0)), &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info); double tmp; double smin, smax=0.0; for (j = 0; j < min_mn; j++) if (s[j] > smax) smax = s[j]; smin = smax*_sv_ratio; // 1.0e-3; for (j = 0; j < min_mn; j++) if (s[j] < smin) s[j] = 0.0; double *utb = new double[m]; // U^T*b for (j = 0; j < m; j++){ tmp = 0; if (s[j]){ for (i = 0; i < m; i++) tmp += u[j*m+i] * _b(i); tmp /= s[j]; } utb[j] = tmp; } // v*utb for (j = 0; j < n; j++){ tmp = 0; for (i = 0; i < n; i++){ if(s[i]) tmp += utb[i] * vt[j*n+i]; } _x(j) = tmp; } delete [] utb; delete [] work; delete [] vt; delete [] s; delete [] u; return info; }
void copy_from_host(dvector<T> &out, const std::vector<T> &in) { out.resize(in.size()); out.copy_from_host(&in[0], in.size()); }
/* * calculate gradient of error surface using back-propagation algorithm * * @param input input vector * @param outputId desired output. This value must be between 0 and * the number of output elements-1. * @param grad computed gradient of the error surface * @return true if successful, or false otherwise. */ bool MLP::calcGradient(const dvector& input, const int outputId, dvector& grad) { const parameters& param = getParameters(); const int layers = param.hiddenUnits.size()+1; propagate(input); grad.resize(weights.size()); int i,j,jj,k,idx,lastIdx; int layer = layerIndex.size()-1; double delta; // compute f'(net) at unitsNet for (i=0;i<layers;++i) { param.activationFunctions[i]->deriv(unitsNet[i]); } // --------------------------------------------- // gradient for the elements of the output layer // --------------------------------------------- const dmatrix& outMat = matWeights[layer]; const dvector* theInput = 0; if (layer>0) { theInput = &unitsOut[layer-1]; } else { theInput = &input; } idx = layerIndex.at(layer); dvector lastDeltas,newDeltas; lastDeltas.resize(outMat.rows(),0,false,false); for (j=0;j<outMat.rows();++j) { delta = ((((j==outputId)?on:off) - unitsOut[layer].at(j)) * unitsNet[layer].at(j)); lastDeltas.at(j)=delta; grad.at(idx)=delta; // bias = 1.0 ++idx; for (i=0;i<theInput->size();++i,++idx) { // idx means layerIndex.at(layer)+i+j*ROWS grad.at(idx) = delta*theInput->at(i); } } // ---------------------------------------------- // gradient for the elements of the hidden layers // ---------------------------------------------- --layer; while (layer>=0) { const dmatrix& outMat = matWeights[layer]; const dmatrix& lastMat = matWeights[layer+1]; const dvector* theInput = 0; if (layer>0) { theInput = &unitsOut[layer-1]; } else { theInput = &input; } idx = layerIndex.at(layer); lastIdx = theInput->size(); newDeltas.resize(outMat.rows(),0.0,false,false); for (j=0,jj=1;j<outMat.rows();++j,++jj) { delta = 0; for (k=0;k<lastMat.rows();++k) { delta+=(lastDeltas.at(k)*lastMat.at(k,jj)); } delta*=unitsNet[layer].at(j); newDeltas.at(j)=delta; grad.at(idx)=delta; // bias = 1.0 ++idx; for (i=0;i<lastIdx;++i,++idx) { // idx means layerIndex.at(layer)+i+j*ROWS grad.at(idx) = delta*theInput->at(i); } } newDeltas.detach(lastDeltas); // continue with next layer --layer; }; return true; }
bool brightRGB::getMedian(const image& img,dvector& dest) const{ // image empty? if (img.empty()) { setStatusString("image empty"); dest.resize(0); return false; } const rgbPixel transColor = getParameters().transColor; dest.resize(3); ivector hist0(256,0); ivector hist1(256,0); ivector hist2(256,0); image::const_iterator it = img.begin(); if(getParameters().transparent) { while(it != img.end()) { if(*it != transColor) { ++hist0.at((*it).getRed()); ++hist1.at((*it).getGreen()); ++hist2.at((*it).getBlue()); } it++; } const int counterHalf = hist0.sumOfElements()/2; // check for complete image transparent if (counterHalf==0) { setStatusString("only transparent pixels"); dest.resize(0); return false; } int i,s; i=-1,s=0; while(++i<256 && s<counterHalf) { s += hist0.at(i); } dest.at(0) = i-1; i=-1,s=0; while(++i<256 && s<counterHalf) { s += hist1.at(i); } dest.at(1) = i-1; i=-1,s=0; while(++i<256 && s<counterHalf) { s += hist2.at(i); } dest.at(2) = i-1; } else { // no transparent color while(it != img.end()) { ++hist0.at((*it).getRed()); ++hist1.at((*it).getGreen()); ++hist2.at((*it).getBlue()); it++; } const int counterHalf = img.columns()*img.rows()/2; int i,s; i=-1,s=0; while(++i<256 && s<counterHalf) { s += hist0.at(i); } dest.at(0) = i-1; i=-1,s=0; while(++i<256 && s<counterHalf) { s += hist1.at(i); } dest.at(1) = i-1; i=-1,s=0; while(++i<256 && s<counterHalf) { s += hist2.at(i); } dest.at(2) = i-1; } // normalize to 0..1 dest.divide(255); return true; };
// On copy apply for type image! bool histogramRGBL::apply(const image& src,dvector& dest) const { if (src.empty()) { dest.clear(); setStatusString("input channel empty"); return false; } const parameters& param = getParameters(); int theMin(0),theMax(255); const int lastIdx = param.cells-1; const float m = float(lastIdx)/(theMax-theMin); int y,r,g,b,l; int idx; int entries; vector<rgbPixel>::const_iterator it,eit; dest.resize(4*param.cells,0.0,false,true); // initialize with 0 dvector theR(param.cells,0.0); dvector theG(param.cells,0.0); dvector theB(param.cells,0.0); dvector theL(param.cells,0.0); entries = 0; // if b too small, it's possible to calculate everything faster... // check if the ignore value if (param.considerAllData) { for (y=0;y<src.rows();++y) { const vector<rgbPixel>& vct = src.getRow(y); for (it=vct.begin(),eit=vct.end();it!=eit;++it) { r = (*it).getRed(); g = (*it).getGreen(); b = (*it).getBlue(); l = (min(r,g,b)+max(r,g,b))/2; idx = static_cast<int>(r*m); theR.at(idx)++; idx = static_cast<int>(g*m); theG.at(idx)++; idx = static_cast<int>(b*m); theB.at(idx)++; idx = static_cast<int>(l*m); theL.at(idx)++; entries++; } } } else { for (y=0;y<src.rows();++y) { const vector<rgbPixel>& vct = src.getRow(y); for (it=vct.begin(),eit=vct.end();it!=eit;++it) { if ((*it) != param.ignoreValue) { r = (*it).getRed(); g = (*it).getGreen(); b = (*it).getBlue(); l = (min(r,g,b)+max(r,g,b))/2; idx = static_cast<int>(r*m); theR.at(idx)++; idx = static_cast<int>(g*m); theG.at(idx)++; idx = static_cast<int>(b*m); theB.at(idx)++; idx = static_cast<int>(l*m); theL.at(idx)++; entries++; } } } } if (param.smooth) { convolution convolver; convolution::parameters cpar; cpar.boundaryType = lti::Mirror; cpar.setKernel(param.kernel); convolver.setParameters(cpar); matrix<double> tmp; tmp.useExternData(4,param.cells,&dest.at(0)); convolver.apply(theR,tmp.getRow(0)); convolver.apply(theG,tmp.getRow(1)); convolver.apply(theB,tmp.getRow(2)); convolver.apply(theL,tmp.getRow(3)); } else { dest.fill(theR,0); dest.fill(theG,param.cells); dest.fill(theB,2*param.cells); dest.fill(theL,3*param.cells); } if (param.normalize) { if (entries > 0) { dest.divide(entries); } } return true; };
// On copy apply for type channel! bool huMoments::apply(const channel& src,dvector& dest, dvector& more) const { channel::value_type val; dest.resize(NUM_FEAT,0,false,true); more.resize(MORE_FEAT,0,false,true); double m00=0.0; double cm11,cm20,cm02,cm30,cm03,cm12,cm21; cm11=cm20=cm02=cm30=cm03=cm12=cm21=0.0; double xcog, ycog; xcog=ycog=0.0; int r, rows=src.rows(); int c, cols=src.columns(); // compute simple moments and cog for (r=0; r<rows; r++) { for (c=0; c<cols; c++) { val = src.at(r,c); m00+=val; xcog+=c*val; ycog+=r*val; } } // end here, if no content if (m00==0) { return false; } // compute cog's more[huMoments::xcog]=xcog=xcog/m00; //xcog more[huMoments::ycog]=ycog=ycog/m00; //ycog // compute central moments for (r=0; r<rows; r++) { for (c=0; c<cols; c++) { val = src.at(r,c); double x_xcog = c-xcog; double y_ycog = r-ycog; cm11+=(x_xcog)*(y_ycog)*val; cm20+=(x_xcog)*(x_xcog)*val; cm02+=(y_ycog)*(y_ycog)*val; cm30+=(x_xcog)*(x_xcog)*(x_xcog)*val; cm03+=(y_ycog)*(y_ycog)*(y_ycog)*val; cm12+=(x_xcog)*(y_ycog)*(y_ycog)*val; cm21+=(x_xcog)*(x_xcog)*(y_ycog)*val; } } double m00pow2,m00pow2_5; m00pow2 = m00*m00; m00pow2_5 = pow(m00,2.5); // normalized central moments cm02 = cm02/m00pow2; cm03 = cm03/m00pow2_5; cm11 = cm11/m00pow2; cm12 = cm12/m00pow2_5; cm20 = cm20/m00pow2; cm21 = cm21/m00pow2_5; cm30 = cm30/m00pow2_5; // calculate moment invariants dest[huMoments::hu1] = cm20 + cm02; dest[huMoments::hu2] = pow((cm20 - cm02),2) + 4*pow(cm11,2); dest[huMoments::hu3] = pow((cm30 - 3*cm12),2) + pow((3*cm21 - cm03),2); dest[huMoments::hu4] = pow((cm30 + cm12),2) + pow((cm21 + cm03),2); dest[huMoments::hu5] = (cm30-3*cm12)*(cm30+cm12)*( pow((cm30+cm12),2) - 3*pow((cm21+cm03),2) ) + (3*cm21-cm03)*(cm21+cm03)*( 3*pow((cm30+cm12),2) - pow((cm21+cm03),2) ); dest[huMoments::hu6] = (cm20-cm02)*( pow((cm30+cm12),2) - pow((cm21+cm03),2) ) + 4*cm11*(cm30+cm12)*(cm21+cm03); dest[huMoments::hu7] = (3*cm21-cm03)*(cm30+cm12)*( pow((cm30+cm12),2) - 3*pow((cm21+cm03),2) ) - (cm30-3*cm12)*(cm21+cm03)*( 3*pow((cm30+cm12),2) - pow((cm21+cm03),2) ); double temp = sqrt( (cm20 - cm02)*(cm20 - cm02) + 4*cm11*cm11 ); more[huMoments::eigen1]=m00*0.5*((cm20+cm02) + temp); //eigen 1 more[huMoments::eigen2]=m00*0.5*((cm20+cm02) - temp); //eigen 2 more[huMoments::orientation]=0.5*atan2(2*cm11, cm20 - cm02); //orientation more[huMoments::m00]=m00; //m00 const parameters& param = getParameters(); if (param.scaling) { int i; for (i=0; i<dest.size();i++){ dest[i]=-logn(dest[i]); } } return true; }