/**
find all the runs in the img
parameter:
@origin				--the original CImg pic
@NumberofRuns		--count the number of runs
@stRun				--record the start of a run
@enRun				--record the end of a run
@rowRun				--record which row the run is in
@masRun				--record how much mass a run has
*/
void fillRunVector(cimg_library::CImg<unsigned char> origin, int &NumberofRuns, std::vector<int> &stRun, std::vector<int> &enRun, std::vector<int> &rowRun, std::vector<int> &masRun)
{
	for (int i = 0; i < origin.height(); i++){
		if (origin.atXY(0, i) == 255){
			NumberofRuns++;
			stRun.push_back(0);
			rowRun.push_back(i);
		}
		for (int j = 1; j < origin.width(); j++){
			if (origin.atXY(j - 1, i) == 0 && origin.atXY(j, i) == 255){
				NumberofRuns++;
				stRun.push_back(j);
				rowRun.push_back(i);
			}
			else if (origin.atXY(j-1, i) == 255 && origin.atXY(j, i) == 0) {
				enRun.push_back(j - 1);
				masRun.push_back(enRun[NumberofRuns-1] - stRun[NumberofRuns-1] + 1);
			}
		}
		if (origin.atXY(origin.width() - 1,i)){
			enRun.push_back(origin.width() - 1);
			masRun.push_back(enRun[NumberofRuns-1] - stRun[NumberofRuns-1] + 1);
		}
	}
}
Exemple #2
0
 int Plot2DAxes::drawOnto(cimg_library::CImg<unsigned char> & im, float opacity)
     {
     im.fBox2_drawAxes(_range, _gradColor, opacity);
     if (_gradStatus) im.fBox2_drawGraduations(_range, _scaling, _gradColor, opacity);
     if (_numStatus) im.fBox2_drawNumbers(_range, _scaling, _numColor, opacity);
     return 100;
     }
