Skip to main content

TensorFlow for Beginners

TensorFlow - Image Recognition for New Data Set

Tensorflow is an open source machine learning tool provided by Google. It provides various machine learning solutions.
Most prominent use for Tensorflow is Computer vision.

Here is a small post, about how you can do tensorflow training on your new image data set using python.
First Install tensorflow in your system using following command (using python pip)

sudo apt-get install python-pip python-dev #used for python 2.7

Then download the TensorFlow Inception model folder from https://github.com/tensorflow/models/tree/master/inception

Save your new Image data under a folder named Images.. Inside the folder group each class of images into each separate folder(with corresponding names)
Then change flowers_data.py in inception model according to your new data set

Places to change:

  def num_classes(self):

    """Returns the number of classes in the data set."""

    return 8    #change here depending on number of classes for images

  def num_examples_per_epoch(self):

    """Returns the number of examples in the data subset."""

    if self.subset == 'train':

      return 70   #change here.. depending on no of examples you can keep value for training

    if self.subset == 'validation':

      return 30    #change here.. depending on no of examples you can keep value for validation

then enter into python interpreter

run :

python flowers_train.py (give whole path to the file) eg. python /home/naima.v/ImageR/root/inception/inception/flowers_train.py

it will produce output showing accuracy for training, validation set etc.

Then two files are created in /tmp of your system named 'output_graph.pb' and 'output_labels.txt' . First file contains the new trained inception graph and second file lists all your classes in atext files.

Now we can use these two files in LabelImage.py given in tensorflow/examples/image_retraining to classify images. Provide the image path to be analysed. Since we are transfering the learning from inception model to new data set we should set output layer as 'final_result:0' . Now when we run lableimage.py we get output for the corresponding image.

If you want to implement this classification in Eclipse Java you can just integrate tensorflow as maven :

  <dependency>

  <groupId>org.tensorflow</groupId>

  <artifactId>tensorflow</artifactId>

  <version>1.2.1</version>

</dependency>

Then take LabelImage code from tensorflow repo . And use the model we trained using python api.

That is , after training using python take the output(graph and label.txt) and give path for new Image , set output layer as 'final_result:0' .Execute the code and then you can see the result.

The LabelImage Java code after the changes are given below :
Main changes are marked in red color.

public class LabelImage {
  private static void printUsage(PrintStream s) {
    final String url =
        "https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip";
    s.println(
        "Java program that uses a pre-trained Inception model (http://arxiv.org/abs/1512.00567)");
    s.println("to label JPEG images.");
    s.println("TensorFlow version: " + TensorFlow.version());
    s.println();
    s.println("Usage: label_image <model dir> <image file>");
    s.println();
    s.println("Where:");
    s.println("<model dir> is a directory containing the unzipped contents of the inception model");
    s.println("            (from " + url + ")");
    s.println("<image file> is the path to a JPEG image file");
  }

  public static void main(String[] args) {
   /* if (args.length != 2) {
      printUsage(System.err);
      System.exit(1);
    }*/
    String modelDir = "/home/naima.v/ImageR/new model";
    String imageFile = "/home/naima.v/ImageR/labels/images (17).jpeg";

    byte[] graphDef = readAllBytesOrExit(Paths.get(modelDir, "output_graph.pb"));
    List<String> labels =
        readAllLinesOrExit(Paths.get(modelDir, "output_labels.txt"));
    byte[] imageBytes = readAllBytesOrExit(Paths.get(imageFile));

    try (Tensor image = constructAndExecuteGraphToNormalizeImage(imageBytes)) {
      float[] labelProbabilities = executeInceptionGraph(graphDef, image);
      int bestLabelIdx = maxIndex(labelProbabilities);
      System.out.println(
          String.format(
              "BEST MATCH: %s (%.2f%% likely)",
              labels.get(bestLabelIdx), labelProbabilities[bestLabelIdx] * 100f));
    }
  }

