void LapVectorField::compute( std::vector<std::vector<CvPoint>> curves_pix, CvSize imgsize, int res ){ // smooth input curves void getBernsteinCoefficient( std::vector<double> &bc, int n ) ; std::vector<std::vector<double2>> bezierCurves ; for( int cid=0; cid<curves_pix.size(); ++cid ){ std::vector<double2> curve ; for( int i=0; i<curves_pix[cid].size(); ++i) curve.push_back( double2( curves_pix[cid][i].x,curves_pix[cid][i].y ) ) ; int n = curve.size(); std::vector<double> bc ; getBernsteinCoefficient(bc, n ) ; // store the Bezier curve std::vector<double2> bezierCurve ; double step = 1.0 / curves_pix[cid].size(); for( double u=0; u<=1.0; u+=step){ double2 p ; for( int k = 0; k<n; ++k ){ p.x += bc[k] * pow(u, k) * pow( 1-u, n-1-k) * curve[k].x ; p.y += bc[k] * pow(u, k) * pow( 1-u, n-1-k) * curve[k].y ; } bezierCurve.push_back( p ) ; } bezierCurves.push_back( bezierCurve ); } #define _use_bezier 0 if( !_use_bezier ){ for( int cid=0; cid<curves_pix.size(); ++cid ){ std::vector<double2> curve ; for( int i=0; i<curves_pix[cid].size(); ++i) curve.push_back( double2( curves_pix[cid][i].x,curves_pix[cid][i].y ) ) ; bezierCurves[cid] = curve ; } } // store the config resolution = res ; LapVectorField::imgsize = imgsize ; // treat the image as square int majorSide = std::max( imgsize.height, imgsize.width ) ; if(imgsize.height> imgsize.width ){ for( int i=0; i<bezierCurves.size(); ++i ) for( int j=0; j<bezierCurves[i].size(); ++j ) bezierCurves[i][j].x += (imgsize.height - imgsize.width)/2 ; }else{ for( int i=0; i<bezierCurves.size(); ++i ) for( int j=0; j<bezierCurves[i].size(); ++j ) bezierCurves[i][j].y += (-imgsize.height + imgsize.width)/2 ; } std::vector<std::vector<double2>> curves_flt ; for( int i=0; i<bezierCurves.size(); ++i ){ std::vector<double2> cur ; for( int j=0; j<bezierCurves[i].size(); ++j ){ cur.push_back( bezierCurves[i][j] / majorSide ) ; } curves_flt.push_back(cur) ; } // calculate the vector field computeVectorField( vector_field, curves_flt, resolution ) ; }
void DrawAlignedGrid(ShaderState &wss, const View& view, float size, float z) { const double2 roundedCam = double2(round(view.position, size)); const double2 roundedSize = double2(round(0.5f * view.getWorldSize(z), size) + float2(size)); ShaderUColor::instance().DrawGrid(wss, size, double3(roundedCam - roundedSize, z), double3(roundedCam + roundedSize, z)); }
double2 LapVectorField::getVector( CvPoint p ){ int majorSide = std::max( imgsize.height, imgsize.width ) ; if(imgsize.height> imgsize.width ){ p.x += (imgsize.height - imgsize.width )/2 ; }else{ p.y += (imgsize.width - imgsize.height )/2 ; } double2 normPos = double2 ( p.x / (double)majorSide, p.y / (double)majorSide ) ; int x = normPos.x * resolution ; int y= normPos.y * resolution ; int index = y * resolution + x ; index = std::min( index , resolution * resolution - 1 ) ; index = std::max( index, 0 ) ; return vector_field[ index] ; }
AlloyContext::AlloyContext(int width, int height, const std::string& title, const Theme& theme) : nvgContext(nullptr), window(nullptr), theme(theme) { threadId = std::this_thread::get_id(); if (glfwInit() != GL_TRUE) { throw std::runtime_error("Could not initialize GLFW."); } glfwSetErrorCallback( [](int error, const char* desc) { std::cout << "GLFW Error [" << error << "] " << desc << std::endl; }); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1); glfwWindowHint(GLFW_VISIBLE, 0); window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); if (!window) { glfwTerminate(); throw std::runtime_error("Could not create window."); } glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { throw std::runtime_error("Could not initialize GLEW."); } glGetError(); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); viewSize = int2(width, height); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1); glfwWindowHint(GLFW_VISIBLE, 0); offscreenWindow = glfwCreateWindow(width, height, "Offscreen", NULL, NULL); if (!offscreenWindow) { glfwTerminate(); throw std::runtime_error("Could not create window."); } glfwMakeContextCurrent(offscreenWindow); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { throw std::runtime_error("Could not initialize GLEW."); } glGetError(); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, width, height); glfwMakeContextCurrent(window); nvgContext = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES); const float2 TextureCoords[6] = { float2(1.0f, 0.0f), float2(0.0f, 0.0f), float2(0.0f, 1.0f), float2(0.0f, 1.0f), float2(1.0f, 1.0f), float2( 1.0f, 0.0f) }; const float3 PositionCoords[6] = { float3(1.0f, 1.0f, 0.0f), float3(0.0f, 1.0f, 0.0f), float3(0.0f, 0.0f, 0.0f), float3(0.0f, 0.0f, 0.0f), float3(1.0f, 0.0f, 0.0f), float3(1.0f, 1.0f, 0.0f) }; glGenVertexArrays(1, &vaoImageOnScreen.vao); glBindVertexArray(vaoImageOnScreen.vao); glGenBuffers(1, &vaoImageOnScreen.positionBuffer); glBindBuffer(GL_ARRAY_BUFFER, vaoImageOnScreen.positionBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, PositionCoords, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &vaoImageOnScreen.uvBuffer); glBindBuffer(GL_ARRAY_BUFFER, vaoImageOnScreen.uvBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 2 * 6, TextureCoords, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); glfwHideWindow(offscreenWindow); glfwMakeContextCurrent(offscreenWindow); glGenVertexArrays(1, &vaoImageOffScreen.vao); glBindVertexArray(vaoImageOffScreen.vao); glGenBuffers(1, &vaoImageOffScreen.positionBuffer); glBindBuffer(GL_ARRAY_BUFFER, vaoImageOffScreen.positionBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, PositionCoords, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &vaoImageOffScreen.uvBuffer); glBindBuffer(GL_ARRAY_BUFFER, vaoImageOffScreen.uvBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 2 * 6, TextureCoords, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); glfwMakeContextCurrent(window); int widthMM, heightMM; GLFWmonitor* monitor = glfwGetPrimaryMonitor(); if (monitor == nullptr) throw std::runtime_error("Could not find monitor."); const GLFWvidmode* mode = glfwGetVideoMode(monitor); if (mode == nullptr) throw std::runtime_error("Could not find video monitor."); glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM); dpmm = double2(mode->width / (double) widthMM, mode->height / (double) heightMM); int winWidth, winHeight, fbWidth, fbHeight; glfwGetWindowSize(window, &winWidth, &winHeight); glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Calculate pixel ration for hi-dpi devices. screenSize = int2(winWidth,winHeight); viewSize = int2(fbWidth,fbHeight); pixelRatio = pixel((float) fbWidth / (float) winWidth); lastAnimateTime = std::chrono::steady_clock::now(); lastCursorTime = std::chrono::steady_clock::now(); lastUpdateTime = std::chrono::steady_clock::now(); cursor = &Cursor::Normal; }
template<> OCLRASTER_API double2 vector2<double>::operator%(const double2& v) const { return double2(fmod(x, v.x), fmod(y, v.y)); }
void tele2d::runRegister() { std::cout<<"begin registration"<<std::endl; unsigned time1 = clock() ; std::vector<double> x0(curves_group.size() *3, 0); int xn = x0.size() ; nlopt::opt opt(nlopt::LD_LBFGS, xn); std::vector<double> lb(xn); std::vector<double> ub(xn); for( int i=0; i<xn; ++i ){ int innerId = i % 3 ; if( innerId <2 ){ lb[i] = -0.5 ; ub[i] = 0.5; }else{ lb[i] = -1.0 ; ub[i] = 1.0 ; } } opt.set_lower_bounds(lb); opt.set_upper_bounds(ub); opt.set_min_objective( efunc, this ); opt.set_ftol_rel(0.001); double minf ; nlopt::result result ; try{ result = opt.optimize(x0, minf); }catch (std::exception& e){ std::cerr << "exception caught: " << e.what() << '\n'; } std::cout << "result code: " << result <<std::endl; std::vector<double> X = x0; // transform the curves resCurves = curves ; for( int gid =0; gid<curves_group.size(); ++gid ){ std::vector<int> curves_id = curves_group[gid] ; // translation for( int i = 0; i<curves_id.size(); ++i ){ int cvid = curves_id[i] ; for (int j=0; j<resCurves[cvid].size(); ++j){ resCurves[cvid][j].x = resCurves[cvid][j].x + X[gid*3] ; resCurves[cvid][j].y = resCurves[cvid][j].y + X[gid*3+1] ; } } // rotation double2 rotation_center = double2( 0, 0 ) ; int count = 0; for( int i = 0; i<curves_id.size(); ++i ){ int cvid = curves_id[i] ; for( int j=0; j<resCurves[cvid].size(); ++j){ rotation_center = rotation_center + resCurves[cvid][j] ; count ++ ; } } rotation_center = rotation_center * (1.0/count ) ; //std::cout<<"rotation_center = ( "<<rotation_center.x<<","<<rotation_center.y <<")"<<std::endl ; //rotation_center = resCurves[curves_id[0]].back() ; for( int i = 0; i<curves_id.size(); ++i ){ int cvid = curves_id[i] ; for( int j=0; j<resCurves[cvid].size(); ++j){ resCurves[cvid][j].x -= rotation_center.x ; resCurves[cvid][j].y -= rotation_center.y ; double2 temp = resCurves[cvid][j] ; resCurves[cvid][j].x = cos(X[gid*3+2]) * temp.x + sin( X[gid*3+2]) * temp.y ; resCurves[cvid][j].y = -sin(X[gid*3+2]) * temp.x + cos( X[gid*3+2]) * temp.y ; resCurves[cvid][j].x += rotation_center.x ; resCurves[cvid][j].y += rotation_center.y ; } } } std::cout << "registration time = " << (double)(clock()-time1)/CLOCKS_PER_SEC <<" s" <<std::endl ; std::cout<<"end registration"<<std::endl; }
void tele2d::outputResCurves( std::string fname, bool link ){ if( !link ){ // de-normalize resCurves CURVES outcurves ; outcurves.resize( resCurves.size() ) ; for( int i=0; i<resCurves.size(); ++i ){ for( int j=0; j< resCurves[i].size(); ++j ){ double2 p = (resCurves[i][j] - double2(0.5, 0.5 ) )/ normalize_scale + double2(0.5, 0.5 ) - normalize_translate ; outcurves[i].push_back ( p ) ; } } // output registered curves std::ofstream regcurOut ( fname) ; regcurOut << outcurves.size() <<std::endl; for( int i=0; i<outcurves.size(); ++i ){ regcurOut << outcurves[i].size() <<std::endl; for( int j=0; j< outcurves[i].size(); ++j ) regcurOut << outcurves[i][j].x << " " << outcurves[i][j].y <<std::endl; } regcurOut.close() ; std::cout << "curves saved!" ; return ; } // --------------------------- merge curves -------------------------- // build a index list. the index of curves is its index in the "curves" vector // the index of interpolated curves is curves.size() + itsIndex std::vector< std::vector<int> > curveIndexLists(bridging_curves_endpoints.size()) ; for( int i=0; i<bridging_curves_endpoints.size(); ++i ){ curveIndexLists[i].push_back( bridging_curves_endpoints[i].first /2 ) ; curveIndexLists[i].push_back( i + curves.size() ) ; curveIndexLists[i].push_back( bridging_curves_endpoints[i].second /2 ) ; } // merge curveIndexLists bool finished = false ; while( !finished ){ finished = true ; for( int i=0; i<curveIndexLists.size(); ++i) for( int j=0; j<curveIndexLists.size(); ++j){ int Li =curveIndexLists[i].size(); int Lj =curveIndexLists[j].size(); if( Li == 0 || Lj == 0 || i == j) continue ; if( curveIndexLists[i][0] == curveIndexLists[j][0] ){ for( int id =1; id<Lj; ++id ) curveIndexLists[i].insert( curveIndexLists[i].begin(), curveIndexLists[j][id] ) ; curveIndexLists[j].clear() ; finished == false ; }else if(curveIndexLists[i][0] == curveIndexLists[j][Lj-1] ){ for( int id =1; id<Li; ++id ) curveIndexLists[j].push_back( curveIndexLists[i][id]) ; curveIndexLists[i].clear(); finished == false ; }else if( curveIndexLists[i][Li-1] == curveIndexLists[j][0] ){ for( int id =1; id<Lj; ++id ) curveIndexLists[i].push_back( curveIndexLists[j][id]) ; curveIndexLists[j].clear() ; finished == false ; }else if(curveIndexLists[i][Li-1] == curveIndexLists[j][Lj-1] ){ for( int id = Lj-2; id >=0; --id ) curveIndexLists[i].push_back(curveIndexLists[j][id]); curveIndexLists[j].clear(); finished == false ; } } } // delete empty list and delete the last element if the index list is a loop for( int i=0; i<curveIndexLists.size(); ++i){ if( curveIndexLists[i].size() == 0 ){ curveIndexLists.erase( curveIndexLists.begin() + i ) ; --i ; }else { if( curveIndexLists[i].size()>1 && curveIndexLists[i][0] == *(curveIndexLists[i].end()-1) ) curveIndexLists[i].erase( curveIndexLists[i].end()-1) ; } } // // print index List for( int i=0; i<curveIndexLists.size(); ++i){ std::cout<<std::endl; for( int j=0; j<curveIndexLists[i].size(); ++j) std::cout<<" "<<curveIndexLists[i][j] ; } // convert the merged index list to merged curves curves.insert(curves.end(), bridging_curves.begin(), bridging_curves.end() ) ; std::vector<std::vector<double2> > mergedCuves (curveIndexLists.size() ); for( int ILid =0; ILid<curveIndexLists.size() ; ++ILid ){ std::vector<int> indList = curveIndexLists[ILid] ; std::vector<double2> curve; if( std::min( (curves[indList[0]][0] - curves[indList[1]][0]).norm() , ( curves[indList[0]][0] - *(curves[indList[1]].end()-1)).norm() ) < std::min( ( *(curves[indList[0]].end()-1) - curves[indList[1]][0]).norm(), ( *(curves[indList[0]].end()-1) - *(curves[indList[1]].end()-1)).norm() ) ){ for(int i = curves[indList[0]].size()-1; i>=0; --i) curve.push_back(curves[indList[0]][i] ) ; } else curve.insert(curve.end(), curves[indList[0]].begin(),curves[indList[0]].end() ) ; for( int i=1; i<indList.size(); i++ ){ if( (curves[indList[i]][0] - *(curve.end()-1)).norm() < (*(curves[indList[i]].end()-1) - *(curve.end()-1)).norm() ) curve.insert(curve.end(), curves[indList[i]].begin(),curves[indList[i]].end() ) ; else{ inverse(curves[indList[i]] ) ; curve.insert(curve.end(), curves[indList[i]].begin(),curves[indList[i]].end() ) ; } } mergedCuves[ILid] = curve; } // de-normalize merged curves CURVES outcurves ; outcurves.resize( mergedCuves.size() ) ; for( int i=0; i<mergedCuves.size(); ++i ){ for( int j=0; j< mergedCuves[i].size(); ++j ){ double2 p = (mergedCuves[i][j] - double2(0.5, 0.5 ) )/ normalize_scale + double2(0.5, 0.5 ) - normalize_translate ; outcurves[i].push_back ( p ) ; } } // output merged curves std::ofstream megcurOut ( fname ) ; megcurOut << outcurves.size() <<std::endl; for( int i=0; i<outcurves.size(); ++i ){ megcurOut << outcurves[i].size() <<std::endl; for( int j=0; j< outcurves[i].size(); ++j ) megcurOut << outcurves[i][j].x << " " << outcurves[i][j].y <<std::endl; } megcurOut.close() ; std::cout << "curves saved!" ; }