image.cc

来自「用于计算矩阵的特征值,及矩阵的其他运算.可以用与稀疏矩阵」· CC 代码 · 共 1,083 行 · 第 1/3 页

CC
1,083
字号
// Copyright (C) 2002 Charless C. Fowlkes <fowlkes@eecs.berkeley.edu>// Copyright (C) 2002 David R. Martin <dmartin@eecs.berkeley.edu>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License as// published by the Free Software Foundation; either version 2 of the// License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful, but// WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU// General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA// 02111-1307, USA, or see http://www.gnu.org/copyleft/gpl.html.#include <iostream>#include <stdio.h>#include <math.h>#include <values.h>#include <assert.h>extern "C"{#include <jpeglib.h>#include <jerror.h>}#include "util.hh"#include "image.hh"#include "sort.hh"namespace Util{  //////////////////////////////////////////////////////////////////////////////////////////////////////  //  // read in a jpeg file into an ImageStack.   // if the jpeg file is grayscale then the resulting ImageStack only has 1 layer  // otherwise it has 3 layers corresponding to the RGB colorspace.  //  bool readJpegFile(const char *filename, ImageStack& im)  {      assert(filename != NULL);      int bytesPerPixel;      int height;      int width;      unsigned char* imbuf;      bool isGray;      FILE* file = fopen(filename, "r");      if (!file)      {        return (false);      }      jpeg_decompress_struct cinfo;      jpeg_error_mgr jerr;      cinfo.err = jpeg_std_error (&jerr);      jpeg_create_decompress (&cinfo);      jpeg_stdio_src (&cinfo, file);      jpeg_read_header (&cinfo, (boolean) true);      if (cinfo.out_color_space == JCS_GRAYSCALE)      {          isGray = true;          cinfo.output_components = 1;          bytesPerPixel = 1;      }      else      {          isGray = false;          cinfo.out_color_space = JCS_RGB;          cinfo.output_components = 3;          bytesPerPixel = 3;      }      jpeg_calc_output_dimensions (&cinfo);      jpeg_start_decompress (&cinfo);      height = cinfo.output_height;      width = cinfo.output_width;      imbuf = new unsigned char[width * height * bytesPerPixel];      const int lineSize = width * bytesPerPixel;      unsigned char* p = imbuf;      while (cinfo.output_scanline < cinfo.output_height)      {        jpeg_read_scanlines (&cinfo, &p, 1);        p += lineSize;      }      jpeg_finish_decompress (&cinfo);      jpeg_destroy_decompress (&cinfo);      fclose (file);      //now fill in our image array data structure      if (isGray)      {        im.resize(1,width,height);        for (int i = 0; i < width * height; i++)        {          const float gray = (float) imbuf[i] / 255;          const int y = i / width;          const int x = i % width;          im(0,x,y) = gray;          // this fails on fp type errors:  assert (gray >= 0 && gray <= 1);        }      }      else      {        im.resize(3,width,height);        for (int i = 0; i < width * height; i++)        {          const int y = i / width;          const int x = i % width;          float r = (float) imbuf[3 * i] / 255;          float g = (float) imbuf[3 * i + 1] / 255;          float b = (float) imbuf[3 * i + 2] / 255;          if ((r < 0) || (r > 1))          {            std::cerr << "r = " << r << std::endl;          }          if ((g < 0) || (g > 1))          {            std::cerr << "g = " << g << std::endl;          }          if ((b < 0) || (b > 1))          {            std::cerr << "b = " << r << std::endl;          }          assert (r >= 0 && r <= 1);          assert (g >= 0 && g <= 1);          assert (b >= 0 && b <= 1);          im(RGB_R,x,y) = r;          im(RGB_G,x,y) = g;          im(RGB_B,x,y) = b;        }      }      delete[] imbuf;      return true;  }  //////////////////////////////////////////////////////////////////////////////////////////////////////  //  // used for writing out a single channel image with  // the "jet" psuedo-color map  //  static int jetR (float v)  {    assert (v >= 0 && v <= 1);    int i = (uint) rint (v * 255);    return Util::minmax (0, (450 - 5 * abs (i - 196)), 255);  }  static int jetG (float v)  {    assert (v >= 0 && v <= 1);    int i = (uint) rint (v * 255);    return Util::minmax (0, (450 - 5 * abs (i - 128)), 255);  }  static int jetB (float v)  {      assert (v >= 0 && v <= 1);      int i = (uint) rint (v * 255);      return Util::minmax (0, (450 - 5 * abs (i - 64)), 255);  }  //  // create a normalized version of this image.  // first run thru and find the min and max values  // and then create a new image whose values range   // over [0.0,1.0].  the constant image is set to 0.0  //  // used in the Jpeg reading and writing.  //  static void getNormalized(const Image& im, Image& normalized)   {      int width = im.size(1);      int height = im.size(0);      normalized.resize(width,height);      float max = im(0,0);      float min = im(0,0);      for (int i = 0; i < width; i++)      {        for (int j = 0; j < height; j++)        {          float val = im(i,j);          max = Util::max(max, val);          min = Util::min(min, val);        }      }      if ((max - min) > 0)      {        normalized = (im - min) / (max - min);      }      else      {        normalized.init(0);      }  }  //  // write out a grayscale image to a jpeg file.  // if normalize=true, then the range of the image is adjusted to use the full scale  // if jet=true then the image is written in pseudocolor rather than grayscale  //  bool writeJpegFile(const Image& im, const char *filespec, const bool normalize, const bool jet)  {      assert(filespec != NULL);      //normalized version of this image      Image normim;      if (normalize)      {        getNormalized(im,normim);       }      else      {        normim = im;      }      struct jpeg_error_mgr jerr;      struct jpeg_compress_struct cinfo;      // Open the output file.      FILE* file = Util::openOutputStrm (filespec);      if (!file)      {        return (false);      }      // Set up the normal JPEG error handling.      cinfo.err = jpeg_std_error (&jerr);      // Init a JPEG compression object.      jpeg_create_compress (&cinfo);      // Specify source of data.      jpeg_stdio_dest (&cinfo, file);      // Specify compression parameters.      cinfo.image_width = im.size(0);      cinfo.image_height = im.size(1);      cinfo.input_components = 3;      cinfo.in_color_space = JCS_RGB;      jpeg_set_defaults (&cinfo);      // Start compression.      jpeg_start_compress (&cinfo, TRUE);      // Allocate space for one scanline.      JSAMPLE* buf = new JSAMPLE[im.size(0) * 3];      // Write data one scanline at a time.      for (int y = 0; y < im.size(1); y++)      {        for (int x = 0; x < im.size(0); x++)        {          float v = normim(x,y);          assert (v >= 0 && v <= 1);          if (jet)          {              buf[3*x + 0] = jetR(v);              buf[3*x + 1] = jetG(v);              buf[3*x + 2] = jetB(v);          }          else          {              int g = (int)rint(255 * v);              buf[3*x + 0] = g;              buf[3*x + 1] = g;              buf[3*x + 2] = g;          }        }        int c = jpeg_write_scanlines (&cinfo, &buf, 1);        if (c != 1)        {          fclose (file);          jpeg_destroy_compress (&cinfo);          delete[]buf;          return false;        }      }      // Clean up.      jpeg_finish_compress (&cinfo);      fclose (file);      jpeg_destroy_compress (&cinfo);      delete[]buf;      return true;  }  //////////////////////////////////////////////////////////////////////////////////////////////////////  //  // convert an RGB imagestack into an 1976 CIE L*a*b* imagestack.  //  void rgb2lab (const ImageStack& rgb, ImageStack& lab)  {      assert(rgb.size(0) == 3);      const int w = rgb.size(1);      const int h = rgb.size(2);      lab.resize(3,w,h);      for (int i = 0; i < w; i++)      {        for (int j = 0; j < h; j++)        {            // RGB            const float R = rgb(RGB_R,i,j);            const float G = rgb(RGB_G,i,j);            const float B = rgb(RGB_B,i,j);            assert (R >= 0 && R <= 1);            assert (G >= 0 && G <= 1);            assert (B >= 0 && B <= 1);            // RGB --> XYZ            const float X = 0.412453 * R + 0.357580 * G + 0.180423 * B;            const float Y = 0.212671 * R + 0.715160 * G + 0.072169 * B;            const float Z = 0.019334 * R + 0.119193 * G + 0.950227 * B;            // XYZ of D65 reference white (R=G=B=1).            const float Xn = 0.950456;            const float Yn = 1.000000;            const float Zn = 1.088754;            // XYZ --> 1976 CIE L*a*b*            const float rX = X / Xn;            const float rY = Y / Yn;            const float rZ = Z / Zn;            const float thresh = 0.008856;#define f(t) (t > thresh) ? pow(t,1./3.) : (7.787 * t + 16./116.)            const float fX = f(rX);            const float fY = f(rY);            const float fZ = f(rZ);#undef f            const float L = (rY > thresh) ? 116. * pow (rY, 1. / 3.) - 16. : 903.3 * rY;            const float a = 500. * (fX - fY);            const float b = 200. * (fY - fZ);            assert (L >= 0 && L <= 100);            assert (a >= -120 && a <= 120);            assert (b >= -120 && b <= 120);            lab(LAB_L,i,j) = L;            lab(LAB_A,i,j) = a;            lab(LAB_B,i,j) = b;        }      }  }  //////////////////////////////////////////////////////////////////////////////////////////////////////  //  // normalize an lab image so that values lie in [0,1]  //

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?