You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@singa.apache.org by wa...@apache.org on 2016/06/23 13:38:17 UTC

[3/4] incubator-singa git commit: SINGA-200 - Implement Encoder and Decoder for data pre-processing

SINGA-200 - Implement Encoder and Decoder for data pre-processing

Add base class Encoder and Decoder.

Add inheritance class Image2JPG_Encoder and Image2JPG_Decoder, which uses opencv to encode and decode image source files.

Add test which contains partial pre-processing procedures (read_raw_image, encode, decode) for images.

Reader and Writer, which uses user specified offline store mechanisms (i.e., kvfile, lmdb, ...), are not implemented in this ticket.

Use random value initialized image for test.

Add derived encoder/decoder class definition in its base class head file (decoder.h/encoder.h).


Project: http://git-wip-us.apache.org/repos/asf/incubator-singa/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-singa/commit/13d60b03
Tree: http://git-wip-us.apache.org/repos/asf/incubator-singa/tree/13d60b03
Diff: http://git-wip-us.apache.org/repos/asf/incubator-singa/diff/13d60b03

Branch: refs/heads/dev
Commit: 13d60b034fe0b08f2fe128a8ad575d72e68001ea
Parents: 67ee3c5
Author: jixin <ji...@comp.nus.edu.sg>
Authored: Wed Jun 22 19:22:17 2016 +0800
Committer: jixin <ji...@comp.nus.edu.sg>
Committed: Thu Jun 23 17:20:38 2016 +0800

----------------------------------------------------------------------
 .gitignore                           |  1 +
 CMakeLists.txt                       |  2 +-
 include/singa/io/decoder.h           | 14 +++--
 include/singa/io/encoder.h           | 11 +++-
 include/singa/io/image2jpg_decoder.h | 40 --------------
 include/singa/io/image2jpg_encoder.h | 40 --------------
 src/CMakeLists.txt                   |  2 +-
 src/io/image2jpg_decoder.cc          | 54 -------------------
 src/io/image2jpg_encoder.cc          | 69 ------------------------
 src/io/jpg2proto_encoder.cc          | 70 +++++++++++++++++++++++++
 src/io/proto2jpg_decoder.cc          | 57 ++++++++++++++++++++
 src/proto/model.proto                | 28 ++++------
 test/singa/test_decoder.cc           | 87 +++++++++++++++++++++++++++++++
 test/singa/test_io.cc                | 65 -----------------------
 14 files changed, 247 insertions(+), 293 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index eaa2d84..221b3d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@
 build/
 thirdparty/*
 !thirdparty/install.sh
+test/samples/

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 46b6bfb..c61f8a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,7 +22,7 @@ INCLUDE_DIRECTORIES(${SINGA_INCLUDE_DIR})
 OPTION(USE_CBLAS "Use CBlas libs" ON)
 OPTION(USE_CUDA "Use Cuda libs" ON)
 OPTION(USE_CUDNN "Use Cudnn libs" ON)
-OPTION(USE_OPENCV "Use opencv" OFF)
+OPTION(USE_OPENCV "Use opencv" ON)
 OPTION(USE_LMDB "Use LMDB libs" OFF)
 OPTION(USE_PYTHON "Generate py wrappers" OFF)
 

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/include/singa/io/decoder.h
----------------------------------------------------------------------
diff --git a/include/singa/io/decoder.h b/include/singa/io/decoder.h
index 8330e34..003dd59 100644
--- a/include/singa/io/decoder.h
+++ b/include/singa/io/decoder.h
@@ -22,6 +22,7 @@
 #include <vector>
 #include <string>
 #include "singa/core/tensor.h"
+#include "singa/proto/model.pb.h"
 
 namespace singa {
 namespace io {
@@ -31,13 +32,18 @@ class Decoder {
     Decoder() { }
     virtual ~Decoder() { }
 
+    virtual void Setup(const DecoderConf& conf) = 0;
+
     /**
     * Decode value to get data and labels
     */
