2

I have been trying to implement a C# client application to interact with Tensorflow serving server for few weeks now with no success. I have a Python client which works successfully but I can not replicate its functionality with C#. The Python client

import requests
#import json
from keras.preprocessing.image import img_to_array, array_to_img, load_img
from keras.preprocessing import image

flowers = 'c:/flower_photos/cars/car1.jpg'
image1 = img_to_array(image.load_img(flowers, target_size=(128,128))) / 255
payload = {
      "instances": [{"image":image1.tolist()},
]
}
print("sending request...")
r = requests.post('http://localhost:8501/v1/models/flowers/versions/1:predict', json=payload)
print(r.content)

The server responds correctly. I am using Tensorflow version 1.12.0 with corresponding latest serving image. They are all working fine.

According to REST API documentation, the API structure is given but its not clear to me at all. I need to send the image to server. How could I add the image payload to JSON request in C# ? After going through many sites, I found that image should be in base64string.

So I did the image conversion into base64

private string GetBase64ImageBytes(string ImagePath)
{
    using (Image image = Image.FromFile(ImagePath))
    {
        using (MemoryStream m = new MemoryStream())
        {
            image.Save(m, image.RawFormat);
            byte[] imageBytes = m.ToArray();

            // Convert byte[] to Base64 String
            string base64String = Convert.ToBase64String(imageBytes);
            return base64String;
        }
    }
}

The request portion is as follows : (server responds with metadata correctly for the GET request)

public string PostImageToServerAndClassify(string imageArray)
        {
            //https://stackoverflow.com/questions/9145667/how-to-post-json-to-a-server-using-c
            string result = null;
            string ModelName = cmbProjectNames.Text.Replace(" ", "");
            string status_url = String.Format("http://localhost:{0}/v1/models/{1}/versions/{2}:predict", txtPort.Text, ModelName, txtVersion.Text);
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(status_url);
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.Method = "POST";

            try
            {
                using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                {
                    //                    string json = "{"+ @"""instances""" + ": [{" + @"""image""" + @":" + imageArray + "}]}";
                 //   imageArray = @""" + imageArray + @""";
                    string json = "{ " + @"""instances""" + ": [{" + @"""image""" + @": { " + @"""b64"": """ + imageArray + @"""}}]}";

                    streamWriter.Write(json);
                    streamWriter.Flush();
                    streamWriter.Close();
                }
                var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    result = streamReader.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            return result;
        }

With the POST request, I get the error message "The remote server returned an error: (400) Bad Request.". Also server terminates its service. In Postman I get the detailed error info as :

{ "error": "Failed to process element: 0 key: image of \'instances\' list. Error: Invalid argument: JSON Value: {\n    \"b64\": \"/9j/4AAQSkZJRgABAQEAAAAAAAD/4QBSRXhpZgAATU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAZKGAAcAAAAcAAAALAAAAABVTklDT0RFAABBAHAAcABsAGUATQBhAHIAaw ... .....(image string data)

So this feels like that I am sending the incorrect data format. Could someone please tell me what is wrong here ? Any example of image conversion and POST request is highly appreciated. I can not find anywhere that base64string format is the right format for the image in TF site. Python client data format is different hence really need to know what is the right format with any reference documents. The nearest reference I found here with JAVA client but did not work with mine may be due to TF version difference.

PCG
  • 2,049
  • 5
  • 24
  • 42
  • Looking to do the same thing. Did you find a solution to this? – runninggeek Sep 05 '19 at 17:52
  • @runningeek did any of you solve this? – JTIM Nov 10 '20 at 21:53
  • I failed too. I ended up embedding python script into C# as a process. – PCG Nov 11 '20 at 16:54
  • @PCG isn't that very slow? – JTIM Nov 17 '20 at 12:35
  • Yes, it is. I spent a lot of time getting the Base64 it is asking, but never able to get it worked. However, my app is for batch processing (several thousand images) so loading 60 seconds not a huge problem. For some reason, it works in Python. – PCG Nov 18 '20 at 16:39

0 Answers0