void DrawLine(cimg_library::CImg<unsigned char>& mask, int x0, int y0, int x1, int y1){
	int dx = x1 - x0;
	int dy = y1 - y0;
	int ux = ((dx > 0) << 1) - 1;
	int uy = ((dy > 0) << 1) - 1;
	int x = x0, y = y0, eps;

	eps = 0; dx = abs(dx); dy = abs(dy);
	if (dx > dy){
		for (x = x0; x != x1; x += ux){
			mask.atXY(x,y) = 255;
			eps += dy;
			if ((eps << 1) >= dx){
				y += uy; eps -= dx;
			}
		}
	}
	else{
		for (y = y0; y != y1; y += uy){
			mask.atXY(x,y) = 255;
			eps += dx;
			if ((eps << 1) >= dy){
				x += ux; eps -= dy;
			}
		}
	}
}
Exemple #4
0
void writeMagnitude(cimg_library::CImg<T>& image, const std::vector<T>& magnitude) {
    for (int x=0; x<image.width(); x++) {
        for (int y=0; y<image.height(); y++) {
            const unsigned char mag = magnitude[y*image.width()+x];
            const unsigned char color_mag[] = { mag, mag, mag };
            image.draw_point(x, y, color_mag);
        }
    }
}
Exemple #5
0
std::vector<std::vector<double> > calculate_luminosity(cimg_library::CImg<unsigned char> &image) {
    std::vector<std::vector<double> > luminosity_map(image.height(), std::vector<double>(image.width(), DBL_MAX));
    for (int i = 0; i < image.height(); i++) {
        for (int j = 0; j < image.width(); j++) {
            luminosity_map[i][j] = luminosity(image.atXY(j, i, 0, 0), image.atXY(j, i, 0, 1), image.atXY(j, i, 0, 2));
        }
    }
    return luminosity_map;
}
Exemple #6
0
void writeMagnitudeDirection(cimg_library::CImg<T>& image, const std::vector<T>& magnitude, const std::vector<float>& direction) {
    for (int x=0; x<image.width(); x++) {
        for (int y=0; y<image.height(); y++) {
            float _r,_g,_b;
            HSVtoRGB(&_r, &_g, &_b, direction[y*image.width()+x]*180/M_PI, 1, (float)magnitude[y*image.width()+x]/255.0);
            const T color_dir[] = { (int)floor(_r*255), (int)floor(_g*255), (int)floor(_b*255) };
            image.draw_point(x, y, color_dir);
        }
    }
}
//找最大的团并返回外轮廓
std::vector<MYPOINT> FindBiggestContour(cimg_library::CImg<unsigned char> origin, std::vector<MYPOINT> Points)
{
	std::vector<MYPOINT> contour;
	cimg_library::CImg<unsigned char> mask;
	//compute the binary img
	int threshold = otsu(origin, Points, mask, 1);
	unsigned char *bi_img = new unsigned char[origin.width()*origin.height()];
	for (int i = 0; i < origin.height(); i++){
		for (int j = 0; j < origin.width(); j++){
			if (origin.atXY(j, i) >= threshold && mask.atXY(j, i) == 255)
				bi_img[i*origin.width() + j] = 255;
			else
				bi_img[i*origin.width() + j] = 0;
		}
	}
	//返回二值图像
	cimg_library::CImg<unsigned char> bi(bi_img, origin.width(), origin.height());
	//done
	
	//找团
	std::vector<int> stRun, enRun, rowRun, masRun;
	int NumberofRuns = 0, offset = 1, maxRun = 1;
	fillRunVector(bi, NumberofRuns, stRun, enRun, rowRun, masRun);
	std::vector<int> runLabels;
	std::vector<std::pair<int, int>> equivalences;
	firstPass(stRun, enRun, rowRun, NumberofRuns, runLabels, equivalences, offset);
	if (!NumberofRuns){
		std::cout << "NOTHING FOUND!!!" << std::endl 
			<<"size of contour is: "<< contour.size() <<  std::endl;
		return contour;
	}
	replaceSameLabel(runLabels, equivalences);

	int maxLabel = *max_element(runLabels.begin(), runLabels.end());
	int *MassofRuns = new int[maxLabel + 1];
	memset(MassofRuns, 0, (maxLabel + 1)*sizeof(int));

	memset(bi_img, 0, (bi.height()*bi.width())*sizeof(unsigned char));
	for (int c = 0; c < NumberofRuns; c++){
		MassofRuns[runLabels[c]] += masRun[c];
		if (MassofRuns[runLabels[c]]>maxRun){
			maxRun = MassofRuns[runLabels[c]];
			maxLabel = runLabels[c];
		}
		int i = rowRun[c]; 
		for (int j = stRun[c]; j <= enRun[c]; j++){
			bi_img[i*bi.width() + j] = runLabels[c];
		}
	}
	for (int i = 0; i < bi.height(); i++)
	for (int j = 0; j < bi.width(); j++) {
		if (bi_img[i*bi.width()+j] == maxLabel)
			bi_img[i*bi.width() + j] = 255;
		else
			bi_img[i*bi.width() + j] = 0;
	}

	return FindContour(bi_img, bi.width(), bi.height());
}
int patchDistance(cimg_library::CImg<unsigned char> currentPatch,cimg_library::CImg<unsigned char> patchPlusOffset)
{
    int width = currentPatch.width();
    int height = currentPatch.height();
    int distance =0;
    for(int i = 0; i< width; i++)
    {
        for(int j = 0; j< height; j++)
        {

            distance = distance + ((int)(currentPatch.atXY(i,j,0))-(int)(patchPlusOffset.atXY(i,j,0)))*((int)(currentPatch.atXY(i,j,0))-(int)(patchPlusOffset.atXY(i,j,0))) + ((int)(currentPatch.atXY(i,j,1))-(int)(patchPlusOffset.atXY(i,j,1)))*((int)(currentPatch.atXY(i,j,1))-(int)(patchPlusOffset.atXY(i,j,1))) + ((int)(currentPatch.atXY(i,j,2))-(int)(patchPlusOffset.atXY(i,j,2)))*((int)(currentPatch.atXY(i,j,2))-(int)(patchPlusOffset.atXY(i,j,2)));
        }
    }

    return distance;

};
Exemple #9
0
void sobelOperator(const cimg_library::CImg<T>& image, std::vector<T>& magnitude, std::vector<float>& direction) {
    //Allocate the magnitude
    magnitude.resize(image.width()*image.height());
    direction.resize(image.width()*image.height());

    //Loop through the image and apply the sobel operator
    for (int x=0; x<image.width(); x++) {
        for (int y=0; y<image.height(); y++) {
            int dx=0, dy=0, mag = 0;
            float dir=0;

            if (!(x == 0 || x == image.width()-1 || y == 0 || y == image.height()-1)) {
                for (int i=-1; i<=1; i++) {
                    for (int j=-1; j<=1; j++) {
                        dx = dx + gx[j+1][i+1] * greyVal(image, x+j, y+i);
                        dy = dy + gy[j+1][i+1] * greyVal(image, x+j, y+i);
                    }
                }
            }

            mag = (int)sqrt(pow((double)dx,2) + pow((double)dy,2));
            dir = atan2(dy, dx);

            if (mag > 255) mag = 255;
            if (mag < 0) mag = 0;

            magnitude[y*image.width()+x] = mag;
            direction[y*image.width()+x] = dir;
        }
    }
}
Exemple #10
0
void flood(cimg_library::CImg<unsigned char> &draw_image, std::vector<std::vector<int> > &energy_map, char *color, int val, int x, int y) {
    if (!valid_coord(std::pair<int, int>(x, y), energy_map[0].size(), energy_map.size())) return;
    if (energy_map[x][y] == val) return;

    draw_image.draw_point(y, x, color);
    energy_map[x][y] = val;

    flood(draw_image, energy_map, color, val, x - 1, y); 
    flood(draw_image, energy_map, color, val, x + 1, y); 
    flood(draw_image, energy_map, color, val, x, y - 1); 
    flood(draw_image, energy_map, color, val, x, y + 1); 
}
double
image_to_pl_function(const cimg_library::CImg<double> &image,
		     T &t,
		     std::map<typename T::Face_handle, Function> &fs)
{
  typedef typename T::Point Point;
  std::vector<Point> grid;
  std::map<Point, double> fgrid;
  size_t n = image.width();
  size_t m = image.height();
  double dx = 2/double(n-1), x0=-1.0;
  double dy = 2/double(m-1), y0=-1.0;
  for (size_t i = 0; i < n; ++i)
    {
      for (size_t j = 0; j < m; ++j)
	{
	  Point p(x0 + i * dx,
		  y0 + j * dy);
	  grid.push_back(p);
	  fgrid[p] = image(i,m-j-1)/double(255) + 1e-3;
	}
    }
  t = T(grid.begin(), grid.end());

  double tot_orig(0);
  for (auto f = t.finite_faces_begin(); 
       f != t.finite_faces_end(); ++f)
    {
      Point p = f->vertex(0)->point(), 
	q = f->vertex(1)->point(), 
	r = f->vertex(2)->point();
      fs[f] = Function(p, fgrid[p], 
		       q, fgrid[q],
		       r, fgrid[r]);
      tot_orig += CGAL::to_double(MA::integrate_centroid(p,q,r, fs[f]));
    }
  return tot_orig;
}
Exemple #12
0
void applyQWAF(cimg_library::CImg<T>& image,cimg_library::CImg<T>& out) {
    for (int x=0; x<image.width(); x++) {
        for (int y=0; y<image.height(); y++) {
            Quaternion q[9];
            for (int ix=-1; ix<=1; ix++) {
                for (int iy=-1; iy<=1; iy++) {
                    int mx=x,my=y;
                    coord(mx, my, image.width(), image.height());
                    q[(iy+1)*3+(ix+1)] = Quaternion(0,image(mx,my,0,0),image(mx,my,0,1),image(mx,my,0,2));
                }
            }

            //Get the weighted average filter
            Quaternion p = QWAF(q);
            int mx=x, my=y;
            coord(mx, my, image.width(), image.height());
            T col[3] = { (T)p.b, (T)p.c, (T)p.d };
            out.draw_point(mx, my, col);
        }
    }
}
Exemple #13
0
inline void loadImage( const std::string& filename, cimg_library::CImg<T>& image )
{
    image.load( filename.c_str() );
}
/*
输入原二值图像,返回一个MYPOINT类型的容器,容器内标记最大连通域的外轮廓
这是直接对已经找到最大连通域的二值图像进行外轮廓标记
*/
std::vector<MYPOINT> FindContour(cimg_library::CImg<unsigned char> origin)
{
	int i = 0, j = 0;
	int cols = origin.width(), rows = origin.height();
	int imgsize = (cols + 2)*(rows + 2);
	unsigned char *ori = new unsigned char[imgsize];
	memset(ori, 0, imgsize*sizeof(unsigned char));
	for (i = 0; i < rows; i++){
		for (j = 0; j < cols; j++)
			ori[(i + 1)*(cols + 2) + (j + 1)] = origin[j,i];
	}
	int *oriLabel = new int[imgsize];
	memset(oriLabel, 0, imgsize*sizeof(int));
	std::vector < MYPOINT > contour;

	//find the start point
	for (i = 0; i < rows + 2; i++){
		for (j = 0; j < cols + 2 && ori[i*(cols + 2) + j] != 255; j++){}
		if (ori[i*(cols + 2) + j] == 255)
			break;
	}

	if (i == rows + 2 && j == cols + 2 && ori[imgsize] == 0) {
		std::cout << "there is no contour." << std::endl;
		return contour;
	}
	MYPOINT start(i - 1, j - 1);
	contour.push_back(start);
	oriLabel[i*(cols + 2) + j] = 1;

	//设置循环计算的参数
	MYPOINT CurP;
	MYPOINT LastP = start;
	int x[8] = { i, i + 1, i + 1, i + 1, i, i - 1, i - 1, i - 1 };
	int y[8] = { j + 1, j + 1, j, j - 1, j - 1, j - 1, j, j + 1 };
	int c = 7, n = 0;
	for (n = 0; n < 8; n++){
		if (ori[x[c] * (cols + 2) + y[c]] == 255) {
			oriLabel[x[c] * (cols + 2) + y[c]] = 1;
			break;
		}
		else
			oriLabel[x[c] * (cols + 2) + y[c]] = -1;
		c = (c + 1) % 8;
	}
	if (n == 7 && ori[x[c] * (cols + 2) + y[c]] == 0) {
		return contour;
	}
	else{
		CurP.x = x[c] - 1;
		CurP.y = y[c] - 1;
		contour.push_back(CurP);
		//重新计算x[],y[],c, n
		x[0] = CurP.x + 1, x[1] = CurP.x + 1 + 1, x[2] = CurP.x + 1 + 1, x[3] = CurP.x + 1 + 1, x[4] = CurP.x + 1, x[5] = CurP.x + 1 - 1, x[6] = CurP.x + 1 - 1, x[7] = CurP.x + 1 - 1;
		y[0] = CurP.y + 1 + 1, y[1] = CurP.y + 1 + 1, y[2] = CurP.y + 1, y[3] = CurP.y + 1 - 1, y[4] = CurP.y + 1 - 1, y[5] = CurP.y + 1 - 1, y[6] = CurP.y + 1, y[7] = CurP.y + 1 + 1;
		n = 0, c = (c + 6) % 8;
	}
	//std::cout << start << std::endl;
	int stop = 1;
	while (stop != 0){
		for (n = 0; n < 8; n++){
			if (ori[x[c] * (cols + 2) + y[c]] == 255) {
				oriLabel[x[c] * (cols + 2) + y[c]] = 1;
				break;
			}
			else
				oriLabel[x[c] * (cols + 2) + y[c]] = -1;
			c = (c + 1) % 8;
		}
		LastP = CurP;
		CurP.x = x[c] - 1;
		CurP.y = y[c] - 1;
		contour.push_back(CurP);
		//重新计算x[],y[],c, n
		if (LastP.x == start.x && LastP.y == start.y){
			//for (int cc = 0; cc < 7; cc++)
			//	printf("%3d, %3d, %3d, %3d, %3d, %3d, %3d\n", oriLabel[cc * 7 + 0], oriLabel[cc * 7 + 1], oriLabel[cc * 7 + 2], oriLabel[cc * 7 + 3], oriLabel[cc * 7 + 4], oriLabel[cc * 7 + 5], oriLabel[cc * 7 + 6], oriLabel[cc * 7 + 7]);
			for (n = 0; n < 8 && (oriLabel[x[n] * (cols + 2) + y[n]] != 0 || ori[x[n] * (cols + 2) + y[n]] == 255); n++);
			if (n == 8 && (oriLabel[x[7] * (cols + 2) + y[7]] != 0 || ori[x[7] * (cols + 2) + y[7]] == 255))
				stop = 0;
			contour.pop_back();
		}
		x[0] = CurP.x + 1, x[1] = CurP.x + 1 + 1, x[2] = CurP.x + 1 + 1, x[3] = CurP.x + 1 + 1, x[4] = CurP.x + 1, x[5] = CurP.x + 1 - 1, x[6] = CurP.x + 1 - 1, x[7] = CurP.x + 1 - 1;
		y[0] = CurP.y + 1 + 1, y[1] = CurP.y + 1 + 1, y[2] = CurP.y + 1, y[3] = CurP.y + 1 - 1, y[4] = CurP.y + 1 - 1, y[5] = CurP.y + 1 - 1, y[6] = CurP.y + 1, y[7] = CurP.y + 1 + 1;
		c = (c + 6) % 8;
	}

	//unsigned char *op = new unsigned char[rows*cols];
	//for (int i = 0; i < rows; i++){
	//	for (int j = 0; j < cols; j++){
	//		if (oriLabel[(i + 1)*(cols + 2) + (j + 1)] == 1)
	//			op[i*cols + j] = 255;
	//		else
	//			op[i*cols + j] = 0;
	//	}
	//}
	//cimg_library::CImg<unsigned char> ttt(op, rows, cols);
	//cimg_library::CImgDisplay ddd(ttt, "ddd");
	return contour;
}
/**
otsu, return the computed threshold,the CImg version
parameter:
@origin		--original pic
@Points		--ROI, 给定连续的点,按顺序连城线以确定一个封闭的环
@debug		--debug option, 0 means no information outputed
*/
int otsu(cimg_library::CImg<unsigned char> origin, std::vector<MYPOINT> Points, cimg_library::CImg<unsigned char>& mask, int debug = 0){
	int thresholdValue = 1;
	int ihist[256] = { 0 };

	int i, j, k;
	int rows = origin.height(), cols = origin.width();
	int n, n1, n2, gmin = 255, gmax = 0;
	double m1, m2, sum, csum, fmax, sb;
	int x0 = origin.width(), y0 = origin.height(), x1 = 0, y1 = 0;
	//缩小计算范围
	for (std::vector<MYPOINT>::iterator it = Points.begin(); it != Points.end(); it++){
		x0 = x0 < (*it).x ? x0 : (*it).x;
		y0 = y0 < (*it).y ? y0 : (*it).y;
		x1 = x1 > (*it).x ? x1 : (*it).x;
		y1 = y1 > (*it).y ? y1 : (*it).y;
	}

	mask = AreaMask(origin, Points);
	

	for (i = y0; i <= y1; i++){
		for (j = x0; j < x1; j++){
			if (mask.atXY(j, i) == 255){
				ihist[origin.atXY(j,i)]++;
				if (origin.atXY(j,i) > gmax)gmax = origin.atXY(j,i);
				if (origin.atXY(j,i) < gmin)gmin = origin.atXY(j,i);
			}
		}
	}

	sum = csum = 0.0;
	n = 0;
	for (k = 0; k < 256; k++){
		sum += (double)k*(double)ihist[k];
		n += ihist[k];
	}

	if (!n){
		std::cout << "NOT NORMAL!!!" << std::endl << " thresholdValue = 160\n" << std::endl;
		return 160;
	}

	//do the otsu global thresholding method
	fmax = -1.0;
	n1 = 0;
	for (k = 0; k < 255; k++){
		n1 += ihist[k];
		if (!n1){ continue; }
		n2 = n - n1;
		if (n2 == 0){ break; }
		csum += (double)k*ihist[k];
		m1 = csum / n1;
		m2 = (sum - csum) / n2;
		sb = (double)n1*(double)n2*(m1 - m2)*(m1 - m2);
		if (sb>fmax){
			fmax = sb;
			thresholdValue = k;
		}
	}
	if (debug) std::cout << "#OTSU: thresholdValue = " << thresholdValue << std::endl
		<< "gmin = " << gmin << std::endl
		<< "gmax = " << gmax << std::endl;
	return thresholdValue;
}
cimg_library::CImg<unsigned char> AreaMask(cimg_library::CImg<unsigned char> origin, std::vector<MYPOINT> Points){
	int i, j, x0 = origin.width(), y0 = origin.height(), x1 = 0, y1 = 0;
	cimg_library::CImg<unsigned char> mask(origin.width(), origin.height(), 1, 1);
	mask.fill(0);
	//draw the circle of chosen area
	for (i = 0, j = Points.size() - 1; i < Points.size(); j = i++){
		DrawLine(mask, Points[j].x, Points[j].y, Points[i].x, Points[i].y);
	}
	//draw the mask
	//find a point in the circle
	//缩小计算范围
	for (std::vector<MYPOINT>::iterator it = Points.begin(); it != Points.end(); it++){
		x0 = x0 < (*it).x ? x0 : (*it).x;
		y0 = y0 < (*it).y ? y0 : (*it).y;
		x1 = x1 > (*it).x ? x1 : (*it).x;
		y1 = y1 > (*it).y ? y1 : (*it).y;
	}
	MYPOINT p(x0, (y1+y0)/2);
	//while (!JudgePoint(p, Points) && p.y <= y1){
	//	p.x = (p.x + 1) % (x1 + 1) + x0;
	//	if (p.x == x0) p.y++;
	//}
	int c = 0, tmp_x = Points[0].x, tmp_y = Points[0].y;
	while (p.y <= y1){
		if (mask.atXY(p.x, p.y) == 255) {
			if (c == 0){
				tmp_x = p.x + 1; tmp_y = p.y;
			}
			c++;
		}
		if (c == 2){
			if (mask.atXY(tmp_x, tmp_y) == 0 && tmp_y == p.y && tmp_x < p.x)
				break;
		}
		p.x = (p.x + 1) % (x1 + 1) + x0;
		if (p.x == x0){
			p.y++; c = 0;
		}
	}
	p.x = tmp_x; p.y = tmp_y;
	//std::cout << x0 << " " << y0 << std::endl;
	//std::cout << tmp_x << " " << tmp_y << std::endl;
	std::vector<MYPOINT> stack;
	stack.push_back(p);
	MYPOINT Cur = p, Las;
	while (stack.size()){
		mask.atXY(Cur.x, Cur.y) = 255;
		
		if (Cur.x + 1 < origin.width() && mask.atXY(Cur.x + 1, Cur.y) == 0){
			Cur.x += 1; stack.push_back(Cur); continue;
		}
		if (Cur.y + 1 < origin.height() && mask.atXY(Cur.x, Cur.y +1 ) == 0){
			Cur.y += 1; stack.push_back(Cur); continue;
		}
		if (Cur.x - 1 > -1 && mask.atXY(Cur.x - 1, Cur.y) == 0){
			Cur.x -= 1; stack.push_back(Cur); continue;
		}
		if (Cur.y - 1 > -1 && mask.atXY(Cur.x, Cur.y - 1) == 0){
			Cur.y -= 1; stack.push_back(Cur); continue;
		}
		stack.pop_back();
		if (stack.size()){
			Cur.x = stack.back().x;
			Cur.y = stack.back().y;
		}
	}
	return mask;
}