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);
}
Exemple #5
0
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;
			}
		}
	}

}