void colorize(const Image<uint32_t> &input, const Image<uint32_t> &strokes, Image<uint32_t> &output) { int w = input.width(); int h = input.height(); int x,y; int max_d = floor(log(min(h,w))/log(2)-2); float scale_factor = 1.0f/( pow(2,max_d-1) ); int padded_w = ceil(w*scale_factor)*pow(2,max_d-1); int padded_h = ceil(h*scale_factor)*pow(2,max_d-1); // RGB 2 YUV and padarray Image<float> yuv_fused(padded_w,padded_h,3); hl_fuse_yuv(input, strokes, yuv_fused); // Extract Strokes mask Image<float> stroke_mask(padded_w, padded_h); hl_nonzero(strokes,stroke_mask); Image<float> result(padded_w,padded_h,3); int n = padded_h; int m = padded_w; int k = 1; Tensor3d D,G,I; Tensor3d Dx,Dy,iDx,iDy; MG smk; G.set(n,m,k); D.set(n,m,k); I.set(n,m,k); int in_itr_num = 5; int out_itr_num = 1; Dx.set(n,m,k-1); Dy.set(n,m,k-1); iDx.set(n,m,k-1); iDy.set(n,m,k-1); // Fill in label mask and luminance channels for ( y = 0; y<n; y++){ for ( x = 0; x<m; x++){ I(y,x,0) = stroke_mask(x,y); G(y,x,0) = yuv_fused(x,y,0); I(y,x,0) = !I(y,x,0); } } // Write output luminance for ( y=0; y<n; y++){ for ( x=0; x<m; x++){ result(x,y,0)=G(y,x,0); } } smk.set(n,m,k,max_d); smk.setI(I) ; smk.setG(G); smk.setFlow(Dx,Dy,iDx,iDy); // Solve chrominance for (int t=1; t<3; t++){ for ( y=0; y<n; y++){ for ( x=0; x<m; x++){ D(y,x,0) = yuv_fused(x,y,t); smk.P()(y,x,0) = yuv_fused(x,y,t); D(y,x,0) *= (!I(y,x,0)); } } smk.Div() = D ; Tensor3d tP2; for (int itr=0; itr<out_itr_num; itr++){ smk.setDepth(max_d); Field_MGN(&smk, in_itr_num, 2) ; smk.setDepth(ceil(max_d/2)); Field_MGN(&smk, in_itr_num, 2) ; smk.setDepth(2); Field_MGN(&smk, in_itr_num, 2) ; smk.setDepth(1); Field_MGN(&smk, in_itr_num, 4) ; } tP2 = smk.P(); for ( y=0; y<n; y++){ for ( x=0; x<m; x++){ result(x,y,t) = tP2(y,x,0); } } } hl_yuv2rgb(result,output); }
int main(int argc, char * argv[]) { string mesh_path; string samples_path; string out_path; int curr_opt = 0; for (int i = 1; i < argc; ++i) { string arg = argv[i]; if (!beginsWith(arg, "-")) { switch (curr_opt) { case 0: mesh_path = arg; break; case 1: samples_path = arg; break; case 2: out_path = arg; break; } curr_opt++; if (curr_opt > 3) break; } else { if (beginsWith(arg, "--max-nbrs=")) { if (sscanf(arg.c_str(), "--max-nbrs=%d", &max_nbrs) != 1 || max_nbrs <= 0) { THEA_ERROR << "Invalid --max-nbrs parameter"; return -1; } } else if (beginsWith(arg, "--min-samples=")) { if (sscanf(arg.c_str(), "--min-samples=%ld", &min_samples) != 1 || min_samples <= 0) { THEA_ERROR << "Invalid --min-samples parameter"; return -1; } } else if (arg == "-n" || arg == "--normals") { consistent_normals = true; } else if (arg == "-r" || arg == "--reachability") { reachability = true; } else { THEA_ERROR << "Unknown parameter: " << arg; return -1; } } } if (curr_opt != 3) { THEA_CONSOLE << ""; THEA_CONSOLE << "Usage: " << argv[0] << " [OPTIONS] <mesh|dense-points> <points> <graph-outfile>"; THEA_CONSOLE << ""; THEA_CONSOLE << "Options:"; THEA_CONSOLE << " --max-nbrs=N Maximum degree of proximity graph"; THEA_CONSOLE << " --min-samples=N Minimum number of original plus generated samples"; THEA_CONSOLE << " --normals | -n Run extra tests assuming consistently oriented mesh normals"; THEA_CONSOLE << " --reachability | -r Reachability test for adjacency (requires -n)"; THEA_CONSOLE << ""; return -1; } if (reachability && !consistent_normals) { THEA_ERROR << "Reachability test requires consistent normals"; return -1; } //=========================================================================================================================== // Load points //=========================================================================================================================== TheaArray<Vector3> sample_positions; TheaArray<Vector3> sample_normals; if (loadSamples(samples_path, sample_positions, sample_normals)) return -1; bool has_normals = (!sample_positions.empty() && sample_normals.size() == sample_positions.size()); THEA_CONSOLE << "Loaded " << sample_positions.size() << " sample(s) from " << samples_path; //=========================================================================================================================== // Load mesh or dense samples //=========================================================================================================================== TheaArray<Vector3> dense_positions; TheaArray<Vector3> dense_normals; bool dense_has_normals = false; KDTree kdtree; if (mesh_path != "-") { // First try to load the file as a set of points int dense_load_status = loadSamples(mesh_path, dense_positions, dense_normals); dense_has_normals = (!dense_positions.empty() && dense_normals.size() == dense_positions.size()); if (dense_load_status != 0 && dense_load_status != UNSUPPORTED_FORMAT) { return -1; } else if (dense_load_status == 0) { THEA_CONSOLE << dense_positions.size() << " extra samples added from: " << mesh_path; } else // Now try to load the file as a mesh, if the above failed { MG mg; try { mg.load(mesh_path); } THEA_STANDARD_CATCH_BLOCKS(return -1;, ERROR, "Could not load mesh %s", mesh_path.c_str()) THEA_CONSOLE << "Loaded mesh from " << mesh_path; // Make sure the mesh is properly scaled AxisAlignedBox3 mesh_bounds = mg.getBounds(); AxisAlignedBox3 samples_bounds; for (array_size_t i = 0; i < sample_positions.size(); ++i) samples_bounds.merge(sample_positions[i]); Real scale_error = (mesh_bounds.getLow() - samples_bounds.getLow()).length() + (mesh_bounds.getHigh() - samples_bounds.getHigh()).length(); if (scale_error > 0.01 * mesh_bounds.getExtent().length()) { // Rescale the mesh Real scale = (samples_bounds.getExtent() / mesh_bounds.getExtent()).max(); // samples give a smaller bound than the // true bound, so take the axis in which // the approximation is best AffineTransform3 tr = AffineTransform3::translation(samples_bounds.getCenter()) * AffineTransform3::scaling(scale) * AffineTransform3::translation(-mesh_bounds.getCenter()); MeshTransformer func(tr); mg.forEachMeshUntil(&func); mg.updateBounds(); THEA_CONSOLE << "Matched scale of source mesh and original samples"; } kdtree.add(mg); kdtree.init(); // If the samples have no normals, compute them if (consistent_normals && !has_normals) { sample_normals.resize(sample_positions.size()); for (array_size_t i = 0; i < sample_positions.size(); ++i) { long elem = kdtree.closestElement<MetricL2>(sample_positions[i]); if (elem < 0) { THEA_ERROR << "Could not find nearest neighbor of sample " << i << " on mesh"; return false; } sample_normals[i] = kdtree.getElements()[(array_size_t)elem].getNormal(); } has_normals = true; THEA_CONSOLE << "Computed sample normals"; } // Augment the number of samples if necessary if ((long)sample_positions.size() < min_samples) { dense_positions.clear(); dense_normals.clear(); MeshSampler<Mesh> sampler(mg); sampler.sampleEvenlyByArea((long)(min_samples - sample_positions.size()), dense_positions, (consistent_normals ? &dense_normals : NULL)); if (!dense_positions.empty()) THEA_CONSOLE << dense_positions.size() << " extra samples added to original set, for density"; dense_has_normals = (!dense_positions.empty() && dense_normals.size() == dense_positions.size()); } }
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[]){ int winSize=int(mxGetScalar(prhs[2])+0.5); int deg=int(mxGetScalar(prhs[3])+0.5); const int* sizes; sizes=mxGetDimensions(prhs[1]); int sizel; sizel=mxGetNumberOfDimensions(prhs[1]); int n=sizes[1]; int m=sizes[0]; int k,max_d, max_d1,max_d2, in_itr_num, out_itr_num, itr; int x,y,z; if (sizel>3){ k=sizes[3]; }else{ k=1; } max_d1=int(floor(log(n)/log(2)-2)+0.1); max_d2=int(floor(log(m)/log(2)-2)+0.1); if (max_d1>max_d2){ max_d=max_d2; }else{ max_d=max_d1; } double *lblImg_pr, *img_pr; double * res_pr; double **res_prv; double *dx_pr,*dy_pr,*idx_pr,*idy_pr; lblImg_pr=mxGetPr(prhs[0]); img_pr=mxGetPr(prhs[1]); Tensor3d D,G,I; Tensor3d Dx,Dy,iDx,iDy; MG smk; G.set(m,n,k); D.set(m,n,k); I.set(m,n,k); dy_pr=mxGetPr(prhs[2]); dx_pr=mxGetPr(prhs[3]); idy_pr=mxGetPr(prhs[4]); idx_pr=mxGetPr(prhs[5]); if (nrhs>6){ in_itr_num=int(mxGetScalar(prhs[6])+0.5); }else{ in_itr_num=5; } if (nrhs>7){ out_itr_num=int(mxGetScalar(prhs[7])+0.5); }else{ out_itr_num=2; } Dx.set(m,n,k-1); Dy.set(m,n,k-1); iDx.set(m,n,k-1); iDy.set(m,n,k-1); for ( z=0; z<(k-1); z++){ for ( y=0; y<n; y++){ for ( x=0; x<m; x++){ Dx(x,y,z)=*dx_pr; dx_pr++; Dy(x,y,z)=*dy_pr; dy_pr++; iDx(x,y,z)=*idx_pr; idx_pr++; iDy(x,y,z)=*idy_pr; idy_pr++; } } } int dims[4]; dims[0]=m; dims[1]=n; dims[2]=3; dims[3]=k; plhs[0]=mxCreateNumericArray(4,dims, mxDOUBLE_CLASS ,mxREAL); res_pr=mxGetPr(plhs[0]); res_prv=new double*[k]; for (z=0; z<k; z++){ res_prv[z]=res_pr+n*m*3*z; } for ( z=0; z<k; z++){ for ( y=0; y<n; y++){ for ( x=0; x<m; x++){ I(x,y,z)=lblImg_pr[x+m*y+z*n*m]; G(x,y,z)=img_pr[x+y*m+z*m*n*3]; I(x,y,z)=!I(x,y,z); } } } for ( z=0; z<k; z++){ for ( y=0; y<n; y++){ for ( x=0; x<m; x++){ (*res_prv[z])=G(x,y,z); res_prv[z]++; } } } smk.set(m,n,k,max_d); smk.setI(I) ; smk.setG(G); smk.setFlow(Dx,Dy,iDx,iDy); for (int t=1; t<3; t++){ for ( z=0; z<k; z++){ for ( y=0; y<n; y++){ for ( x=0; x<m; x++){ D(x,y,z)=img_pr[x+y*m+n*m*t+z*m*n*3]; smk.P()(x,y,z)=img_pr[x+y*m+n*m*t+z*m*n*3]; D(x,y,z)*=(!I(x,y,z)); } } } smk.Div() = D ; Tensor3d tP2; if (k==1){ for (itr=0; itr<out_itr_num; itr++){ smk.setDepth(max_d); Field_MGN(&smk, in_itr_num, 2) ; smk.setDepth(ceil(max_d/2)); Field_MGN(&smk, in_itr_num, 2) ; smk.setDepth(2); Field_MGN(&smk, in_itr_num, 2) ; smk.setDepth(1); Field_MGN(&smk, in_itr_num, 4) ; } } else{ for (itr=0; itr<out_itr_num; itr++){ smk.setDepth(2); Field_MGN(&smk, in_itr_num, 2) ; smk.setDepth(1); Field_MGN(&smk, in_itr_num, 4) ; } } tP2=smk.P(); for ( z=0; z<k; z++){ for ( y=0; y<n; y++){ for ( x=0; x<m; x++){ (*res_prv[z])=tP2(x,y,z); res_prv[z]++; } } } } }