-    virtual std::vector<Tensor> Decode(std::string value) {
-      vector<Tensor> output;
-      return output; 
-    }
+    virtual std::vector<Tensor> Decode(std::string value) = 0;
+};
+
+class Proto2JPGDecoder : public Decoder {
+  public:
+    void Setup(const DecoderConf& conf) override;
+    std::vector<Tensor> Decode(std::string value) override;
 };
 
 } // namespace io

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/include/singa/io/encoder.h
----------------------------------------------------------------------
diff --git a/include/singa/io/encoder.h b/include/singa/io/encoder.h
index 66a2fe5..5a8dbeb 100644
--- a/include/singa/io/encoder.h
+++ b/include/singa/io/encoder.h
@@ -22,6 +22,7 @@
 #include <vector>
 #include <string>
 #include "singa/core/tensor.h"
+#include "singa/proto/model.pb.h"
 
 namespace singa {
 namespace io {
@@ -30,13 +31,21 @@ class Encoder {
   public:
     Encoder() { }
     virtual ~Encoder() { }
+    
+    virtual void Setup(const EncoderConf& conf) = 0;
 
     /**
      * Format each sample data as a string,
      * whose structure depends on the proto definition.
      * e.g., {key, shape, label, type, data, ...}
      */
-    virtual std::string Encode(vector<Tensor>& data) { return ""; }
+    virtual std::string Encode(vector<Tensor>& data) = 0;
+};
+
+class JPG2ProtoEncoder : public Encoder {
+  public:
+    void Setup(const EncoderConf& conf) override;
+    std::string Encode(vector<Tensor>& data) override;
 };
 
 } // namespace io

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/include/singa/io/image2jpg_decoder.h
----------------------------------------------------------------------
diff --git a/include/singa/io/image2jpg_decoder.h b/include/singa/io/image2jpg_decoder.h
deleted file mode 100644
index 6895c29..0000000
--- a/include/singa/io/image2jpg_decoder.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SINGA_IO_IMAGE2JPG_DECODER_H_
-#define SINGA_IO_IMAGE2JPG_DECODER_H_
-
-#include <vector>
-#include <string>
-#include "singa/core/tensor.h"
-#include "singa/io/decoder.h"
-#include "singa/proto/model.pb.h"
-#include <opencv2/highgui/highgui.hpp>
-#include <opencv2/imgproc/imgproc.hpp>
-
-namespace singa {
-namespace io {
-
-class Image2JPGDecoder : public Decoder {
-  public:
-    std::vector<Tensor> Decode(std::string value) override;
-};
-
-} // namespace io
-} // namespace singa
-#endif // SINGA_IO_IMAGE2JPG_DECODER_H_

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/include/singa/io/image2jpg_encoder.h
----------------------------------------------------------------------
diff --git a/include/singa/io/image2jpg_encoder.h b/include/singa/io/image2jpg_encoder.h
deleted file mode 100644
index 2e94b64..0000000
--- a/include/singa/io/image2jpg_encoder.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SINGA_IO_IMAGE2JPG_ENCODER_H_
-#define SINGA_IO_IMAGE2JPG_ENCODER_H_
-
-#include <vector>
-#include <string>
-#include "singa/core/tensor.h"
-#include "singa/io/encoder.h"
-#include "singa/proto/model.pb.h"
-#include <opencv2/highgui/highgui.hpp>
-#include <opencv2/imgproc/imgproc.hpp>
-
-namespace singa {
-namespace io {
-
-class Image2JPGEncoder : public Encoder {
-  public:
-  	 std::string Encode(vector<Tensor>& data) override;
-};
-
-} // namespace io
-} // namespace singa
-#endif  // SINGA_IO_IMAGE2JPG_ENCODER_H_

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/src/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 90343d5..e5970d8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -57,7 +57,7 @@ LIST(APPEND SINGA_LINKER_LIBS singa_model)
 
 AUX_SOURCE_DIRECTORY(io io_source)
 ADD_LIBRARY(singa_io SHARED ${io_source})
-TARGET_LINK_LIBRARIES(singa_io ${SINGA_LIBKER_LIBS})
+TARGET_LINK_LIBRARIES(singa_io ${SINGA_LINKER_LIBS})
 LIST(APPEND SINGA_LINKER_LIBS singa_io)
 
 #ADD_LIBRARY(singa_layer SHARED ${LAYER_SOURCE})

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/src/io/image2jpg_decoder.cc
----------------------------------------------------------------------
diff --git a/src/io/image2jpg_decoder.cc b/src/io/image2jpg_decoder.cc
deleted file mode 100644
index da0c909..0000000
--- a/src/io/image2jpg_decoder.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "singa/io/image2jpg_decoder.h"
-#include <vector>
-//#include <opencv2/core/core.hpp>
-//#include <opencv2/highgui/highgui.hpp>
-//#include "opencv2/opencv.hpp"
-
-using namespace cv;
-using namespace std;
-
-namespace singa {
-
-namespace io {
-  vector<Tensor> Image2JPGDecoder::Decode(string value) {
-    vector<Tensor> output;
-    RecordProto image;
-    image.ParseFromString(value);
-    Shape shape(image.shape().begin(), image.shape().end());
-    Tensor features(shape), labels(Shape{1});
-    
-    //string pixel = image.pixel();
-    vector<unsigned char> pixel(image.pixel().begin(), image.pixel().end());
-    Mat buff(shape[1], shape[2], CV_8UC3, pixel.data());
-    Mat mat = imdecode(buff, CV_LOAD_IMAGE_COLOR);
-    vector<int> data;
-    data.assign(mat.datastart, mat.dataend);
-    //for (size_t i = 0; i < image.pixel().size(); i++)
-    //  data[i] = static_cast<int>(static_cast<uint8_t>(pixel[i]));
-    features.CopyDataFromHostPtr<vector<int>>(&data, data.size());
-    int l[1] = {image.label()};
-    labels.CopyDataFromHostPtr(l, 1);
-    output.push_back(features);
-    output.push_back(labels);
-    return output;
-  }
-}
-}

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/src/io/image2jpg_encoder.cc
----------------------------------------------------------------------
diff --git a/src/io/image2jpg_encoder.cc b/src/io/image2jpg_encoder.cc
deleted file mode 100644
index 4a1f428..0000000
--- a/src/io/image2jpg_encoder.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "singa/io/image2jpg_encoder.h"
-//#include <opencv2/core/core.hpp>
-//#include <opencv2/highgui/highgui.hpp>
-//#include "opencv2/opencv.hpp"
-
-using namespace cv;
-using namespace std;
-
-namespace singa {
-
-namespace io{
-  string Image2JPGEncoder::Encode(vector<Tensor>& data) {
-    // suppose data[0]: data, data[1]: label
-    // suppose data[0] has a shape as {channel, height, width}
-    CHECK_EQ(data[0].nDim(), 3u);
-    string output;
-    size_t height = data[0].shape()[1];
-    size_t width = data[0].shape()[2];
-    Mat mat = Mat(height, width, CV_8UC3);
-    Mat resized;
-    resize(mat, resized, Size(256, 256));
-    Mat test = imread("test/samples/test.jpeg", CV_LOAD_IMAGE_COLOR);
-    if (data[0].data_type() == kInt)
-      memcpy(mat.data, data[0].data<const int*>(), data[0].Size()*sizeof(int));
-    else LOG(FATAL) << "Data type is invalid for an raw image";
-    //cout << mat << endl;
-
-    const int* label;
-    // suppose each image is attached with only one label
-    if (data[1].data_type() == kInt)
-      label = data[1].data<const int*>();
-    else LOG(FATAL) << "Data type is invalid for image label";
-
-    vector<uchar> buff;
-    vector<int> param = vector<int>(2);
-    param[0] = CV_IMWRITE_JPEG_QUALITY;
-    param[1] = 95; // default is 95
-    imencode(".jpg", mat, buff, param);
-    string buf(buff.begin(), buff.end());
-
-    RecordProto image;
-    image.set_label(label[0]);
-    for (size_t i = 0; i < data[0].nDim(); i++)
-      image.add_shape(data[0].shape()[i]);
-    image.set_pixel(buf);
-    image.SerializeToString(&output);
-
-    return output;
-  }
-}
-}

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/src/io/jpg2proto_encoder.cc
----------------------------------------------------------------------
diff --git a/src/io/jpg2proto_encoder.cc b/src/io/jpg2proto_encoder.cc
new file mode 100644
index 0000000..5b006e1
--- /dev/null
+++ b/src/io/jpg2proto_encoder.cc
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "singa/io/encoder.h"
+#include "singa/proto/model.pb.h"
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+namespace singa {
+
+namespace io{
+  void JPG2ProtoEncoder::Setup(const EncoderConf& conf) { return; }
+
+  std::string JPG2ProtoEncoder::Encode(vector<Tensor>& data) {
+    // suppose data[0]: data, data[1]: label
+    // data[0] has a shape as {height, width, channel}
+    CHECK_EQ(data[0].nDim(), 3u);
+    int height = data[0].shape()[0];
+    int width = data[0].shape()[1];
+    int channel = data[0].shape()[2];
+    cv::Mat mat = cv::Mat(height, width, CV_8UC3, cv::Scalar(0, 0, 0));
+    CHECK_EQ(height, mat.rows);
+    CHECK_EQ(width, mat.cols);
+    CHECK_EQ(channel, mat.channels());
+
+    if (data[0].data_type() != kInt)
+      LOG(FATAL) << "Data type " << data[0].data_type() <<" is invalid for an raw image";
+    const int* raw = data[0].data<const int*>();
+    for (int i = 0; i < height; i++)
+      for (int j = 0; j < width; j++)
+        for (int k = 0; k < channel; k++)
+	  mat.at<cv::Vec3b>(i, j)[k] = static_cast<uchar>(raw[i * width * channel + j * channel + k]);
+    // suppose each image is attached with only one label
+    const int* label = data[1].data<const int*>();
+    CHECK_EQ(label[0], 2);
+
+    // encode image with jpg format
+    std::vector<uchar> buff;
+    std::vector<int> param = std::vector<int>(2);
+    param[0] = CV_IMWRITE_JPEG_QUALITY;
+    param[1] = 100; // default is 95
+    cv::imencode(".jpg", mat, buff, param);
+    std::string buf(buff.begin(), buff.end());
+
+    std::string output;
+    ImageRecordProto image;
+    image.set_label(label[0]);
+    for (size_t i = 0; i < data[0].nDim(); i++)
+      image.add_shape(data[0].shape()[i]);
+    image.set_pixel(buf);
+    image.SerializeToString(&output);
+    return output;
+  }
+}
+}

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/src/io/proto2jpg_decoder.cc
----------------------------------------------------------------------
diff --git a/src/io/proto2jpg_decoder.cc b/src/io/proto2jpg_decoder.cc
new file mode 100644
index 0000000..fd8d9b3
--- /dev/null
+++ b/src/io/proto2jpg_decoder.cc
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "singa/io/decoder.h"
+#include "singa/proto/model.pb.h"
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+namespace singa {
+
+namespace io {
+  void Proto2JPGDecoder::Setup(const DecoderConf& conf) { return; }
+
+  std::vector<Tensor> Proto2JPGDecoder::Decode(std::string value) {
+    std::vector<Tensor> output;
+    ImageRecordProto image;
+    image.ParseFromString(value);
+    Shape shape(image.shape().begin(), image.shape().end());
+    Tensor raw(shape), label(Shape{1});
+    std::vector<uchar> pixel(image.pixel().begin(), image.pixel().end());
+
+    // decode image
+    cv::Mat mat = cv::imdecode(cv::Mat(pixel), CV_LOAD_IMAGE_COLOR);
+    int height = mat.rows, width = mat.cols, channel = mat.channels();
+    CHECK_EQ(shape[0], height);
+    CHECK_EQ(shape[1], width);
+    CHECK_EQ(shape[2], channel);
+
+    float* data = new float[raw.Size()];
+    for (int i = 0; i < height; i++)
+      for (int j = 0; j < width; j++)
+        for (int k = 0; k < channel; k++)
+          data[i * width * channel + j * channel + k] = static_cast<float>(static_cast<int>(mat.at<cv::Vec3b>(i, j)[k]));
+    raw.CopyDataFromHostPtr<float>(data, raw.Size());
+    float l = static_cast<float>(image.label());
+    label.CopyDataFromHostPtr(&l, 1);
+    output.push_back(raw);
+    output.push_back(label);
+    return output;
+  }
+}
+}

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/src/proto/model.proto
----------------------------------------------------------------------
diff --git a/src/proto/model.proto b/src/proto/model.proto
index 77a7f75..8666c30 100644
--- a/src/proto/model.proto
+++ b/src/proto/model.proto
@@ -51,28 +51,20 @@ message BlobProto {
   optional int32 width = 4 [default = 0];
 }
 
-/// directly copy from v0.3
-message Record {
-  enum Type {
-    // each record contains image raw feature and its label.
-    kSingleLabelImage = 0;
-  }
-  optional Type type = 1 [default = kSingleLabelImage];
-  optional string user_type =2;
-  // configuration for
-  optional RecordProto image = 5;
-
-  extensions 101 to 200;
-}
-
-// rename SingleLabelImageRecord to RecordProto
-message RecordProto {
+// rename RecordProto to ImageRecordProto
+message ImageRecordProto {
   repeated int32 shape = 1;
   optional int32 label = 2;
   optional bytes pixel = 3;
-  repeated float data = 4 [packed = true];
 }
-/// end of copy v0.3
+
+message EncoderConf {
+  optional string type = 1 [default = 'jpg'];
+}
+
+message DecoderConf {
+  optional string type = 1 [default = 'jpg'];
+}
 
 message FillerConf {
   // The filler type, case insensitive

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/test/singa/test_decoder.cc
----------------------------------------------------------------------
diff --git a/test/singa/test_decoder.cc b/test/singa/test_decoder.cc
new file mode 100644
index 0000000..33c4cd4
--- /dev/null
+++ b/test/singa/test_decoder.cc
@@ -0,0 +1,87 @@
+/************************************************************
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*************************************************************/
+
+#include "../include/singa/io/encoder.h"
+#include "../include/singa/io/decoder.h"
+#include "gtest/gtest.h"
+#include <time.h>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+using namespace singa;
+
+TEST(Decoder, Decode) {
+  io::JPG2ProtoEncoder encoder;
+  io::Proto2JPGDecoder decoder;
+
+  // initial random seed
+  srand(time(NULL));
+
+  size_t height = 40, width = 30;
+  size_t nheight = 256, nwidth = 256, channel = 3;
+  size_t total = nheight * nwidth * channel;
+  int raw_label = 2;
+  cv::Mat image(height, width, CV_8UC3); 
+  for (size_t i = 0; i < height; i++)
+    for (size_t j = 0; j < width; j++)
+      for (size_t k = 0; k < channel; k++)
+        image.at<cv::Vec3b>(i, j)[k] = static_cast<uchar>(rand() % 256);
+  
+  cv::Mat transformed;
+  cv::Size size(nwidth, nheight);
+  cv::resize(image, transformed, size);
+  EXPECT_EQ(nwidth, transformed.cols);
+  EXPECT_EQ(nheight, transformed.rows);
+  EXPECT_EQ(channel, transformed.channels());
+  
+  unsigned char* buff = transformed.data;
+  int* buf = new int[total];
+  for (size_t i = 0; i < total; i++)
+    buf[i] = static_cast<int>(buff[i]);
+  Shape shape{nheight, nwidth, channel};
+  Tensor pixel(shape, kInt), label(Shape{1}, kInt);
+  pixel.CopyDataFromHostPtr<int>(buf, total);
+  label.CopyDataFromHostPtr<int>(&raw_label, 1);
+
+  std::vector<Tensor> input;
+  input.push_back(pixel);
+  input.push_back(label); 
+  const int* in_pixel = input[0].data<const int *>();
+  for(size_t i = 0; i < total; i++) 
+    EXPECT_EQ(buf[i], in_pixel[i]);
+  const int* in_label = input[1].data<const int *>();
+  EXPECT_EQ(2, in_label[0]);
+  EXPECT_EQ(2, input.size());
+
+  std::string tmp = encoder.Encode(input);
+  std::vector<Tensor> output = decoder.Decode(tmp);
+  EXPECT_EQ(2, output.size());
+  EXPECT_EQ(kFloat32, output[0].data_type());
+  Shape out_shape = output[0].shape();
+  for (size_t i = 0; i < shape.size(); i++)
+    EXPECT_EQ(shape[i], out_shape[i]);
+  const float* out_label = output[1].data<const float*>();
+  EXPECT_EQ(raw_label, out_label[0]);
+  // opencv imencode will have some information loss
+  //const float* out_pixel = output[0].data<const float*>();
+  //for(size_t i = 0; i < total; i++) 
+  //  EXPECT_LE(fabs(in_pixel[i]-out_pixel[i]), 10.f);
+}

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/13d60b03/test/singa/test_io.cc
----------------------------------------------------------------------
diff --git a/test/singa/test_io.cc b/test/singa/test_io.cc
deleted file mode 100644
index 16853c4..0000000
--- a/test/singa/test_io.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-/************************************************************
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-* KIND, either express or implied.  See the License for the
-* specific language governing permissions and limitations
-* under the License.
-*
-*************************************************************/
-
-#include "../include/singa/io/image2jpg_encoder.h"
-#include "../include/singa/io/image2jpg_decoder.h"
-#include "gtest/gtest.h"
-#include <opencv2/highgui/highgui.hpp>
-#include <opencv2/imgproc/imgproc.hpp>
-
-using namespace singa;
-using namespace singa::io;
-using namespace cv;
-
-TEST(Decoder, Decode) {
-  Encoder encoder;
-  Decoder decoder;
-  string path = "test/samples/test.jpeg";
-  size_t resize_height = 256;
-  size_t resize_width = 256;
-  size_t channel = 3;
-  int raw_label[] = {1};
-  Mat image = imread(path, CV_LOAD_IMAGE_COLOR);
-  Mat transformed;
-  Size size(resize_height, resize_width);
-  resize(image, transformed, size);
-  
-  vector<int> buff;
-  buff.assign(transformed.datastart, transformed.dataend);
-  Shape shape{channel, (size_t)transformed.size().height, (size_t)transformed.size().width};
-  Tensor pixel(shape), label(Shape{1});
-  pixel.CopyDataFromHostPtr<vector<int>>(&buff, buff.size());
-  label.CopyDataFromHostPtr<int>(raw_label, 1);
-
-  vector<Tensor> input;
-  input.push_back(pixel);
-  input.push_back(label);
-  string str0 = encoder.Encode(input);
-  vector<Tensor> output = decoder.Decode(str0);
-  Shape out_shape = output.at(0).shape();
-  const int* out_pixel = output.at(0).data<const int *>();
-  const int* out_label = output.at(1).data<const int *>();
-  EXPECT_EQ(raw_label[0], out_label[0]);
-  for (size_t i = 0; i < shape.size(); i++)
-    EXPECT_EQ(shape[i], out_shape[i]);
-  for(size_t i = 0; i < 10; i++) 
-    EXPECT_EQ(buff[i], out_pixel[i]);
-}