Ejemplo n.º 1
0
void Slic::try_fill(int x, int y, int i,
	vector<bool>& mask, vector<bool>& visited,
	int xlo, int xhi, int ylo, int yhi, int cols_) {

	visited[i] = true;
	bool mask_val = mask[i];
	mask[i] = false;
	if (mask_val) {
		// go left
		int i_lef = linear_index(y, x - 1, cols_);
		if ((x > xlo) && (visited[i_lef] == false))
			try_fill(x - 1, y, i_lef, mask, visited, xlo, xhi, ylo, yhi, cols_);
		// go right
		int i_rig = linear_index(y, x + 1, cols_);
		if ((x < xhi) && (visited[i_rig] == false))
			try_fill(x + 1, y, i_rig, mask, visited, xlo, xhi, ylo, yhi, cols_);
		// go bottom
		int i_bot = linear_index(y + 1, x, cols_);
		if ((y < yhi) && (visited[i_bot] == false))
			try_fill(x, y + 1, i_bot, mask, visited, xlo, xhi, ylo, yhi, cols_);
		// go top
		int i_top = linear_index(y - 1, x, cols_);
		if ((y > ylo) && (visited[i_top] == false))
			try_fill(x, y - 1, i_top, mask, visited, xlo, xhi, ylo, yhi, cols_);
	}
}
Ejemplo n.º 2
0
void apply_dyt(float* out, const float* in, int rows, int cols, int chan) { 
    for (int r = 1; r < rows; ++r) { 
        int rp = r-1;
        for (int c = 0; c < cols; ++c) { 
            for (int k = 0; k < chan; ++k) { 
                int i1 = linear_index(r, c, k, cols, chan);
                int i2 = linear_index(rp, c, k, cols, chan);
                //! NOTICE THAT THIS IS '+=', rather than '='.
                //! YOU MUST RUN apply_dxt prior to running this function
                out[i1] += (in[i2] - in[i1]);
            }
        }
    }
    //
    int r = 0;
    int rp = rows-1;
    for (int c = 0; c < cols; ++c) { 
        for (int k = 0; k < chan; ++k) { 
            int i1 = linear_index(r, c, k, cols, chan);
            int i2 = linear_index(rp, c, k, cols, chan);
            //! NOTICE THAT THIS IS '+=', rather than '='.
            //! YOU MUST RUN apply_dxt prior to running this function
            out[i1] += (in[i2] - in[i1]);
        }
    }
}
Ejemplo n.º 3
0
/* The most naive implementation of warping (bilinear) */
void Slic::imresize(vector<unsigned char>& out,
	const vector<unsigned char>& img, int rows, int cols, int out_rows, int out_cols) {
	// this is needed to prevent floor/ceil returning the same value if xx is integer.
	float EPS = 1e-4;
	float xx, yy;  // location and flow directions
	float weight1, weight2, weight3, weight4;
	int nx0, nx1, ny0, ny1;  // neighboring location

	float scale = (float(out_rows) / float(rows) + float(out_cols) / float(cols)) / 2.0;
	if (out.size() != (size_t)out_rows*out_cols*chan) {
		out = vector<unsigned char>(out_rows*out_cols*chan);
	}

	float antiscale = 1.0 / scale;
	for (size_t r = 0; r < (size_t)out_rows; ++r) {
		for (size_t c = 0; c < (size_t)out_cols; ++c) {
			xx = (float)c*antiscale;
			yy = (float)r*antiscale;

			nx0 = floor(xx + EPS);
			nx1 = ceil(xx + EPS);
			ny0 = floor(yy + EPS);
			ny1 = ceil(yy + EPS);

			nx0 = min(max(nx0, 0), cols - 1);
			nx1 = min(max(nx1, 0), cols - 1);
			ny0 = min(max(ny0, 0), rows - 1);
			ny1 = min(max(ny1, 0), rows - 1);

			weight1 = (nx1 - xx)*(ny1 - yy);  // upper left
			weight2 = (xx - nx0)*(ny1 - yy);  // upper right
			weight3 = (nx1 - xx)*(yy - ny0);  // lower left
			weight4 = (xx - nx0)*(yy - ny0);  // lower right

			for (int k = 0; k < chan; ++k) {
				int i1 = linear_index(ny0, nx0, k, cols, chan);
				int i2 = linear_index(ny1, nx0, k, cols, chan);
				int i3 = linear_index(ny0, nx1, k, cols, chan);
				int i4 = linear_index(ny1, nx1, k, cols, chan);

				int i_out = linear_index(r, c, k, out_cols, chan);

				out[i_out] =
					weight1*img[i1] +
					weight2*img[i2] +
					weight3*img[i3] +
					weight4*img[i4];
			}
		}
	}
}
Ejemplo n.º 4
0
void Slic::reassign_neighbors(vector<bool>& mask,
	int cluster, int xlo, int xhi, int ylo, int yhi, int level) {
	int cols_ = cols[level];
	int rows_ = rows[level];
	vector<int> *assignments = &assignments_pyramid[level];
	vector<int> stack;
	stack.reserve(1000);
	// need to reassign pixels.
	for (int y = ylo; y <= yhi; ++y) {
		for (int x = xlo; x <= xhi; ++x) {
			int i = linear_index(y, x, cols_);
			if (!mask[i]) {
				continue;
			}
			else {
				mask[i] = false;
			}

			int neighbor = -1;

			int i_rig = linear_index(y, x + 1, cols_);
			int i_top = linear_index(y - 1, x, cols_);
			int i_bot = linear_index(y + 1, x, cols_);
			int i_lef = linear_index(y, x - 1, cols_);

			if (((*assignments)[i_lef] != cluster) && (x>0))
				neighbor = (*assignments)[i_lef];
			else if (((*assignments)[i_rig] != cluster) && (x<cols_))
				neighbor = (*assignments)[i_rig];
			else if (((*assignments)[i_top] != cluster) && (y>0))
				neighbor = (*assignments)[i_top];
			else if (((*assignments)[i_bot] != cluster) && (y<rows_))
				neighbor = (*assignments)[i_bot];
			if (neighbor >= 0) {
				// empty the stack...
				(*assignments)[i] = neighbor;
				while (!stack.empty()) {
					int s = stack[0];
					stack.erase(stack.begin());
					(*assignments)[s] = neighbor;
				}
			}
			else {
				// push pixel onto the stack...
				stack.push_back(i);
			}
		}
	}
}
Ejemplo n.º 5
0
void Slic::init_centers() {
	// initialized at the smallest/coarsest level.
#ifdef SLIC_DEBUG
	printf("Slic::init_centers()\n");
#endif
	centers = vector<cluster>(K);

	float step_x = float(cols[num_levels - 1]) / float(nx + 1.0);
	float step_y = float(rows[num_levels - 1]) / float(ny + 1.0);
	float offset_x = step_x / 2.0;
	float offset_y = step_y / 2.0;
	int cols_ = cols[num_levels - 1];
	vector<unsigned char>* data = &pyramid[num_levels - 1];

	int i = 0;
	if (chan == 3) {
		for (int x = 0; x<nx; ++x) {
			for (int y = 0; y<ny; ++y) {
				centers[i].x = (x)*step_x + offset_x;
				centers[i].y = (y)*step_y + offset_y;
				centers[i].rgb = vector<unsigned char>(3, 0);
				for (int u = 0; u<3; ++u) {
					int k = linear_index(y, x, u, cols_, 3);
					centers[i].rgb[u] = (*data)[k];
				}
				i++;
			}
		}
	}
	else {
		for (int x = 0; x<nx; ++x) {
			for (int y = 0; y<ny; ++y) {
				centers[i].x = x*step_x + offset_x;
				centers[i].y = y*step_y + offset_y;
				int k = linear_index(y, x, cols_);
				centers[i].gray = (*data)[k];
				i++;
			}
		}
	}
	// initialize to 'valid'
	for (int k = 0; i < K; ++i) {
		centers[k].valid = 1;
	}
}
Ejemplo n.º 6
0
void apply_dxt(float* out, const float* in, int rows, int cols, int chan) {
    for (int r = 0; r < rows; ++r) { 
        int c = 0;
        int cp = cols-1;
        for (int k = 0; k < chan; ++k) { 
            int i1 = linear_index(r, c, k, cols, chan);
            int i2 = linear_index(r, cp, k, cols, chan);
            out[i1] = (in[i2] - in[i1]);
        }
        for (int c = 1; c < cols; ++c) {
            cp = c - 1;
            for (int k = 0; k < chan; ++k) { 
                int i1 = linear_index(r, c, k, cols, chan);
                int i2 = linear_index(r, cp, k, cols, chan);
                out[i1] = (in[i2] - in[i1]);
            }
        }
    }
}
Ejemplo n.º 7
0
void apply_dx(float* out, const float* in, int rows, int cols, int chan) { 
    for (int r = 0; r < rows; ++r) {
        for (int c = 0; c < cols-1; ++c) {
            int cn = c + 1;
            for (int k = 0; k < chan; ++k) {
                int i1 = linear_index(r, c, k, cols, chan);
                int i2 = linear_index(r, cn, k, cols, chan);
                out[i1] = in[i2] - in[i1];
            }
        }
        //
        int c = cols-1;
        int cn = 0;
        for (int k = 0; k < chan; ++k) { 
            int i1 = linear_index(r, c, k, cols, chan);
            int i2 = linear_index(r, cn, k, cols, chan);
            out[i1] = in[i2] - in[i1];
        }
    }
}
Ejemplo n.º 8
0
// ! Returns an RGB image with highlighted superpixel boundaries
vector<unsigned char> Slic::get_boundary_image(
	const vector<unsigned char>& rgb_data, int level) {
	int rows_ = rows[level];
	int cols_ = cols[level];
	vector<int> *assignments = &assignments_pyramid[level];

	int k, k_left = 0, k_right = 0, k_bottom = 0, k_top = 0;
	float w;
	vector<unsigned char> img = vector<unsigned char>(rows_*cols_*chan);
	for (int c = 0; c<cols_; ++c) {
		for (int r = 0; r<rows_; ++r) {
			int i = linear_index(r, c, cols_);
			k = (*assignments)[i];
			if (c>0) {
				k_left = (*assignments)[linear_index(r, c - 1, cols_)];
			}
			else { k_left = -1; }
			if (c < cols_ - 1) {
				k_right = (*assignments)[linear_index(r, c + 1, cols_)];
			}
			else { k_right = -1; }
			if (r>0) {
				k_top = (*assignments)[linear_index(r - 1, c, cols_)];
			}
			else { k_top = -1; }
			if (r < rows_ - 1) {
				k_bottom = (*assignments)[linear_index(r + 1, c, cols_)];
			}
			else { k_bottom = -1; }

			w = ((float)(k == k_right) + (float)(k == k_left) +
				(float)(k == k_bottom) + (float)(k == k_top)) / 4.0;
			if (chan == 3) {
				for (int u = 0; u < 3; ++u) {
					i = linear_index(r, c, u, cols_, 3);
					img[i] = rgb_data[i] * w;
				}
			}
			else {
				img[i] = rgb_data[i] * w;
			}
		}
	}
	return img;
}
Ejemplo n.º 9
0
void Slic::upsample_assignments(int level) {
#ifdef SLIC_DEBUG
	unsigned long t1, t2;
	t1 = now_us();
	printf("Slic::upsample_assignments ");
#endif
	// level is the current level.
	if (level == 0) { printf("Should not be called with this argument!\n"); }
	vector<int> *assignments = &assignments_pyramid[level];
	vector<int> *assignments_out = &assignments_pyramid[level - 1];
	vector<unsigned char> *data = &pyramid[level - 1];
	int rows_ = rows[level];
	int cols_ = cols[level];
	int rows_big = rows[level - 1];
	int cols_big = cols[level - 1];

	float EPS = 1e-4;
	float xx, yy;  // location and flow directions
	int nx0, nx1, ny0, ny1;  // neighboring location
	int i1, i2, i3, i4, i_out, i_;
	int ass1, ass2, ass3, ass4, temp;
	int d1, d2, d3, d4;

	float scale = (float(rows_big) / float(rows_) + float(cols_big) / float(cols_)) / 2.0;
	float antiscale = 1.0 / scale;
	int Mp = get_distance_weight(level - 1);
	for (size_t r = 0; r < (size_t)rows_big; ++r) {
		for (size_t c = 0; c < (size_t)cols_big; ++c) {
			xx = (float)c*antiscale;
			yy = (float)r*antiscale;

			nx0 = floor(xx + EPS);
			nx1 = ceil(xx + EPS);
			ny0 = floor(yy + EPS);
			ny1 = ceil(yy + EPS);

			nx0 = min(max(nx0, 0), cols_ - 1);
			nx1 = min(max(nx1, 0), cols_ - 1);
			ny0 = min(max(ny0, 0), rows_ - 1);
			ny1 = min(max(ny1, 0), rows_ - 1);

			i1 = linear_index(ny0, nx0, cols_);
			i2 = linear_index(ny1, nx0, cols_);
			i3 = linear_index(ny0, nx1, cols_);
			i4 = linear_index(ny1, nx1, cols_);
			i_out = linear_index(r, c, cols_big);

			ass1 = (*assignments)[i1];
			ass2 = (*assignments)[i2];
			ass3 = (*assignments)[i3];
			ass4 = (*assignments)[i4];

			if ((ass1 == ass2) && (ass2 == ass3) && (ass3 == ass4)) {
				// we are on the interior of the superpixel (whew)
				(*assignments_out)[i_out] = ass1;
			}
			else {
				d1 = d2 = d3 = d4 = 0;
				for (int k = 0; k < chan; ++k) {
					i_ = linear_index(r, c, k, cols_big, chan);
					temp = (*data)[i_] - centers[ass1].rgb[k];
					d1 += temp*temp;
					temp = (*data)[i_] - centers[ass2].rgb[k];
					d2 += temp*temp;
					temp = (*data)[i_] - centers[ass3].rgb[k];
					d3 += temp*temp;
					temp = (*data)[i_] - centers[ass4].rgb[k];
					d4 += temp*temp;
				}
				temp = (r - centers[ass1].y)*(r - centers[ass1].y) +
					(c - centers[ass1].x)*(c - centers[ass1].x);
				d1 += Mp*temp;
				temp = (r - centers[ass2].y)*(r - centers[ass2].y) +
					(c - centers[ass2].x)*(c - centers[ass2].x);
				d2 += Mp*temp;
				temp = (r - centers[ass3].y)*(r - centers[ass3].y) +
					(c - centers[ass3].x)*(c - centers[ass3].x);
				d3 += Mp*temp;
				temp = (r - centers[ass4].y)*(r - centers[ass4].y) +
					(c - centers[ass4].x)*(c - centers[ass4].x);
				d4 += Mp*temp;

				if ((d1 <= d2) && (d1 <= d2) && (d1 <= d3)) {
					(*assignments_out)[i_out] = ass1;
				}
				else if ((d2 <= d1) && (d2 <= d3) && (d2 <= d4)) {
					(*assignments_out)[i_out] = ass2;
				}
				else if ((d3 <= d1) && (d3 <= d2) && (d3 <= d4)) {
					(*assignments_out)[i_out] = ass3;
				}
				else {
					(*assignments_out)[i_out] = ass4;
				}
			}
		}
	}

#ifdef SLIC_DEBUG
	t2 = now_us();
	printf("elapsed: %f\n", (t2 - t1) / 1000.0);
#endif
}
Ejemplo n.º 10
0
void Slic::ensure_contiguity(int level) {
#ifdef SLIC_DEBUG
	unsigned long t1, t2;
	t1 = now_us();
	printf("Slic::ensure_contiguity ");
#endif
	int rows_ = rows[level];
	int cols_ = cols[level];
	int search_region_x_ = search_region_x[level];
	int search_region_y_ = search_region_y[level];
	int n = rows_*cols_;
	vector<int> *assignments = &assignments_pyramid[level];

	vector<bool> mask = vector<bool>(n);
	vector<bool> visited = vector<bool>(n);
	for (int k = 0; k<K; ++k) {
		int xc = centers[k].x;
		int yc = centers[k].y;
		if ((xc < 0) || (yc < 0)) {
			continue;
		}

		int xlo = max(0, xc - search_region_x_);
		int xhi = min(cols_ - 1, xc + search_region_x_);
		int ylo = max(0, yc - search_region_y_);
		int yhi = min(rows_ - 1, yc + search_region_y_);
		// the actual extents of the superpixel.
		int xlosp = xc;
		int xhisp = xc;
		int ylosp = yc;
		int yhisp = yc;
		// by definition, no need to check outside search region.
		int nums = 0;
		int origin_x = -1;
		int origin_y = -1;
		int dist_to_origin = INT_MAX;
		// first check if the centroid (or its 4 nearest neighbors belong to 
		// this superpixel. if yes, great -- we will start at this location.
		// otherwise we need to find a point that belongs to this superpixel
		// while being close to the center (this would be necessary if the 
		// superpixel is U-shaped)
		int i = linear_index(yc, xc, cols_);
		if ((*assignments)[i] == k) {
			// yay!
			origin_x = xc;
			origin_y = yc;
			nums = 1;
		}
		else {
			for (int y = ylo; y <= yhi; ++y) {
				int ddy = (y - yc)*(y - yc);
				if (ddy > dist_to_origin) { continue; }
				for (int x = xlo; x <= xhi; ++x) {
					int i = linear_index(y, x, cols_);
					if ((*assignments)[i] == k) {
						int d = ddy + (x - xc)*(x - xc);
						if (d < dist_to_origin) {
							dist_to_origin = d;
							origin_x = x;
							origin_y = y;
						}
					}
				}
			}
		}

		for (int y = ylo; y <= yhi; ++y) {
			for (int x = xlo; x <= xhi; ++x) {
				int i = linear_index(y, x, cols_);
				visited[i] = false;
				mask[i] = ((*assignments)[i] == k);
				if (mask[i]) {
					nums++;
					xlosp = min(xlosp, x);
					ylosp = min(ylosp, y);
					xhisp = max(xhisp, x);
					yhisp = max(yhisp, y);
				}
			}
		}
		if (nums == 0) {
			//printf("No pixels associated with this superpixel");
			continue;
			// this is a can of worms, but it is handled later
		}
		// we know the point closest to center that belongs to this cluster,
		// so start here and try to 'unset' all the 'set' pixels in the mask.
		try_fill(origin_x, origin_y, linear_index(origin_y, origin_x, cols_),
			mask, visited, xlosp, xhisp, ylosp, yhisp, cols_);

		int num_left = 0;
		for (int y = ylosp; y <= yhisp; ++y) {
			for (int x = xlosp; x <= xhisp; ++x) {
				int i = linear_index(y, x, cols_);
				if (mask[i]) {
					num_left += 1;
					break;
				}
			}
			if (num_left > 0) { break; }
		}

		if (num_left > 0) {
			// assign the remaining pixels to neighboring clusters
			reassign_neighbors(mask, k, xlosp, xhisp, ylosp, yhisp, level);
		}
	}
#ifdef SLIC_DEBUG
	t2 = now_us();
	printf("elapsed: %f\n", double(t2 - t1) / 1000.0);
#endif
}
Ejemplo n.º 11
0
// SEEMS OK.
void Slic::update(int level) {
#ifdef SLIC_DEBUG
	printf("Slic::update ");
	unsigned long t1, t2;
	t1 = now_us();
#endif
	int rows_ = rows[level];
	int cols_ = cols[level];
	int search_region_x_ = search_region_x[level];
	int search_region_y_ = search_region_y[level];
	//int n = rows_*cols_;
	vector<unsigned char> *data = &pyramid[level];
	vector<int> *assignments = &assignments_pyramid[level];

	for (int k = 0; k<K; ++k) {
		int xc = centers[k].x;
		int yc = centers[k].y;

		int xlo = max(0, xc - search_region_x_);
		int xhi = min(cols_ - 1, xc + search_region_x_);
		int ylo = max(0, yc - search_region_y_);
		int yhi = min(rows_ - 1, yc + search_region_y_);

		if (chan == 3) {
			int r = 0;
			int g = 0;
			int b = 0;
			int px = 0;
			int py = 0;
			int nums = 0;
			for (int y = ylo; y <= yhi; ++y) {
				for (int x = xlo; x <= xhi; ++x) {
					int i = linear_index(y, x, cols_);
					if ((*assignments)[i] == k) {
						int q = linear_index(y, x, 0, cols_, 3);
						r += (int)(*data)[q + 0];
						g += (int)(*data)[q + 1];
						b += (int)(*data)[q + 2];
						px += x;
						py += y;
						nums++;
					}
				}
			}

			if (nums>0) {
				centers[k].x = px / nums;
				centers[k].y = py / nums;
				centers[k].rgb[0] = (unsigned char)(r / nums);
				centers[k].rgb[1] = (unsigned char)(g / nums);
				centers[k].rgb[2] = (unsigned char)(b / nums);
				centers[k].valid = 1;
			}
			else {
				centers[k].valid = 0;
			}
		}
		else {
			int r = 0;
			int px = 0;
			int py = 0;
			int nums = 0;
			for (int y = ylo; y <= yhi; ++y) {
				for (int x = xlo; x <= xhi; ++x) {
					int i = linear_index(y, x, cols_);
					if ((*assignments)[i] == k) {
						nums++;
						r += (int)(*data)[i];
						px += x;
						py += y;
					}
				}
			}
			if (nums>0) {
				centers[k].x = px / nums;
				centers[k].y = py / nums;
				centers[k].gray = (unsigned char)(r / nums);
				centers[k].valid = 1;
			}
			else {
				centers[k].valid = 0;
			}
		}
	}
#ifdef SLIC_DEBUG
	t2 = now_us();
	printf("elapsed: %f\n", double(t2 - t1) / 1000.0);
#endif
}
Ejemplo n.º 12
0
void Slic::assign(int level) {
#ifdef SLIC_DEBUG
	printf("Slic::assign ");
	unsigned long t1, t2;
	t1 = now_us();
#endif
	int rows_ = rows[level];
	int cols_ = cols[level];
	int search_region_x_ = search_region_x[level];
	int search_region_y_ = search_region_y[level];
	int n = rows_*cols_;
	vector<unsigned char> *data = &pyramid[level];
	vector<int> *assignments = &assignments_pyramid[level];
	int Mp = get_distance_weight(level);

	for (int i = 0; i < n; ++i) {
		(*assignments)[i] = 0;
	}
	for (int i = 0; i<n; ++i)
		d[i] = INT_MAX;
	for (int k = 0; k<K; ++k) {
		int xc = centers[k].x;
		int yc = centers[k].y;

		int xlo = max(0, xc - search_region_x_);
		int xhi = min(cols_ - 1, xc + search_region_x_);
		int ylo = max(0, yc - search_region_y_);
		int yhi = min(rows_ - 1, yc + search_region_y_);

		if (chan == 3) {
			int r = centers[k].rgb[0];
			int g = centers[k].rgb[1];
			int b = centers[k].rgb[2];
			for (int y = ylo; y <= yhi; ++y) {
				int ddy = Mp*(y - yc)*(y - yc);
				for (int x = xlo; x <= xhi; ++x) {
					int i = linear_index(y, x, cols_);
					if (ddy >= d[i])
						continue;
					int dist = Mp*(x - xc)*(x - xc) + ddy;
					if (dist >= d[i])
						continue;
					int q = linear_index(y, x, 0, cols_, 3);
					int temp1 = ((int)(*data)[q + 0] - r);
					int temp2 = ((int)(*data)[q + 1] - g);
					int temp3 = ((int)(*data)[q + 2] - b);
					dist += (temp1*temp1 + temp2*temp2 + temp3*temp3);

					if (dist < d[i]) {
						d[i] = dist;
						(*assignments)[i] = k;
					}
				}
			}
		}
		else {
			int g = centers[k].gray;
			for (int y = ylo; y <= yhi; ++y) {
				int ddy = Mp*(y - yc)*(y - yc);
				for (int x = xlo; x <= xhi; ++x) {
					int i = linear_index(y, x, cols_);
					if (ddy >= d[i])
						continue;
					int dist = Mp*(x - xc)*(x - xc) + ddy;
					if (dist >= d[i])
						continue;
					int temp = ((int)(*data)[i] - g);
					dist += temp*temp;

					if (dist < d[i]) {
						d[i] = dist;
						(*assignments)[i] = k;
					}
				}
			}
		}
	}
#ifdef SLIC_DEBUG
	t2 = now_us();
	printf("elapsed: %f\n", double(t2 - t1) / 1000.0);
#endif
}
Ejemplo n.º 13
0
void Slic::adjust_centers() {
#ifdef SLIC_DEBUG
	printf("Slic::adjust_centers ");
	unsigned long t1, t2;
	t1 = now_us();
#endif
	vector<unsigned char>* data = &pyramid[num_levels - 1];
	int cols_ = cols[num_levels - 1];
	//int rows_ = rows[num_levels-1];
	for (int k = 0; k < K; ++k) {
		int x = centers[k].x;
		int y = centers[k].y;
		int i = 0;
		int min_val = INT_MAX;
		int best_x = x;
		int best_y = y;

		// boundary checks are not implemented because centers should be
		// initialized away from the image boundary in the first place!!           
		if (chan == 3) {
			// for rgb images
			for (int yy = y - 1; yy <= (y + 1); yy++) {
				for (int xx = x - 1; xx <= (x + 1); xx++) {
					float grad = 0.0;
					for (int u = 0; u<3; ++u) {
						int i_bot = linear_index(yy + 1, xx, u, cols_, 3);
						int i_top = linear_index(yy - 1, xx, u, cols_, 3);
						int i_lef = linear_index(yy, xx - 1, u, cols_, 3);
						int i_rig = linear_index(yy, xx + 1, u, cols_, 3);
						float v = (int)((*data)[i_bot] - (int)(*data)[i_top]);
						float h = (int)((*data)[i_lef] - (int)(*data)[i_rig]);
						grad += v*v + h*h;
					}
					if (grad < min_val) {
						min_val = grad;
						best_x = xx;
						best_y = yy;
					}
					i++;
				}
			}
			centers[k].x = best_x;
			centers[k].y = best_y;
		}
		else {
			// for grayscale images
			for (int yy = y - 1; yy <= (y + 1); yy++) {
				for (int xx = x - 1; xx <= (x + 1); xx++) {
					float grad = 0.0;
					int i_bot = linear_index(yy + 1, xx, cols_);
					int i_top = linear_index(yy - 1, xx, cols_);
					int i_lef = linear_index(yy, xx - 1, cols_);
					int i_rig = linear_index(yy, xx + 1, cols_);
					float v = (int)((*data)[i_bot] - (int)(*data)[i_top]);
					float h = (int)((*data)[i_lef] - (int)(*data)[i_rig]);
					grad += v*v + h*h;
					if (grad < min_val) {
						min_val = grad;
						best_x = xx;
						best_y = yy;
					}
					i++;
				}
			}
			centers[k].x = best_x;
			centers[k].y = best_y;
		}
	}
#ifdef SLIC_DEBUG
	t2 = now_us();
	printf("elapsed: %f\n", double(t2 - t1) / 1000.0);
#endif
}