void OutputGradientViz(const string& filename,
												 const ImageRGB<byte>& image) const {
		const int& w = image.GetWidth();
		const int& h = image.GetHeight();

		// Draw segment boundaries
		ImageRGB<byte> canvas;
		const MatI& segmap = segmentation;
		ImageCopy(image, canvas);
		for (int r = 0; r < h; r++) {
			for (int c = 0; c < w; c++) {
				if (distxform.dists[r][c] == 0) {
					canvas[r][c] = BrightColors::Get(segmap[r][c]);
				}
			}
		}

		// Draw segment orientation
		for (int i = 0; i < num_segments; i++) {
			if (seg_sizes[i] > 40) {
				const double norm = 10.0 / sqrt(seg_dx[i]*seg_dx[i] + seg_dy[i]*seg_dy[i]);
				Vector<2> a = makeVector(seg_x[i], seg_y[i]);
				Vector<2> b = makeVector(seg_x[i]+seg_dx[i]*norm, seg_y[i]+seg_dy[i]*norm);
				DrawSpot(canvas, BrightColors::Get(i), a, 1);
				DrawLineClipped(canvas, a, b, BrightColors::Get(i));
			}
		}
		WriteImage("out/segorients.png", canvas);
	}
	void Compute(const ImageRGB<byte>& image, const ImageHSV<byte>& imagehsv) {
		const int& w = image.GetWidth();
		const int& h = image.GetHeight();

		feature_map.reset(new Table<2,VecD>(h, w));
		for (int r = 0; r < h; r++) {
			const PixelRGB<byte>* row = image[r];
			for (int c = 0; c < w; c++) {
				VecD& ftr = (*feature_map)(r, c);
				ftr.Resize(3);
				if (r > 0 && r < h-1 && c > 0 && c < w-1) {
					int i = 0;
					ftr[i++] = imagehsv[r][c].h;
					ftr[i++] = imagehsv[r][c].s;
					ftr[i++] = imagehsv[r][c].v;
					/*ftr[i++] = imagehsv[r-1][c-1].v - ftr[1];
					ftr[i++] = imagehsv[r-1][c].v - ftr[1];
					ftr[i++] = imagehsv[r-1][c+1].v - ftr[1];
					ftr[i++] = imagehsv[r][c-1].v - ftr[1];
					ftr[i++] = imagehsv[r][c+1].v - ftr[1];
					ftr[i++] = imagehsv[r+1][c-1].v - ftr[1];
					ftr[i++] = imagehsv[r+1][c].v - ftr[1];
					ftr[i++] = imagehsv[r+1][c+1].v - ftr[1];*/
				} else {
					ftr.Fill(0);
				}

				features.push_back(ftr);
			}
		}
	}
	void Compute(const ImageRGB<byte>& imagergb,
							 const ImageHSV<byte>& imagehsv,
							 const MatI& seg,
							 int num_segments) {
		const int& w = imagergb.GetWidth();
		const int& h = imagergb.GetHeight();
		// Compute pixel features
		pixel_ftrs.Compute(imagergb, imagehsv);

		// Build histograms over labels for each segment
		hists.Resize(num_segments, pixel_ftrs.label_map.MaxValue()+1);
		hists.Fill(0);
		for (int r = 0; r < h; r++) {
			const int* labelrow = pixel_ftrs.label_map[r];
			const int* segrow = seg[r];
			for (int c = 0; c < w; c++) {
				hists[ segrow[c] ][ labelrow[c] ]++;
			}
		}

		// Normalize the histograms
		features.resize(num_segments);
		for (int i = 0; i < num_segments; i++) {
			features[i] = hists.GetRow(i);
			features[i] /= features[i].Sum();
		}
	}
	void Compute(const ImageRGB<byte>& image, const ImageHSV<byte>& imagehsv) {
		const int& w = image.GetWidth();
		const int& h = image.GetHeight();
		label_map.Resize(h, w);

		// Compute pixel-wise features
		pixel_ftrs.Compute(image, imagehsv);

		// Run K-means to generate textons
		vector<VecD> points;
		const vector<VecD>& ftrs = pixel_ftrs.features;
		random_sample_n(ftrs.begin(), ftrs.end(), back_inserter(points), 5000);
		VecI labels(points.size());
		KMeans::Estimate(points, 20, textons, labels);

		// Label the pixels
		for (int r = 0; r < h; r++) {
			for (int c = 0; c < w; c++) {
				const VecD& ftr = (*pixel_ftrs.feature_map)(r, c);
				double mindist = INFINITY;
				for (int i = 0; i < textons.size(); i++) {
					const double dist = VectorSSD(textons[i], ftr);
					if (dist < mindist) {
						mindist = dist;
						label_map[r][c] = i;
					}
				}
			}
		}
	}
	// Minimal mock of VW imageio routines
	void ReadImage(const std::string& file, ImageRGB<byte>& image) {
		CHECK_PRED1(fs::exists, file);
		bool jpeg = IsJpegFilename(file);

		// Get size
		point2<ptrdiff_t> size;
		if (jpeg) {
			size = jpeg_read_dimensions(file);
		} else {
			size = png_read_dimensions(file);
		}

		// Allocate image data
		image.AllocImageData(size.x, size.y);
		rgba8_view_t v = interleaved_view(image.GetWidth(),
																			image.GetHeight(),
																			(rgba8_pixel_t*)image.GetImageBuffer(),
																			image.GetWidth()*sizeof(PixelRGB<byte>));

		// Load the image
		if (jpeg) {
			jpeg_read_and_convert_view(file, v);
		} else {
			png_read_and_convert_view(file, v);
		}

		// GIL uses 255=opaque but we use 0=opaque
		InvertAlpha(image);
	}
