// 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); }
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 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>& 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; } } } } }
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)); }
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 Draw(ImageRGB<byte>& canvas, const PixelRGB<byte>& color) const { const int nx = canvas.GetWidth(); const int ny = canvas.GetWidth(); const float theta = theta; const float rho = rho; canvas.SetPenColour(color); canvas.DrawLine(start[0], start[1], end[0], end[1]); }
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); } } }
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); }
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]); } }
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); }
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("")); }