  private static Tensor constructAndExecuteGraphToNormalizeImage(byte[] imageBytes) {
    try (Graph g = new Graph()) {
      GraphBuilder b = new GraphBuilder(g);
      // Some constants specific to the pre-trained model at:
      // https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
      //
      // - The model was trained with images scaled to 224x224 pixels.
      // - The colors, represented as R, G, B in 1-byte each were converted to
      //   float using (value - Mean)/Scale.
      final int H = 224;
      final int W = 224;
      final float mean = 117f;
      final float scale = 1f;

      // Since the graph is being constructed once per execution here, we can use a constant for the
      // input image. If the graph were to be re-used for multiple input images, a placeholder would
      // have been more appropriate.
      final Output input = b.constant("input", imageBytes);
      final Output output =
          b.div(
              b.sub(
                  b.resizeBilinear(
                      b.expandDims(
                          b.cast(b.decodeJpeg(input, 3), DataType.FLOAT),
                          b.constant("make_batch", 0)),
                      b.constant("size", new int[] {H, W})),
                  b.constant("mean", mean)),
              b.constant("scale", scale));
      try (Session s = new Session(g)) {
        return s.runner().fetch(output.op().name()).run().get(0);
      }
    }
  }

  private static float[] executeInceptionGraph(byte[] graphDef, Tensor image) {
    try (Graph g = new Graph()) {
      g.importGraphDef(graphDef);
      try (Session s = new Session(g);
          Tensor result = s.runner().feed("input", image).fetch("final_result:0").run().get(0)) {
        final long[] rshape = result.shape();
        if (result.numDimensions() != 2 || rshape[0] != 1) {
          throw new RuntimeException(
              String.format(
                  "Expected model to produce a [1 N] shaped tensor where N is the number of labels, instead it produced one with shape %s",
                  Arrays.toString(rshape)));
        }
        int nlabels = (int) rshape[1];
        return result.copyTo(new float[1][nlabels])[0];
      }
    }
  }

  private static int maxIndex(float[] probabilities) {
    int best = 0;
    for (int i = 1; i < probabilities.length; ++i) {
      if (probabilities[i] > probabilities[best]) {
        best = i;
      }
    }
    return best;
  }

  private static byte[] readAllBytesOrExit(Path path) {
    try {
      return Files.readAllBytes(path);
    } catch (IOException e) {
      System.err.println("Failed to read [" + path + "]: " + e.getMessage());
      System.exit(1);
    }
    return null;
  }

  private static List<String> readAllLinesOrExit(Path path) {
    try {
      return Files.readAllLines(path, Charset.forName("UTF-8"));
    } catch (IOException e) {
      System.err.println("Failed to read [" + path + "]: " + e.getMessage());
      System.exit(0);
    }
    return null;
  }

  // In the fullness of time, equivalents of the methods of this class should be auto-generated from
  // the OpDefs linked into libtensorflow_jni.so. That would match what is done in other languages
  // like Python, C++ and Go.
  static class GraphBuilder {
    GraphBuilder(Graph g) {
      this.g = g;
    }

    Output div(Output x, Output y) {
      return binaryOp("Div", x, y);
    }

    Output sub(Output x, Output y) {
      return binaryOp("Sub", x, y);
    }

    Output resizeBilinear(Output images, Output size) {
      return binaryOp("ResizeBilinear", images, size);
    }

    Output expandDims(Output input, Output dim) {
      return binaryOp("ExpandDims", input, dim);
    }

    Output cast(Output value, DataType dtype) {
      return g.opBuilder("Cast", "Cast").addInput(value).setAttr("DstT", dtype).build().output(0);
    }

    Output decodeJpeg(Output contents, long channels) {
      return g.opBuilder("DecodeJpeg", "DecodeJpeg")
          .addInput(contents)
          .setAttr("channels", channels)
          .build()
          .output(0);
    }

    Output constant(String name, Object value) {
      try (Tensor t = Tensor.create(value)) {
        return g.opBuilder("Const", name)
            .setAttr("dtype", t.dataType())
            .setAttr("value", t)
            .build()
            .output(0);
      }
    }

    private Output binaryOp(String type, Output in1, Output in2) {
      return g.opBuilder(type, type).addInput(in1).addInput(in2).build().output(0);
    }

    private Graph g;
  }
}

Comments

Post a Comment

Popular posts from this blog

Converting DICOM images into JPG Format in Centos

Converting DICOM images into JPG Format in Centos I wanted to work with medical image classification using Deep learning. The Image data set was .dcm format. So to convert the images to jpg format following steps have performed. Used ImageMagick software. http://www.ofzenandcomputing.com/batch-convert-image-formats-imagemagick/ Installed ImageMagick in Centos by downloading the rom and installing its libraries : rpm -Uvh ImageMagick-libs-7.0.7-10.x86_64.rpm rpm -Uvh ImageMagick-7.0.7-10.x86_64.rpm After installation the the image which is to be converted is pointed in directory. Inside the directory executed the command: mogrify -format jpg *.dcm Now dcm image is converted to JPG format.