Example #6
0
static std::pair<bool, String> save_png_gdiplus(const Path &filename, const ImageRGB &img)
{
	// gdi+ does not support URIs
	Path winname(filename);
	winname.ToWindows();
	const auto newsize = winname.Size() + 1;
	auto wcstring = std::vector<wchar_t>(newsize);
	auto convertedChars = size_t(0);
	mbstowcs_s(&convertedChars, wcstring.data(), newsize, winname.CStr(), _TRUNCATE);

	Gdiplus::Bitmap *outbm = new Gdiplus::Bitmap(INT(img.GetWidth()), INT(img.GetHeight()), PixelFormat24bppRGB);
	if (!outbm)
	{
		return std::make_pair(false, String(_("Cannot create bitmap")));
	}
	Gdiplus::BitmapData bitmapData;
	auto clip = Gdiplus::Rect(0, 0, outbm->GetWidth(), outbm->GetHeight());
	outbm->LockBits(&clip, Gdiplus::ImageLockModeWrite, PixelFormat24bppRGB, &bitmapData);
	auto *pixels = (uint8_t*)bitmapData.Scan0;
//#pragma omp parallel for
	FOREACHPIXEL(x, y, img)
	{
		size_t poffset = 3 * x + y * bitmapData.Stride;
		const auto &pix = img.At(x, y);
		pixels[poffset + 2] = pix.r;
		pixels[poffset + 1] = pix.g;
		pixels[poffset] = pix.b;
	}
	// Invert alpha channel in an RGB image
	void InvertAlpha(ImageRGB<byte>& image) {
		for (int y = 0; y < image.GetHeight(); y++) {
			PixelRGB<byte>* row = image[y];
			for (int x = 0; x < image.GetWidth(); x++) {
				row[x].alpha = 255-row[x].alpha;
			}
		}
	}
	void Compute(const ImageRGB<byte>& image,
							 const ImageHSV<byte>& imagehsv) {
		const int kNumBins = 5;
		const int& w = image.GetWidth();
		const int& h = image.GetHeight();
		label_map.Resize(h, w);
		for (int r = 0; r < h; r++) {
			for (int c = 0; c < w; c++) {
				label_map[r][c] = static_cast<int>
					(imagehsv[r][c].h * kNumBins / 256);
			}
		}
	}
Example #9
0
void init()
{
	std::string infile("images//distance.bmp");
	ImageRGB rgb = Imread(infile);
	width = rgb.GetWidth();
	height = rgb.GetHeight();
	pixelData = GetGLPixelData(rgb);

	glClearColor(0.0, 0.0, 0.0, 0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, width, 0.0, height);
}
Example #10
0
	void Compute(const ImageRGB<byte>& imagergb,
							 const MatI& seg,
							 int num_segs) {
		const int& w = imagergb.GetWidth();
		const int& h = imagergb.GetHeight();
		segmentation = seg;
		num_segments = num_segs;
		
		// Compute gradients
		ImageCopy(imagergb, imagemono);
		gradients.Compute(imagemono);
		distxform.Compute(seg);

		// Compute average gradient in each segment
		mask.Resize(h, w);
		mask.Fill(0);
		seg_x.Resize(num_segments, 0.0);
		seg_y.Resize(num_segments, 0.0);
		seg_dx.Resize(num_segments, 0.0);
		seg_dy.Resize(num_segments, 0.0);
		seg_sizes.Resize(num_segments, 0);
		for (int r = 0; r < h; r++) {
			const int* segrow = seg[r];
			const PixelF* dxrow = gradients.diffx[r];
			const PixelF* dyrow = gradients.diffy[r];
			const int* distrow = distxform.dists[r];
			for (int c = 0; c < w; c++) {
				if (distrow[c] >= 2) {
					const int seg = segrow[c];
					seg_x[seg] += c;
					seg_y[seg] += r;
					seg_dx[seg] += dxrow[c].y;  // "y" just means the value of the pixel
					seg_dy[seg] += dyrow[c].y;
					seg_sizes[seg]++;
					mask[r][c] = 1;
				}
			}
		}

		// Compose features and normalize
		features.resize(num_segments);
		for (int i = 0; i < num_segments; i++) {
			if (seg_sizes[i] > 0) {
				seg_x[i] /= seg_sizes[i];
				seg_y[i] /= seg_sizes[i];
				seg_dx[i] /= seg_sizes[i];
				seg_dy[i] /= seg_sizes[i];
			}
			features[i] = MakeVector<2,float>(seg_dx[i], seg_dy[i]);
		}
	}
	void WriteImage(const std::string& file, const ImageRGB<byte>& image) {
		rgba8c_view_t v = interleaved_view(image.GetWidth(),
																			 image.GetHeight(),
																			 (const rgba8_pixel_t*)image.GetImageBuffer(),
																			 image.GetWidth()*sizeof(PixelRGB<byte>));
		// Here we use a hack to work around the fact that GIL uses
		// 255=opaque but we use 0=opaque
		InvertAlpha(const_cast<ImageRGB<byte>&>(image));
		if (IsJpegFilename(file)) {
			CHECK(false) << "jpeg output not supported";
			//jpeg_write_view(file, v);
		} else {
			png_write_view(file, v);
		}
		InvertAlpha(const_cast<ImageRGB<byte>&>(image));
	}
Example #12
0
static std::pair<bool, String> save_png_gdkpixbuf(const Path &fname, const ImageRGB &img)
{
	GdkPixbuf *pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 
			int(img.GetWidth()), int(img.GetHeight()));
	if (!pb)
	{
		return std::make_pair(false, String(_("Cannot create temporary buffer.")));
	}

	int w = gdk_pixbuf_get_width(pb);
	int h = gdk_pixbuf_get_height(pb);
	int rs = gdk_pixbuf_get_rowstride(pb);
	guchar *ppix = gdk_pixbuf_get_pixels(pb);
	for (int y = 0; y < h; y++)
		for (int x = 0; x < w; x++)
		{
			const auto px = img.At(x, y);
			int o2 = x + x + x + y * rs;
			ppix[o2] = px.r;
			ppix[o2 + 1] = px.g;
			ppix[o2 + 2] = px.b;
		}

	GError *err = NULL;
	gchar *utfname;
	gsize i;
	utfname = g_locale_to_utf8(fname.CStr(), -1, NULL, &i, NULL);
	gchar *filename;
	filename = g_filename_from_utf8(utfname, -1, NULL, &i, NULL);
	g_free(utfname);
	gchar *tinfo = g_locale_to_utf8("tEXt::Source", -1, NULL, &i, NULL);
	gchar *tinfo2 = g_locale_to_utf8("Saved by libcrn.", -1, NULL, &i, NULL);
	bool ok = gdk_pixbuf_save(pb, filename, "png", &err, tinfo, tinfo2, NULL); 
	g_free(filename);
	g_free(tinfo);
	g_free(tinfo2);
	g_object_unref(pb);
	String out(U"");
	if (!ok)
	{
		out = String(_("Cannot save file. ")) + err->message;
		g_error_free(err);
	}
	return std::make_pair(ok, out);
}
Example #13
0
static std::pair<bool, String> save_png_libpng(const Path &filename, const ImageRGB &img)
{
	// libpng does not support URIs
	Path fname(filename);
	fname.ToLocal();

	std::unique_ptr<FILE, decltype(fclose_if_not_null)*> fp(fopen(fname.CStr(), "wb"), fclose_if_not_null);
	if (!fp)
	{
		return std::make_pair(false, String(_("Cannot create file ")) + U"<" + fname + U">");
	}

	/* Create png struct & info */
	png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr)
	{
		return std::make_pair(false, String(_("Cannot create the PNG structure.")));
	}
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		return std::make_pair(false, String(_("Cannot create the PNG info.")));
	}

	/* Set up the error handling */
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return std::make_pair(false, String(_("Error while generating the PNG image.")));
	}

	/* setup libpng for using standard C fwrite() function with our FILE pointer */
	png_init_io(png_ptr, fp.get());

	/* Fill in the png_info structure */
	int width = int(img.GetWidth());
	int height = int(img.GetHeight());
	int bit_depth = 8;
	int color_type = PNG_COLOR_TYPE_RGB;
	int interlace_type = PNG_INTERLACE_NONE;
	int compression_type = PNG_COMPRESSION_TYPE_DEFAULT;
	int filter_method = PNG_FILTER_TYPE_DEFAULT;
	png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_type, compression_type, filter_method);

	/* Using the low-level write interface */
	png_write_info(png_ptr, info_ptr);
	png_bytepp row_pointers;
	row_pointers = (png_bytep*)malloc(sizeof(png_byte*) * height);
	for (int i = 0; i < height ; ++i)
	{
#if (PNG_LIBPNG_VER > 10300)
		row_pointers[i] = (png_bytep)calloc(1, png_get_rowbytes(png_ptr, info_ptr));
#else
		row_pointers[i] = (png_bytep)calloc(1, info_ptr->rowbytes);
#endif
	}

	/* Conversion */
#if (PNG_LIBPNG_VER > 10300)
	int channels = png_get_channels(png_ptr, info_ptr);
#else
	int channels = info_ptr->channels;
#endif
	for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++)
		{
			const auto px = img.At(x, y);
			row_pointers[y][x * channels] = px.r;
			row_pointers[y][x * channels + 1] = px.g;
			row_pointers[y][x * channels + 2] = px.b;
		}

	png_write_image(png_ptr, row_pointers);

	// TODO more options
	png_text txt[1];
	txt[0].compression = PNG_TEXT_COMPRESSION_NONE;
	txt[0].key = (char*)"creator";
	txt[0].text = (char*)"libcrn";
	txt[0].text_length = strlen(txt[0].text);
	png_set_text(png_ptr, info_ptr, txt, 1);

	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	// free
	for (int i = 0; i < height ; ++i)
	{
		free(row_pointers[i]);
	}
	free(row_pointers);
	return std::make_pair(true, String(""));

}