Image anisotropic_smoothing(const Image &image, int width, int height, const float amplitude, const float sharpness, const float anisotropy, const float alpha, const float sigma) { Image res(Geometry(width, height), "white"); res.type(GrayscaleType); #pragma omp critical { CImg<unsigned char> source(width, height, 1, 1, 0); unsigned char color[1] = { 0 }; unsigned char cc; ColorGray c; for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) { c = image.pixelColor(i, j); color[0] = (unsigned char) (255 * c.shade()); source.draw_point(i, j, color); } CImg<unsigned char> dest(source); const float gfact = 1.; //const float amplitude = 5.; // 20 // const float sharpness = 0.3; //const float anisotropy = 1.; //const float alpha = .2; //0.6 //const float sigma = 1.1; // 2. const float dl = 0.8; const float da = 30.; const float gauss_prec = 2.; const unsigned int interp = 0; const bool fast_approx = true; const unsigned int tile = 512; const unsigned int btile = 4; const unsigned int threads = 1; // orig - 2 dest.greycstoration_run(amplitude, sharpness, anisotropy, alpha, sigma, gfact, dl, da, gauss_prec, interp, fast_approx, tile, btile, threads); do { cimg::wait(1); } while (dest.greycstoration_is_running()); for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) { cc = dest(i, j); c.shade(1. * cc / 255); res.pixelColor(i, j, c); } } return (res); }
Image adaptive_otsu(const Image &image, int window) { int num_bins=20; Image result(Geometry(image.columns(),image.rows()),"white"); vector<int> h(num_bins,0); vector<int> h0(num_bins,0); ColorGray g; int peak1, peak2, max1, max2; for (int i1 = 0; i1 < min((int)image.columns(), window/2); i1++) for (int j1 = 0; j1 < min((int)image.rows(), window/2); j1++) { g = image.pixelColor(i1, j1); h0[int((num_bins-1)*g.shade())]++; } for (int j = 0; j < image.rows(); j++) { for (int k = 0; k<num_bins; k++) h[k]=h0[k]; for (int i = 0; i < image.columns(); i++) { otsu_find_peaks(h,num_bins,peak1,peak2, max1, max2); g = image.pixelColor(i, j); double median = 0.5*(peak1+peak2)/num_bins; if (g.shade() > median) result.pixelColor(i,j,"white"); else result.pixelColor(i,j,"black"); if ((i-window/2) >=0) for (int j1 = max(0,j-window/2); j1 < min((int)image.rows(), j + window/2); j1++) { g = image.pixelColor(i-window/2, j1); h[int((num_bins-1)*g.shade())]--; } if ((i+window/2) < image.columns()) for (int j1 = max(0,j-window/2); j1 < min((int)image.rows(), j + window/2); j1++) { g = image.pixelColor(i+window/2, j1); h[int((num_bins-1)*g.shade())]++; } } if ((j-window/2) >=0) for (int i1 = 0; i1 < min((int)image.columns(),window/2); i1++) { g = image.pixelColor(i1,j-window/2); h0[int((num_bins-1)*g.shade())]--; } if ((j+window/2) < image.rows()) for (int i1 = 0; i1 < min((int)image.columns(),window/2); i1++) { g = image.pixelColor(i1,j+window/2); h0[int((num_bins-1)*g.shade())]++; } } return(result); }
bool convert_to_gray(Image &image, bool invert, bool adaptive, bool verbose) { int num_bins=50; int num_bins_rgb = 20; vector<int> h(num_bins,0); vector < vector < vector <int> > > bg_search(num_bins_rgb, vector < vector <int> > (num_bins_rgb, vector<int>(num_bins_rgb, 0))); ColorRGB c,b; Color t; ColorGray g; double a; image.type(TrueColorMatteType); for (int i = 0; i < BG_PICK_POINTS; i++) { double a = (double) rand() / RAND_MAX; double b = (double) rand() / RAND_MAX; int x = int(image.columns() * a); int y = int(image.rows() * b); c = image.pixelColor(x, y); bg_search[int((num_bins_rgb-1)*c.red())][int((num_bins_rgb-1)*c.green())][int((num_bins_rgb-1)*c.blue())]++; } int bg_peak = 0; double bg_pos_red = 0, bg_pos_green = 0, bg_pos_blue = 0; for (int i=0; i<num_bins_rgb; i++) for (int j=0; j<num_bins_rgb; j++) for (int k=0; k<num_bins_rgb; k++) if (bg_search[i][j][k] > bg_peak) { bg_peak = bg_search[i][j][k]; bg_pos_red = (double)i/(num_bins_rgb-1); bg_pos_green = (double)j/(num_bins_rgb-1); bg_pos_blue = (double)k/(num_bins_rgb-1); } bool color_background = false; if (verbose) { cout<<"Background rgb: "<<bg_pos_red<<" "<<bg_pos_green<<" "<<bg_pos_blue<<endl; } if (fabs(bg_pos_red-bg_pos_green) > 0.05 || fabs(bg_pos_red-bg_pos_blue)>0.05 || fabs(bg_pos_green-bg_pos_blue)>0.05) color_background = true; bool matte = image.matte(); if (color_background) { image.contrast(2); image.type(GrayscaleType); } for (unsigned int i = 0; i < image.columns(); i++) for (unsigned int j = 0; j < image.rows(); j++) { t = image.pixelColor(i, j); b = t; g = t; if (matte && t.alpha() == 1 && g.shade() < 0.5) { g.shade(1); image.pixelColor(i, j, g); } else if (!color_background && (fabs(b.red()-b.green()) > 0.1 || fabs(b.red()-b.blue()) > 0.1 || fabs(b.blue()-b.green()) > 0.1)) { if (fabs(b.red()-bg_pos_red) >= fabs(b.green()-bg_pos_green) && fabs(b.red()-bg_pos_red) >= fabs(b.blue()-bg_pos_blue)) a = b.red(); else if (fabs(b.red()-bg_pos_red) < fabs(b.green()-bg_pos_green) && fabs(b.green()-bg_pos_green) >= fabs(b.blue()-bg_pos_blue)) a = b.green(); else a = b.blue(); c.red(a); c.green(a); c.blue(a); image.pixelColor(i, j, c); } g = image.pixelColor(i, j); h[int((num_bins-1)*g.shade())]++; } int peak1, peak2, max1, max2; otsu_find_peaks(h,num_bins,peak1,peak2, max1, max2); double distance_between_peaks = (double)(peak2-peak1)/(num_bins-1); // if (distance_between_peaks < THRESHOLD_GLOBAL) adaptive = true; if (distance_between_peaks < 0.5) adaptive = true; if (max1 > max2 || invert) invert = true; if (verbose) { cout << "Distance between light and dark: " << distance_between_peaks << endl; cout<<"Max at peak 1: "<<max1<<" Max at peak 2: "<<max2<<endl; cout<<"Color background? "<<color_background<<endl; cout<<"Adaptive? "<<adaptive<<endl; cout<<"Invert? "<<invert<<endl; } //const double kernel[]={0.0, -1.0, 0.0,-1.0, 5.0, -1.0, 0.0, -1.0, 0.0}; //image.convolve(3,kernel); if (!color_background) { image.contrast(2); image.type(GrayscaleType); } int window = min(image.columns(),image.rows()) / 41; if (window < 15) window = 15; if (adaptive) { image.despeckle(); if (invert) { image.adaptiveThreshold(window,window,7); } else { image.negate(); image.adaptiveThreshold(window,window,7); image.negate(); } } else if (color_background) { image.despeckle(); image = adaptive_otsu(image,window); } if (invert) image.negate(); // image.write("tmp.png"); return(adaptive); }
Image anisotropic_scaling(const Image &image, int width, int height, int nw, int nh) { Image res(Geometry(nw, nh), "white"); res.type(GrayscaleType); #pragma omp critical { CImg<unsigned char> source(width, height, 1, 1, 0); unsigned char color[1] = { 0 }; unsigned char cc; ColorGray c; for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) { c = image.pixelColor(i, j); color[0] = (unsigned char) (255 * c.shade()); source.draw_point(i, j, color); } //const float gfact = (sizeof(T) == 2) ? 1.0f / 256 : 1.0f; const float gfact = 1.; const float amplitude = 20.; // 40 20! const float sharpness = 0.2; // 0.2! 0.3 const float anisotropy = 1.; const float alpha = .6; //0.6! 0.8 const float sigma = 2.; //1.1 2.! const float dl = 0.8; const float da = 30.; const float gauss_prec = 2.; const unsigned int interp = 0; const bool fast_approx = true; const unsigned int tile = 512; // 512 0 const unsigned int btile = 4; const unsigned int threads = 1; // 2 1 const unsigned int init = 5; CImg<unsigned char> mask; mask.assign(source.dimx(), source.dimy(), 1, 1, 255); mask = !mask.resize(nw, nh, 1, 1, 4); source.resize(nw, nh, 1, -100, init); CImg<unsigned char> dest(source); dest.greycstoration_run(mask, amplitude, sharpness, anisotropy, alpha, sigma, gfact, dl, da, gauss_prec, interp, fast_approx, tile, btile, threads); do { cimg::wait(1); } while (dest.greycstoration_is_running()); for (int i = 0; i < nw; i++) for (int j = 0; j < nh; j++) { cc = dest(i, j); c.shade(1. * cc / 255); res.pixelColor(i, j, c); } } return (res); }
void ProcessImage::ReadImage(Image& image, vector<REAL>&pixval) { UINT m = image.rows(), n = image.columns(); if (channel == Gray) { image.type(GrayscaleType); ColorGray mycolor; UINT count = 0; for (UINT i = 0; i < m; ++i) { for (UINT j = 0; j < n; ++j) { ColorGray mycolor = image.pixelColor(j, i); pixval[count++] = mycolor.shade(); } } } // look into folder ~/ocs/ // sRGB2XYZ ==> Standard RGB values to XYZ color Space, then we convert from the XYZ to opponent Color Space // Where O1== luminance component... // O2 is the red-green channel // O3 is the blue-yellow channel.... else if (channel == O1 || channel == O2 || channel == O3) { // Older Transformation matrix... // REAL tm[3][3]={{0.2814, 0.6938, 0.0638}, // {-0.0971 0.1458 -0.0250}, // {-0.0930 -0.2529 0.4665}}; // // RGB2OCS rgb 2 opponent Color Space... REAL tm[3][3] = { { 0.2661, 0.6019, 0.0006 }, { -0.1250, 0.0377, -0.1332 }, { -0.0803, -0.3315, 0.4490 } }; const PixelPacket *pix1 = image.getConstPixels(0, 0, n, m); PixelPacket tpix; UINT count = 0, tvar; REAL factor = 1.0 / MaxRGB; UINT row = channel == O1 ? 0 : channel == O2 ? 1 : 2; for (UINT i = 0; i < m; ++i) { tvar = i * n; for (UINT j = 0; j < n; ++j) { tpix = pix1[tvar + j];//0.2814 0.6938 0.0638 pixval[count++] = (tpix.red * tm[row][0] + tpix.green * tm[row][1] + tpix.blue * tm[row][2]) * factor; } } } else if (channel == ABSGradientMag) { UINT width = image.columns(), height = image.rows(); const PixelPacket *pix = image.getConstPixels(0, 0, width, height); REAL factor = 255.0 / (pow(2.0, 16.0) - 1);// scaling factor to have real values[0,1] UINT count = 0; for (int ty = 1; ty < height - 1; ty++) { for (int tx = 1; tx < width - 1; tx++) { //abs(g)=abs(gx)+abs(gy) // first color channel double dy = (pix[tx + (ty + 1) * width].red - pix[tx + (ty - 1) * width].red) * factor, dy2 = (pix[tx + (ty + 1) * width].green - pix[tx + (ty - 1) * width].green) * factor, dy3 = (pix[tx + (ty + 1) * width].blue - pix[tx + (ty - 1) * width].blue) * factor, dx = (pix[(tx + 1) + ty * width].red - pix[(tx - 1) + ty * width].red) * factor, dx2 = (pix[(tx + 1) + ty * width].green - pix[(tx - 1) + ty * width].green) * factor, dx3 = (pix[(tx + 1) + ty * width].blue - pix[(tx - 1) + ty * width].blue) * factor, v = ABS(dx) + ABS(dy), v2 = ABS(dx2) + ABS(dy2), v3 = ABS( dx3) + ABS(dy3); // pick channel with strongest ABSOLUTE gradient if (v2 > v) { v = v2; } if (v3 > v) { v = v3; } pixval[count++] = v; } } } else { const PixelPacket *pix1 = image.getConstPixels(0, 0, n, m); UINT count = 0, tvar; REAL factor = 1.0 / MaxRGB; if (channel == Red) { for (UINT i = 0; i < m; ++i) { tvar = i * n; for (UINT j = 0; j < n; ++j) pixval[count++] = pix1[tvar + j].red * factor; } } else if (channel == Blue) { for (UINT i = 0; i < m; ++i) { tvar = i * n; for (UINT j = 0; j < n; ++j) pixval[count++] = pix1[tvar + j].blue * factor; } } else { for (UINT i = 0; i < m; ++i) { tvar = i * n; for (UINT j = 0; j < n; ++j) pixval[count++] = pix1[tvar + j].green * factor; } } } }