//---------------------------------------------------------------------------- void RayTrace::Correction (float gamma) { mGamma = gamma; for (int i = 0; i < mAccum->GetQuantity(); ++i) { unsigned char gray = (unsigned char)(31.0f*Mathf::Pow((*mAccum)[i], mGamma)); (*mRender)[i] = GetColor24(gray, gray, gray); } }
//---------------------------------------------------------------------------- void SimplePendulum::SolveMethod (float* (*method)(float,float,float), const char* outImage, const char* outText) { float x0 = 0.1f, y0 = 1.0f; float h = 0.1f; float* output = method(x0, y0, h); std::string path = Environment::GetPathW(outText); std::ofstream outFile(path.c_str()); int i; for (i = 0; i < SIZE; ++i) { outFile << "i = " << i << ", " << output[i] << std::endl; } // Set image to white. for (i = 0; i < msImage->GetQuantity(); ++i) { (*msImage)[i] = GetColor24(255, 255, 255); } // Draw the approximate solution. float y = 256.0f*(output[0] + 3.0f)/6.0f; int iY0 = SIZE - 1 - (int)y; for (i = 1; i < SIZE; ++i) { y = 256.0f*(output[i] + 3.0f)/6.0f; int iY1 = SIZE - 1 - (int)y; Line2D(i - 1, iY0, i, iY1, DrawPixel); iY0 = iY1; } path = Environment::GetPathW(outImage); msImage->Save(path.c_str()); delete1(output); }
//---------------------------------------------------------------------------- void RayTrace::Line2D (bool visible, int x0, int y0, int x1, int y1) { // Starting point of line. int x = x0, y = y0; // Direction of line. int dx = x1-x0, dy = y1-y0; // Increment or decrement depending on direction of line. int sx = (dx > 0 ? 1 : (dx < 0 ? -1 : 0)); int sy = (dy > 0 ? 1 : (dy < 0 ? -1 : 0)); // Decision parameters for pixel selection. dx = abs(dx); dy = abs(dy); int ax = 2*dx, ay = 2*dy; int xDec, yDec; // Determine largest direction component and single-step related variable. int dmax = dx, var = 0; if (dy > dmax) { dmax = dy; var = 1; } // Traverse Bresenham line and set render colors. switch (var) { case 0: // Single-step in x-direction. yDec = ay - dx; for (/**/; /**/; x += sx, yDec += ay) { // Process pixel (x,y). if (visible) { (*mRender)(x, y) = GetColor24(255, 0, 0); } else { (*mRender)(x, y) = GetColor24(128, 0, 0); } // Take Bresenham step. if (x == x1) { break; } if (yDec >= 0) { yDec -= ax; y += sy; } } break; case 1: // Single-step in y-direction. xDec = ax - dy; for (/**/; /**/; y += sy, xDec += ax) { // Process pixel (x,y). if (visible) { (*mRender)(x, y) = GetColor24(255, 0, 0); } else { (*mRender)(x, y) = GetColor24(128, 0, 0); } // Take Bresenham step. if (y == y1) { break; } if (xDec >= 0) { xDec -= ay; x += sx; } } break; } }
//---------------------------------------------------------------------------- void RayTrace::Line3D (int j0, int j1, int x0, int y0, int z0, int x1, int y1, int z1) { // Starting point of line. int x = x0, y = y0, z = z0; // Direction of line. int dx = x1 - x0, dy = y1 - y0, dz = z1 - z0; // Increment or decrement depending on direction of line. int sx = (dx > 0 ? 1 : (dx < 0 ? -1 : 0)); int sy = (dy > 0 ? 1 : (dy < 0 ? -1 : 0)); int sz = (dz > 0 ? 1 : (dz < 0 ? -1 : 0)); // Decision parameters for voxel selection. dx = abs(dx); dy = abs(dy); dz = abs(dz); int ax = 2*dx, ay = 2*dy, az = 2*dz; int xDec, yDec, zDec; // Determine largest direction component and single-step related variable. int dmax = dx, var = 0; if (dy > dmax) { dmax = dy; var = 1; } if (dz > dmax) { dmax = dz; var = 2; } // Traverse Bresenham line and accumulate density values. int index = j0 + mAccum->GetBound(0)*j1; switch (var) { case 0: // Single-step in x-direction. yDec = ay - dx; zDec = az - dx; for (/**/; /**/; x += sx, yDec += ay, zDec += az) { // Accumulate the density value. (*mAccum)[index] = (*mAccum)[index] + (*mDensity)(x, y, z); // Take Bresenham step. if (x == x1) { break; } if (yDec >= 0) { yDec -= ax; y += sy; } if (zDec >= 0) { zDec -= ax; z += sz; } } break; case 1: // Single-step in y-direction. xDec = ax - dy; zDec = az - dy; for (/**/; /**/; y += sy, xDec += ax, zDec += az) { // Accumulate the density value. (*mAccum)[index] = (*mAccum)[index] + (*mDensity)(x, y, z); // Take Bresenham step. if (y == y1) { break; } if (xDec >= 0) { xDec -= ay; x += sx; } if (zDec >= 0) { zDec -= ay; z += sz; } } break; case 2: // Single-step in z-direction. xDec = ax - dz; yDec = ay - dz; for (/**/; /**/; z += sz, xDec += ax, yDec += ay) { // Accumulate the density value. (*mAccum)[index] = (*mAccum)[index] + (*mDensity)(x, y, z); // Take Bresenham step. if (z == z1) { break; } if (xDec >= 0) { xDec -= az; x += sx; } if (yDec >= 0) { yDec -= az; y += sy; } } break; } unsigned char gray = (unsigned char)(255.0f*Mathf::Pow((*mAccum)[index], mGamma)); (*mRender)[index] = GetColor24(gray, gray, gray); }
//---------------------------------------------------------------------------- void SimplePendulum::Stiff1 () { const int maxIterations = 1024 + 256; const float cSqr = 2.0f, c = Mathf::Sqrt(2.0f); float h = 0.01f; float x0 = 1.0f, x0Save = x0; float y0 = -c*x0; float* approx = new1<float>(maxIterations); int i; for (i = 0; i < maxIterations; ++i) { float k1X = h*y0; float k1Y = h*cSqr*x0; float x1 = x0 + 0.5f*k1X; float y1 = y0 + 0.5f*k1Y; float k2X = h*y1; float k2Y = h*cSqr*x1; x1 = x0 + 0.5f*k2X; y1 = y0 + 0.5f*k2Y; float k3X = h*y1; float k3Y = h*cSqr*x1; x1 = x0 + k3X; y1 = y0 + k3Y; float k4X = h*y1; float k4Y = h*cSqr*x1; x1 = x0 + (k1X + 2.0f*k2X + 2.0f*k3X + k4X)/6.0f; y1 = y0 + (k1Y + 2.0f*k2Y + 2.0f*k3Y + k4Y)/6.0f; approx[i] = x1; x0 = x1; y0 = y1; } std::string path = Environment::GetPathW("Data/stiff1.txt"); std::ofstream outFile(path.c_str()); for (i = 0; i < maxIterations; ++i) { outFile << "i = " << i << ", " << approx[i] << std::endl; } // Set image to white. for (i = 0; i < msImage->GetQuantity(); ++i) { (*msImage)[i] = GetColor24(255, 255, 255); } // Draw the true solution. float y = 256.0f*(x0Save + 3.0f)/6.0f; int iY0 = SIZE - 1 - (int)y; for (i = 1; i < SIZE; ++i) { int j = (maxIterations - 1)*i/(SIZE - 1); y = 256.0f*(x0Save*Mathf::Exp(-c*j*h) + 3.0f)/6.0f; int iY1 = SIZE - 1 - (int)y; Line2D(i - 1, iY0, i, iY1, DrawPixel); iY0 = iY1; } path = Environment::GetPathW("Data/stiff1_true.im"); msImage->Save(path.c_str()); // Set image to white. for (i = 0; i < msImage->GetQuantity(); ++i) { (*msImage)[i] = GetColor24(255, 255, 255); } // Draw the approximate solution. y = 256.0f*(approx[0] + 3.0f)/6.0f; iY0 = SIZE - 1 - (int)y; for (i = 1; i < SIZE; ++i) { int j = (maxIterations - 1)*i/(SIZE - 1); y = 256.0f*(approx[j] + 3.0f)/6.0f; int iY1 = SIZE - 1 - (int)y; Line2D(i - 1, iY0, i, iY1, DrawPixel); iY0 = iY1; } path = Environment::GetPathW("Data/stiff1_appr.im"); msImage->Save(path.c_str()); delete1(approx); }
//---------------------------------------------------------------------------- int ExtractRidges::Main (int, char**) { std::string imageName = Environment::GetPathR("Head.im"); ImageDouble2D image(imageName.c_str()); // Normalize the image values to be in [0,1]. int quantity = image.GetQuantity(); double minValue = image[0], maxValue = minValue; int i; for (i = 1; i < quantity; ++i) { if (image[i] < minValue) { minValue = image[i]; } else if (image[i] > maxValue) { maxValue = image[i]; } } double invRange = 1.0/(maxValue - minValue); for (i = 0; i < quantity; ++i) { image[i] = (image[i] - minValue)*invRange; } // Use first-order centered finite differences to estimate the image // derivatives. The gradient is DF = (df/dx, df/dy) and the Hessian // is D^2F = {{d^2f/dx^2, d^2f/dxdy}, {d^2f/dydx, d^2f/dy^2}}. int xBound = image.GetBound(0); int yBound = image.GetBound(1); int xBoundM1 = xBound - 1; int yBoundM1 = yBound - 1; ImageDouble2D dx(xBound, yBound); ImageDouble2D dy(xBound, yBound); ImageDouble2D dxx(xBound, yBound); ImageDouble2D dxy(xBound, yBound); ImageDouble2D dyy(xBound, yBound); int x, y; for (y = 1; y < yBoundM1; ++y) { for (x = 1; x < xBoundM1; ++x) { dx(x, y) = 0.5*(image(x+1, y) - image(x-1, y)); dy(x, y) = 0.5*(image(x, y+1) - image(x, y-1)); dxx(x, y) = image(x+1, y) - 2.0*image(x, y) + image(x-1, y); dxy(x, y) = 0.25*(image(x+1, y+1) + image(x-1, y-1) - image(x+1, y-1) - image(x-1, y+1)); dyy(x, y) = image(x, y+1) - 2.0*image(x, y) + image(x, y+1); } } dx.Save("dx.im"); dy.Save("dy.im"); dxx.Save("dxx.im"); dxy.Save("dxy.im"); dyy.Save("dyy.im"); // The eigensolver produces eigenvalues a and b and corresponding // eigenvectors U and V: D^2F*U = a*U, D^2F*V = b*V. Define // P = Dot(U,DF) and Q = Dot(V,DF). The classification is as follows. // ridge: P = 0 with a < 0 // valley: Q = 0 with b > 0 ImageDouble2D aImage(xBound, yBound); ImageDouble2D bImage(xBound, yBound); ImageDouble2D pImage(xBound, yBound); ImageDouble2D qImage(xBound, yBound); for (y = 1; y < yBoundM1; ++y) { for (x = 1; x < xBoundM1; ++x) { Vector2d gradient(dx(x, y), dy(x, y)); Matrix2d hessian(dxx(x, y), dxy(x, y), dxy(x, y), dyy(x, y)); EigenDecompositiond decomposer(hessian); decomposer.Solve(true); aImage(x,y) = decomposer.GetEigenvalue(0); bImage(x,y) = decomposer.GetEigenvalue(1); Vector2d u = decomposer.GetEigenvector2(0); Vector2d v = decomposer.GetEigenvector2(1); pImage(x,y) = u.Dot(gradient); qImage(x,y) = v.Dot(gradient); } } aImage.Save("a.im"); bImage.Save("b.im"); pImage.Save("p.im"); qImage.Save("q.im"); // Use a cheap classification of the pixels by testing for sign changes // between neighboring pixels. ImageRGB82D result(xBound, yBound); for (y = 1; y < yBoundM1; ++y) { for (x = 1; x < xBoundM1; ++x) { unsigned char gray = (unsigned char)(255.0f*image(x, y)); double pValue = pImage(x, y); bool isRidge = false; if (pValue*pImage(x-1 ,y) < 0.0 || pValue*pImage(x+1, y) < 0.0 || pValue*pImage(x, y-1) < 0.0 || pValue*pImage(x, y+1) < 0.0) { if (aImage(x, y) < 0.0) { isRidge = true; } } double qValue = qImage(x,y); bool isValley = false; if (qValue*qImage(x-1, y) < 0.0 || qValue*qImage(x+1, y) < 0.0 || qValue*qImage(x, y-1) < 0.0 || qValue*qImage(x, y+1) < 0.0) { if (bImage(x,y) > 0.0) { isValley = true; } } if (isRidge) { if (isValley) { result(x, y) = GetColor24(gray, 0, gray); } else { result(x, y) = GetColor24(gray, 0, 0); } } else if (isValley) { result(x, y) = GetColor24(0, 0, gray); } else { result(x, y) = GetColor24(gray, gray, gray); } } } result.Save("result.im"); return 0; }