void CANNY::apply_canny() { int *dest_1d,**tmp_2d,**p_2d,**q_2d,**m_2d,**nms,**delta,**tracked,*tmp2_1d; double **theta_2d; int i,j; int result; //int tmp = 0; unsigned char **aux; d_w = height; d_h = width; for(i=0;i<height;i++){ for(j=0;j<width;j++){ im_lineas[i][j]=0xff000000; } } aux=new unsigned char* [d_w]; dest_1d= new int[d_h*d_w]; tmp2_1d=new int [d_h*d_w]; tmp_2d=new int* [d_w]; p_2d=new int* [d_w]; q_2d=new int* [d_w]; m_2d=new int* [d_w]; theta_2d=new double* [d_w]; nms=new int* [d_w]; delta=new int* [d_w]; tracked=new int* [d_w]; for(i=0;i<d_w;i++){ aux[i]=new unsigned char[d_h]; tmp_2d[i]=new int[d_h]; p_2d[i]=new int[d_h]; q_2d[i]=new int[d_h]; m_2d[i]=new int[d_h]; theta_2d[i]=new double[d_h]; nms[i]=new int[d_h]; delta[i]=new int[d_h]; tracked[i]=new int[d_h]; } //Smooth the initial image cout<<tmp_2d<<" "<<height<<" "<<width<<" "<<kernel_size<<" "<<theta<<endl; SmoothImage(im_entrada,tmp_2d,height, width, kernel_size, theta); //Mask off so that we work with values between 0 and 255 for(i=0;i<height;i++){ for(j=0;j<width;j++){ tmp_2d[i][j]=tmp_2d[i][j]&0x000000ff; } } //Apply the gradient detection for(i = 0; i < (d_w-1); i++){ for(j = 0; j < (d_h-1); j++){ p_2d[i][j] = (tmp_2d[i][j+1]-tmp_2d[i][j]+ tmp_2d[i+1][j+1]-tmp_2d[i+1][j])/2; q_2d[i][j] = (tmp_2d[i][j]-tmp_2d[i+1][j]+ tmp_2d[i][j+1]-tmp_2d[i+1][j+1])/2; m_2d[i][j] = (int)sqrt(pow((double)p_2d[i][j],2)+ pow((double)q_2d[i][j],2)); if((q_2d[i][j]==0)&&(p_2d[i][j]==0)){ theta_2d[i][j]=0; }else{ theta_2d[i][j] =atan2((double)(q_2d[i][j]),(double)(p_2d[i][j])); } } } //Resize image d_w--; d_h--; //Apply the nonmaxima suppression //First calculate which sector each line appears in for( i = 0; i < d_w; i++){ for( j = 0; j < d_h; j++){ delta[i][j] = sector(theta_2d[i][j]); } } //Then apply non maximal suppression for( i = 0; i < (d_w-1); i++){ nms[i][0] = 0; nms[i][d_h-1] = 0; } for( j = 0; j < (d_h-1); j++){ nms[0][j] = 0; nms[d_w-1][j] = 0; } for( i = 1; i < (d_w-1); i++){ for( j = 1; j < (d_h-1); j++){ nms[i][j] = suppress(m_2d, delta[i][j], i, j,lowthresh); } } //Resize again! d_w = d_w - 2; d_h = d_h - 2; //Track the image apply_track(nms,tracked, d_w, d_h, lowthresh, highthresh); //Calculate the output array for( i = 0; i < d_w; i++){ for( j = 0; j < d_h; j++){ result = tracked[i][j]; //if(result!=0)ShowMessage("Aki"); result = (int) (result * scale); if(result>0){ result = result + offset; } if(result > 255){result = 255;} if(result < 0){result = 0;} im_lineas[i][j] =0xff000000|result; } } //Change the sizes back d_w = d_w + 3; d_h = d_h + 3; for(i=0;i<d_w;i++){ delete(aux[i]); delete(tmp_2d[i]); delete(p_2d[i]); delete(q_2d[i]); delete(m_2d[i]); delete(theta_2d[i]); delete(nms[i]); delete(delta[i]); delete(tracked[i]); } delete(aux); delete(tmp_2d); delete(p_2d); delete(q_2d); delete(m_2d); delete(theta_2d); delete(nms); delete(delta); delete(tracked); delete(dest_1d); delete(tmp2_1d); }
cHeightmapData::cHeightmapData(const opengl::string_t& sFilename) { voodoo::cImage image; if (!image.LoadFromFile(sFilename)) { std::cout<<"cHeightmapData::cHeightmapData Could not load "<<opengl::string::ToUTF8(sFilename)<<std::endl; assert(false); } width = image.GetWidth(); depth = image.GetHeight(); // Create heightmap data const size_t n = width * depth; heightmap.resize(n, 0); const uint8_t* pPixels = image.GetPointerToBuffer(); for (size_t y = 0; y < depth; y++) { for (size_t x = 0; x < width; x++) { heightmap[(y * width) + x] = float(pPixels[(y * width) + x]) / 255.0f; } } // Calculate shadowmap texture std::vector<spitfire::math::cColour> _lightmap; _lightmap.resize(n, spitfire::math::cColour()); // I find that an exagerated z scale gives a better, more obvious result const float fScaleZ = 100.0f; const spitfire::math::cColour ambientColour(1.0f, 1.0f, 1.0f); const spitfire::math::cColour shadowColour = 0.5f * ambientColour; int size = width; const spitfire::math::cVec3 sunPosition(50.0f, 100.0f, 100.0f); GenerateLightmap(heightmap, _lightmap, fScaleZ, ambientColour, shadowColour, size, sunPosition); widthLightmap = width; depthLightmap = depth; #if 0 // For debugging { const size_t nLightmap = widthLightmap * depthLightmap; // Copy the lightmap from the cColour vector to the uint8_t vector lightmap.resize(nLightmap * 4, 0); for (size_t y = 0; y < depthLightmap; y++) { for (size_t x = 0; x < widthLightmap; x++) { const size_t src = (y * widthLightmap) + x; const size_t dst = 4 * ((y * widthLightmap) + x); lightmap[dst + 0] = uint8_t(_lightmap[src].r * 255.0f); lightmap[dst + 1] = uint8_t(_lightmap[src].g * 255.0f); lightmap[dst + 2] = uint8_t(_lightmap[src].b * 255.0f); lightmap[dst + 3] = uint8_t(_lightmap[src].a * 255.0f); } } } voodoo::cImage generated; const uint8_t* pBuffer = &lightmap[0]; generated.CreateFromBuffer(pBuffer, widthLightmap, depthLightmap, opengl::PIXELFORMAT::R8G8B8A8); generated.SaveToBMP(TEXT("/home/chris/dev/tests/openglmm_heightmap/textures/generated.bmp")); exit(0); #endif { // Smooth the lightmap std::vector<spitfire::math::cColour> smoothed; SmoothImage(_lightmap, widthLightmap, depthLightmap, 10, smoothed); _lightmap = smoothed; } for (size_t i = 0; i < 3; i++) { // Double the resolution of the lightmap std::vector<spitfire::math::cColour> lightmapCopy; DoubleImageSize(_lightmap, widthLightmap, depthLightmap, lightmapCopy); _lightmap = lightmapCopy; widthLightmap *= 2; depthLightmap *= 2; // Smooth the lightmap std::vector<spitfire::math::cColour> smoothed; SmoothImage(_lightmap, widthLightmap, depthLightmap, 10, smoothed); _lightmap = smoothed; } const size_t nLightmap = widthLightmap * depthLightmap; // Copy the lightmap from the cColour vector to the uint8_t vector lightmap.resize(nLightmap * 4, 0); for (size_t y = 0; y < depthLightmap; y++) { for (size_t x = 0; x < widthLightmap; x++) { const size_t src = (y * widthLightmap) + x; const size_t dst = 4 * ((y * widthLightmap) + x); lightmap[dst + 0] = uint8_t(_lightmap[src].r * 255.0f); lightmap[dst + 1] = uint8_t(_lightmap[src].g * 255.0f); lightmap[dst + 2] = uint8_t(_lightmap[src].b * 255.0f); lightmap[dst + 3] = uint8_t(_lightmap[src].a * 255.0f); } } }