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;
			}
		}
	}
}
Beispiel #2
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;
}
//找最大的团并返回外轮廓
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;

};
/**
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);
		}
	}
}
/**
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;
}