c# - 如何在 C# 中创建 TensorProto,方法与 Python 相同
问题描述
我得到了以下 python 片段,用于调用 Tensorflow 模型
# Create prediction request object
request = predict_pb2.PredictRequest()
# Specify model name (must be the same as when the TensorFlow serving serving was started)
request.model_spec.name = FLAGS.model_name
# Specify signature name (should be the same as specified when exporting model)
request.model_spec.signature_name = FLAGS.signature_name
data={}
image=cv2.imread(FLAGS.input_image)
image=np.expand_dims(image, axis=0)
request.inputs['inputs'].CopyFrom(tf.contrib.util.make_tensor_proto(image))
start=time.time()
# Call the prediction server
result = stub.Predict(request, 10) # 10 secs timeout
我正在尝试将此调用合并到我的 asp.net core 3.1 应用程序中。我已经使用 openCV 成功创建了一个 docker 图像,并且可以将我的图像加载到 Mat 中。我无法弄清楚如何复制以下方法。
图像=np.expand_dims(图像,轴=0)
tf.contrib.util.make_tensor_proto(图像)
到目前为止,这是我的代码
public Task GetSignatures(IEnumerable<string> filenames)
{
Channel channel = new Channel("172.17.0.4:8500", ChannelCredentials.Insecure);
var client = new ModelService.ModelServiceClient(channel);
var request = new GetModelStatusRequest
{
ModelSpec = new ModelSpec
{
Name = "model"
}
};
var reply = client.GetModelStatus(request);
var pClient = new PredictionService.PredictionServiceClient(channel);
foreach (string filename in filenames)
{
TensorProto tensor = GetTensorProto(filename);
PredictRequest pRequest = new PredictRequest();
pRequest.ModelSpec = new ModelSpec() { Name = "model" };
pRequest.Inputs.Add("inputs", tensor);
DateTime deadline = DateTime.UtcNow.AddSeconds(2000);
PredictResponse response = pClient.Predict(pRequest, new CallOptions(deadline: deadline));
}
}
private TensorProto GetTensorProto(string filename)
{
using Mat mat = new Mat(filename);
byte[] bytes = mat.ToBytes();
ByteString imageData = ByteString.CopyFrom(bytes);
TensorProto tensorProto = new TensorProto();
Dim dimBatch = new Dim() { Name = "batch", Size = 1 };
Dim dimData = new Dim() { Name = "data", Size = 1 };
TensorShapeProto tensorShape = new TensorShapeProto();
tensorShape.Dim.Add(dimBatch);
tensorShape.Dim.Add(dimData);
tensorProto.TensorShape = tensorShape;
tensorProto.Dtype = DataType.DtUint8;
tensorProto.StringVal.Add(imageData);
return tensorProto;
}
我收到以下错误
rpc.Core.RpcException: Status(StatusCode=InvalidArgument, Detail="slice index 1 of dimension 0 out of bounds.
[[{{node Preprocessor/map/while/ResizeToRange/strided_slice_1}}]]")
解决方案
这篇文章有点晚了,但我遇到了类似的问题并努力寻找任何资源。我对这种机器学习的东西还很陌生,但我想我知道了其中的一部分。
在 python 中,如果您运行以下命令,您可以找到有关矩阵的更多信息:
# tell us it's a numpy.ndarray
print(type(image))
# tells us the dimensions of the array -4 dimensions
print(image.ndim)
# tells us the shape - (1, height of image, width of image, RGB)
print(image.shape)
然后在 C# 中,我能够像这样将这些维度添加到我的张量原型中:
var imageFeatureShape = new TensorShapeProto();
// define our matrix dimensions that we will populate with data. [1, Img.Height, Img.Width, RGB]
imageFeatureShape.Dim.Add(new TensorShapeProto.Types.Dim() { Size = 1 }); // first dimension in our matrix
imageFeatureShape.Dim.Add(new TensorShapeProto.Types.Dim() { Size = imageHeight }); //second dimension in our matrix
imageFeatureShape.Dim.Add(new TensorShapeProto.Types.Dim() { Size = imageWidth }); //third dimension in our matrix
imageFeatureShape.Dim.Add(new TensorShapeProto.Types.Dim() { Size = 3 }); // fourth dimension - RGB values
这是我在 C# 中从文件名转换为张量原型的整个帮助文件。希望这可以帮助某人。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Tensorflow;
namespace TRANS_AI_BASE.DATA.Services
{
public class ImageToTensorProto: IImageToTensorProto
{
/// <summary>
/// Exposed helper function that creates our TensorProto object from our fileInput
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
public TensorProto GetTensorProto(string filename)
{
// create bitmap from file
Bitmap image = new Bitmap(filename);
// convert bitmap to RGB Array/Matrix where values are the individual RGB values from 0-255
var imageDimArray = ConvertImageStreamToDimArraysColor(image);
// take the RGB value array and convert it into a 4 dimensional matrix tensor protoe
var imageTensor = CreateTensorFromImage(imageDimArray, image.Width, image.Height);
return imageTensor;
}
/// <summary>
/// Function to return dim Array, Calls two sub functions to do actual work.
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
private static (int, int, int)[][] ConvertImageStreamToDimArraysColor(Bitmap bitmap)
{
// Convert Bitmap to Byte Array
var bitmapArray = BitmapToByteArrayColor(bitmap);
using (var memoryStream = new MemoryStream(bitmapArray))
{
memoryStream.Position = 0;
// Take byte array and convert it to RGB Matrix format(maybe the same as a tuple array in C#?)
return ConvertImageDataToDimArraysColor(bitmap.Height, bitmap.Width, memoryStream);
}
}
/// <summary>
/// Convert Bitmap to a byte array
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
private static byte[] BitmapToByteArrayColor(Bitmap bitmap)
{
BitmapData bmpdata = null;
try
{
bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
int numbytes = bmpdata.Stride * bitmap.Height;
var bytedata = new byte[numbytes];
var ptr = bmpdata.Scan0;
Marshal.Copy(ptr, bytedata, 0, numbytes);
return bytedata;
}
finally
{
if (bmpdata != null)
bitmap.UnlockBits(bmpdata);
}
}
/// <summary>
/// Convert Byte Array to Dim Array (RGB matrix) format for tensorflow
/// </summary>
/// <param name="numRows"></param>
/// <param name="numCols"></param>
/// <param name="stream"></param>
/// <returns></returns>
private static (int, int, int)[][] ConvertImageDataToDimArraysColor(int numRows, int numCols, MemoryStream stream)
{
var imageMatrix = new (int, int, int)[numRows][];
for (int row = 0; row < numRows; row++)
{
imageMatrix[row] = new (int, int, int)[numCols];
for (int col = 0; col < numCols; ++col)
{
imageMatrix[row][col] = (stream.ReadByte(), stream.ReadByte(), stream.ReadByte());
}
}
return imageMatrix;
}
/// <summary>
/// Create our Tensor Proto. Basemodel expect a matrix of [1, Img.Width, Img.Height, RGB]
/// </summary>
/// <param name="imageData"></param>
/// <returns></returns>
private static TensorProto CreateTensorFromImage((int b, int g, int r)[][] imageData, int imageWidth, int imageHeight)
{
var imageFeatureShape = new TensorShapeProto();
// define our matrix dimensions that we will populate with data. [1, Img.Width, Img.Height, RGB]
imageFeatureShape.Dim.Add(new TensorShapeProto.Types.Dim() { Size = 1 }); // first dimension in our matrix
imageFeatureShape.Dim.Add(new TensorShapeProto.Types.Dim() { Size = imageHeight }); //second dimension in our matrix
imageFeatureShape.Dim.Add(new TensorShapeProto.Types.Dim() { Size = imageWidth }); //third dimension in our matrix
imageFeatureShape.Dim.Add(new TensorShapeProto.Types.Dim() { Size = 3 }); // fourth dimension - RGB values - the values we really care about most
// create a TensorProto and add our tensor shape and datatype values to it
var imageTensorBuilder = new TensorProto();
imageTensorBuilder.Dtype = DataType.DtUint8; // Basemodel (Faster rcnn/resnet 101) expects values of Uint8, AKA byte in C#
imageTensorBuilder.TensorShape = imageFeatureShape;
// loop through essentially the image height or rows of the matrix
for (int i = 0; i < imageData.Length; ++i)
{
// loop through each rows columns or image width
for (int j = 0; j < imageData[i].Length; ++j)
{
// it's hard to find documentation on this stuff. It's by Google, not Microsoft
// developers.google.com/protocol-buffers/docs/reference/csharp
// add the current pixle RGB values to the imageTensorBuilder (tensorProto), but in B.G.R. order
imageTensorBuilder.IntVal.Add(imageData[i][j].b);
imageTensorBuilder.IntVal.Add(imageData[i][j].g);
imageTensorBuilder.IntVal.Add(imageData[i][j].r);
}
}
// useful to compare the count here to the numpy array in python
//var a = imageTensorBuilder.IntVal.Count;
return imageTensorBuilder;
}
}
}
留下我在下面使用的来源:
推荐阅读
- optimization - 未使用主索引
- python - 将动态 url 添加到电子邮件正文 python
- .net - VS2022 可扩展性:如何解决“在 T4 模板执行中,‘Assembly 1’和‘Assembly2’中都存在类型‘XXX’
- python - Scrapy Splash 爬虫 ReactorNotRestartable
- css - React:图像背景图案被 React 组件覆盖
- mongodb - Mongoose 子文档每次返回不同的 ID
- html - 选中后如何更改复选框的边框颜色?
- wordpress - 为购物车总数中的不同优惠券名称更改 WooCommerce 优惠券标签
- c# - System.Text.Json 构造函数和不可变类型
- javascript - onload 完成时继续调用 xmlhttprequest