void MapperGradSimilar::calculate( const cv::Mat& img1, const cv::Mat& image2, cv::Ptr<Map>& res) const { Mat gradx, grady, imgDiff; Mat img2; CV_DbgAssert(img1.size() == image2.size()); CV_DbgAssert(img1.channels() == image2.channels()); CV_DbgAssert(img1.channels() == 1 || img1.channels() == 3); if(!res.empty()) { // We have initial values for the registration: we move img2 to that initial reference res->inverseWarp(image2, img2); } else { img2 = image2; } // Get gradient in all channels gradient(img1, img2, gradx, grady, imgDiff); // Matrices with reference frame coordinates Mat grid_r, grid_c; grid(img1, grid_r, grid_c); // Calculate parameters using least squares Matx<double, 4, 4> A; Vec<double, 4> b; // For each value in A, all the matrix elements are added and then the channels are also added, // so we have two calls to "sum". The result can be found in the first element of the final // Scalar object. Mat xIx_p_yIy = grid_c.mul(gradx); xIx_p_yIy += grid_r.mul(grady); Mat yIx_m_xIy = grid_r.mul(gradx); yIx_m_xIy -= grid_c.mul(grady); A(0, 0) = sum(sum(sqr(xIx_p_yIy)))[0]; A(0, 1) = sum(sum(xIx_p_yIy.mul(yIx_m_xIy)))[0]; A(0, 2) = sum(sum(gradx.mul(xIx_p_yIy)))[0]; A(0, 3) = sum(sum(grady.mul(xIx_p_yIy)))[0]; A(1, 1) = sum(sum(sqr(yIx_m_xIy)))[0]; A(1, 2) = sum(sum(gradx.mul(yIx_m_xIy)))[0]; A(1, 3) = sum(sum(grady.mul(yIx_m_xIy)))[0]; A(2, 2) = sum(sum(sqr(gradx)))[0]; A(2, 3) = sum(sum(gradx.mul(grady)))[0]; A(3, 3) = sum(sum(sqr(grady)))[0]; // Lower half values (A is symmetric) A(1, 0) = A(0, 1); A(2, 0) = A(0, 2); A(3, 0) = A(0, 3); A(2, 1) = A(1, 2); A(3, 1) = A(1, 3); A(3, 2) = A(2, 3); // Calculation of b b(0) = -sum(sum(imgDiff.mul(xIx_p_yIy)))[0]; b(1) = -sum(sum(imgDiff.mul(yIx_m_xIy)))[0]; b(2) = -sum(sum(imgDiff.mul(gradx)))[0]; b(3) = -sum(sum(imgDiff.mul(grady)))[0]; // Calculate affine transformation. We use Cholesky decomposition, as A is symmetric. Vec<double, 4> k = A.inv(DECOMP_CHOLESKY)*b; Matx<double, 2, 2> linTr(k(0) + 1., k(1), -k(1), k(0) + 1.); Vec<double, 2> shift(k(2), k(3)); if(res.empty()) { res = Ptr<Map>(new MapAffine(linTr, shift)); } else { MapAffine newTr(linTr, shift); res->compose(newTr); } }
static inline void* cvAlignPtr( const void* ptr, int align = 32 ) { CV_DbgAssert ( (align & (align-1)) == 0 ); return (void*)( ((size_t)ptr + align - 1) & ~(size_t)(align-1) ); }
static inline int cvAlign( int size, int align ) { CV_DbgAssert( (align & (align-1)) == 0 && size < INT_MAX ); return (size + align - 1) & -align; }
template<typename _Tp> inline const _Tp *oclMat::ptr(int y) const { CV_DbgAssert( (unsigned)y < (unsigned)rows ); CV_Error(CV_GpuNotSupported, "This function hasn't been supported yet.\n"); return (const _Tp *)(data + step * y); }
/*! Aligns buffer size by the certain number of bytes This small inline function aligns a buffer size by the certian number of bytes by enlarging it. */ static inline size_t alignSize(size_t sz, int n) { CV_DbgAssert((n & (n - 1)) == 0); // n is a power of 2 return (sz + n-1) & -n; }
inline const uchar* GpuMat::ptr(int y) const { CV_DbgAssert( (unsigned)y < (unsigned)rows ); return data + step * y; }
inline const uchar *oclMat::ptr(int y) const { CV_DbgAssert( (unsigned)y < (unsigned)rows ); CV_Error(CV_GpuNotSupported, "This function hasn't been supported yet.\n"); return data + step * y; }
Vec2d computeProbabilities(const Mat& sample, Mat* probs, int ptype) const { // L_ik = log(weight_k) - 0.5 * log(|det(cov_k)|) - 0.5 *(x_i - mean_k)' cov_k^(-1) (x_i - mean_k)] // q = arg(max_k(L_ik)) // probs_ik = exp(L_ik - L_iq) / (1 + sum_j!=q (exp(L_ij - L_iq)) // see Alex Smola's blog http://blog.smola.org/page/2 for // details on the log-sum-exp trick int stype = sample.type(); CV_Assert(!means.empty()); CV_Assert((stype == CV_32F || stype == CV_64F) && (ptype == CV_32F || ptype == CV_64F)); CV_Assert(sample.size() == Size(means.cols, 1)); int dim = sample.cols; Mat L(1, nclusters, CV_64FC1), centeredSample(1, dim, CV_64F); int i, label = 0; for(int clusterIndex = 0; clusterIndex < nclusters; clusterIndex++) { const double* mptr = means.ptr<double>(clusterIndex); double* dptr = centeredSample.ptr<double>(); if( stype == CV_32F ) { const float* sptr = sample.ptr<float>(); for( i = 0; i < dim; i++ ) dptr[i] = sptr[i] - mptr[i]; } else { const double* sptr = sample.ptr<double>(); for( i = 0; i < dim; i++ ) dptr[i] = sptr[i] - mptr[i]; } Mat rotatedCenteredSample = covMatType != COV_MAT_GENERIC ? centeredSample : centeredSample * covsRotateMats[clusterIndex]; double Lval = 0; for(int di = 0; di < dim; di++) { double w = invCovsEigenValues[clusterIndex].at<double>(covMatType != COV_MAT_SPHERICAL ? di : 0); double val = rotatedCenteredSample.at<double>(di); Lval += w * val * val; } CV_DbgAssert(!logWeightDivDet.empty()); L.at<double>(clusterIndex) = logWeightDivDet.at<double>(clusterIndex) - 0.5 * Lval; if(L.at<double>(clusterIndex) > L.at<double>(label)) label = clusterIndex; } double maxLVal = L.at<double>(label); double expDiffSum = 0; for( i = 0; i < L.cols; i++ ) { double v = std::exp(L.at<double>(i) - maxLVal); L.at<double>(i) = v; expDiffSum += v; // sum_j(exp(L_ij - L_iq)) } if(probs) L.convertTo(*probs, ptype, 1./expDiffSum); Vec2d res; res[0] = std::log(expDiffSum) + maxLVal - 0.5 * dim * CV_LOG2PI; res[1] = label; return res; }
void LBSP::setReference(const cv::Mat& img) { CV_DbgAssert(img.empty() || img.type()==CV_8UC1 || img.type()==CV_8UC3); m_oRefImage = img; }
cl_program getOrBuildProgram(const Context* ctx, const cv::ocl::ProgramEntry* source, const String& options) { cl_int status = 0; cl_program program = NULL; std::vector<char> binary; if (!enable_disk_cache || !readConfigurationFromFile(options, binary)) { program = clCreateProgramWithSource(getClContext(ctx), 1, (const char**)&source->programStr, NULL, &status); openCLVerifyCall(status); cl_device_id device = getClDeviceID(ctx); status = clBuildProgram(program, 1, &device, options.c_str(), NULL, NULL); if(status == CL_SUCCESS) { if (enable_disk_cache) { size_t binarySize; openCLSafeCall(clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, NULL)); std::vector<char> binary(binarySize); char* ptr = &binary[0]; openCLSafeCall(clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(char*), &ptr, NULL)); if (!writeConfigurationToFile(options, binary)) { std::cerr << "Can't write data to file: " << fileName_ << std::endl; } } } } else { cl_device_id device = getClDeviceID(ctx); size_t size = binary.size(); const char* ptr = &binary[0]; program = clCreateProgramWithBinary(getClContext(ctx), 1, &device, (const size_t *)&size, (const unsigned char **)&ptr, NULL, &status); openCLVerifyCall(status); status = clBuildProgram(program, 1, &device, options.c_str(), NULL, NULL); } if(status != CL_SUCCESS) { if(status == CL_BUILD_PROGRAM_FAILURE) { cl_int logStatus; char *buildLog = NULL; size_t buildLogSize = 0; logStatus = clGetProgramBuildInfo(program, getClDeviceID(ctx), CL_PROGRAM_BUILD_LOG, buildLogSize, buildLog, &buildLogSize); if(logStatus != CL_SUCCESS) std::cout << "Failed to build the program and get the build info." << std::endl; buildLog = new char[buildLogSize]; CV_DbgAssert(!!buildLog); memset(buildLog, 0, buildLogSize); openCLSafeCall(clGetProgramBuildInfo(program, getClDeviceID(ctx), CL_PROGRAM_BUILD_LOG, buildLogSize, buildLog, NULL)); std::cout << "\nBUILD LOG: " << options << "\n"; std::cout << buildLog << std::endl; delete [] buildLog; } openCLVerifyCall(status); } return program; }
// calc the sum of an area inline bool calcAreaMean(const cv::Mat &src, cv::Point currpos, cv::Size blockSize, const cv::Mat &sum=cv::Mat(), double *mean=NULL, const cv::Mat &sqsum=cv::Mat(), double *sd=NULL){ ////////////////////////////////////////////////////////////////////////// ///// exceptions if(blockSize.width%2==0||blockSize.height%2==0){ CV_Error(CV_StsBadArg,"[calcAreaMean] either block's height or width is 0."); } ////////////////////////////////////////////////////////////////////////// ///// initialization int SSFilterSize_h = blockSize.height/2; // SSFilterSize: Single Side Filter Size int SSFilterSize_w = blockSize.width/2; // SSFilterSize: Single Side Filter Size const int &height = src.rows; const int &width = src.cols; const int &i = currpos.y; const int &j = currpos.x; ////////////////////////////////////////////////////////////////////////// bool A=true, // bottom, top, left, right; thus br: bottom-right B=true, C=true, D=true; if((i+SSFilterSize_h)>=height){ A=false; } if((j+SSFilterSize_w)>=width){ B=false; } if((i-SSFilterSize_h-1)<0){ C=false; } if((j-SSFilterSize_w-1)<0){ D=false; } ////////////////////////////////////////////////////////////////////////// ok ///// get area size // width double areaWidth = blockSize.width, areaHeight = blockSize.height; if(!D){ areaWidth = j+SSFilterSize_w+1; }else if(!B){ areaWidth = width-j+SSFilterSize_w; } // height if(!C){ areaHeight = i+SSFilterSize_h+1; }else if(!A){ areaHeight = height-i+SSFilterSize_h; } ////////////////////////////////////////////////////////////////////////// ///// get value // get positions int y_up = i+SSFilterSize_h +1, // '+1' is the bias term of the integral image y_dn = i-SSFilterSize_h-1 +1; if(!A){ y_up = height-1 +1; } int x_left = j-SSFilterSize_w-1 +1, x_right = j+SSFilterSize_w +1; if(!B){ x_right = width-1 +1; } // get values double cTR_sum=0,cTR_sqsum=0, cTL_sum=0,cTL_sqsum=0, cBR_sum=0,cBR_sqsum=0, cBL_sum=0,cBL_sqsum=0; cTR_sum = sum.ptr<double>(y_up)[x_right]; cTR_sqsum = sqsum.ptr<double>(y_up)[x_right]; if(C&&D){ cBL_sum = sum.ptr<double>(y_dn)[x_left]; cBL_sqsum = sqsum.ptr<double>(y_dn)[x_left]; } if(D){ cTL_sum = -sum.ptr<double>(y_up)[x_left]; cTL_sqsum = -sqsum.ptr<double>(y_up)[x_left]; } if(C){ cBR_sum = -sum.ptr<double>(y_dn)[x_right]; cBR_sqsum = -sqsum.ptr<double>(y_dn)[x_right]; } ////////////////////////////////////////////////////////////////////////// ok ///// get mean and sd *mean =cTR_sum +cTL_sum +cBR_sum +cBL_sum; *mean /=areaHeight*areaWidth; CV_DbgAssert((*mean)>=0.&&(*mean)<=255.); *sd =cTR_sqsum +cTL_sqsum +cBR_sqsum +cBL_sqsum; *sd /=areaHeight*areaWidth; // compensate error if(fabs((*sd)-(*mean)*(*mean))<0.00001){ *sd=0; }else{ CV_DbgAssert((*sd)>=(*mean)*(*mean)); *sd =sqrt(*sd-(*mean)*(*mean)); } CV_DbgAssert((*sd)>=0.&&(*sd)<=255.); return true; }
bool pixkit::enhancement::local::POHE2013(const cv::Mat &src,cv::Mat &dst,const cv::Size blockSize,const cv::Mat &sum,const cv::Mat &sqsum){ ////////////////////////////////////////////////////////////////////////// ///// Exceptions // blockSize if(blockSize.height>=src.rows || blockSize.width>=src.cols){ CV_Error(CV_StsBadArg,"[pixkit::enhancement::local::POHE2013] block size should be smaller than image size. "); } if(blockSize.height%2==0 || blockSize.width%2==0){ CV_Error(CV_StsBadArg,"[pixkit::enhancement::local::POHE2013] both block's width and height should be odd."); } if(blockSize.height==1&&blockSize.width==1){ CV_Error(CV_StsBadArg,"[pixkit::enhancement::local::POHE2013] blockSize=(1,1) will turn entire image to dead white."); } // src if(src.type()!=CV_8UC1&&src.type()!=CV_8UC3&&src.type()!=CV_32FC1){ CV_Error(CV_StsBadArg,"[pixkit::enhancement::local::POHE2013] src should be one of CV_8UC1, CV_8UC3, and CV_32FC1."); } // sum and sqsum if(!sum.empty()){ if(sum.type()!=CV_64FC1){ CV_Error(CV_StsBadArg,"[pixkit::enhancement::local::POHE2013] both sum and sqsum should be CV_64FC1"); } } if(!sqsum.empty()){ if(sqsum.type()!=CV_64FC1){ CV_Error(CV_StsBadArg,"[pixkit::enhancement::local::POHE2013] both sum and sqsum should be CV_64FC1"); } } ////////////////////////////////////////////////////////////////////////// ///// color image cv::Mat _src1x,_src3x; if(src.channels()==1){ _src1x=src; }else if(src.channels()==3){ // create space for _src1x if(src.type()==CV_8UC3){ _src1x.create(src.size(),CV_8UC1); }else if(src.type()==CV_32FC3){ _src1x.create(src.size(),CV_32FC1); }else{ CV_Assert(false); } // convert color cvtColor(src,_src3x,CV_BGR2Lab); int from_to[]={0,0}; mixChannels(&_src3x,1,&_src1x,1,from_to,1); }else{ CV_Error(CV_StsUnsupportedFormat,"[pixkit::enhancement::local::POHE2013] images should be grayscale or color."); } ////////////////////////////////////////////////////////////////////////// // initialization cv::Mat tdst; // temp dst. To avoid that when src == dst occur. tdst.create(_src1x.size(),_src1x.type()); const int &height=_src1x.rows; const int &width=_src1x.cols; ////////////////////////////////////////////////////////////////////////// ///// create integral images cv::Mat tsum,tsqsum; if(sum.empty()||sqsum.empty()){ cv::integral(_src1x,tsum,tsqsum,CV_64F); }else{ tsum = sum; tsqsum = sqsum; } ////////////////////////////////////////////////////////////////////////// ///// process for(int i=0;i<height;i++){ for(int j=0;j<width;j++){ ////////////////////////////////////////////////////////////////////////// ///// get mean and sd double mean,sd; calcAreaMean(_src1x,cv::Point(j,i),blockSize,tsum,&mean,tsqsum,&sd); ////////////////////////////////////////////////////////////////////////// // get current src value double current_src_value=0.; if(_src1x.type()==CV_8UC1){ current_src_value = _src1x.ptr<uchar>(i)[j]; }else if(_src1x.type()==CV_32FC1){ current_src_value = _src1x.ptr<float>(i)[j]; }else{ assert(false); } ////////////////////////////////////////////////////////////////////////// // calc Gaussian's cdf double cdf = calcCDF_Gaussian(current_src_value,mean,sd); ////////////////////////////////////////////////////////////////////////// // get output if(tdst.type()==CV_8UC1){ if(current_src_value >= mean-1.885*sd){ tdst.data[i*width+j] = cvRound(cdf*255.); }else{ tdst.data[i*width+j] = 0; } CV_DbgAssert(((uchar*)tdst.data)[i*width+j]>=0.&&((uchar*)tdst.data)[i*width+j]<=255.); }else if(tdst.type()==CV_32FC1){ if(current_src_value >= mean-1.885*sd){ ((float*)tdst.data)[i*width+j] = cvRound(cdf*255.); }else{ ((float*)tdst.data)[i*width+j] = 0; } CV_DbgAssert(((float*)tdst.data)[i*width+j]>=0.&&((float*)tdst.data)[i*width+j]<=255.); }else{ CV_Assert(false); } } } ////////////////////////////////////////////////////////////////////////// ///// copy to dst if(src.channels()==1){ dst = tdst.clone(); }else if(src.channels()==3){ int from_to[]={0,0}; mixChannels(&tdst,1,&_src3x,1,from_to,1); cvtColor(_src3x,dst,CV_Lab2BGR); }else{ CV_Error(CV_StsUnsupportedFormat,"[pixkit::enhancement::local::POHE2013] images should be grayscale or color."); } return true; }