C# Onnx Chinese CLIP 通过一句话从图库中搜出来符合要求的图片
效果
生成图片特征
查找踢足球的小孩
测试图片
模型信息
image_model.onnx
Inputs
-------------------------
name:image
tensor:Float[1, 3, 224, 224]
---------------------------------------------------------------
Outputs
-------------------------
name:unnorm_image_features
tensor:Float[1, 512]
---------------------------------------------------------------
text_model.onnx
Inputs
-------------------------
name:text
tensor:Int64[1, 52]
---------------------------------------------------------------
Outputs
-------------------------
name:unnorm_text_features
tensor:Float[1, 512]
---------------------------------------------------------------
项目
代码
Form1.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Onnx_Demo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Clip mynet = new Clip("model/image_model.onnx", "model/text_model.onnx", "model/myvocab.txt");
float[] imagedir_features;
string image_dir = "test_img";
StringBuilder sb = new StringBuilder();
private void button2_Click(object sender, EventArgs e)
{
//特征向量 可以存二进制文件或者向量数据库
imagedir_features = mynet.generate_imagedir_features(image_dir);
txtInfo.Text = "生成完成!";
txtInfo.Text += "有" + mynet.imgnum + "张图片,特征向量长度=" + imagedir_features.Length;
}
服务器托管网private void button3_Click(object sender, EventArgs e)
{
if (imagedir_features == null)
{
MessageBox.Show("请先生成图片特征!");
return;
}
sb.Clear();
txtInfo.Text = "";
lblInfo.Text = "";
pictureBox1.Image = null;
string input_text = txt_input_text.Text;
if (string.IsNullOrEmpty(input_text))
{
return;
}
List> top5imglist = mynet.input_text_search_image(input_text, imagedir_features, mynet.imglist);
sb.AppendLine("top5:");
fore服务器托管网ach (var item in top5imglist)
{
sb.AppendLine(Path.GetFileName(item.Keys.First()) + " 相似度:" + item[item.Keys.First()].ToString("F2"));
}
txtInfo.Text = sb.ToString();
lblInfo.Text = Path.GetFileName(top5imglist[0].Keys.First());
pictureBox1.Image = new Bitmap(top5imglist[0].Keys.First());
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
Clip.cs
public class Clip
{
int inpWidth = 224;
int inpHeight = 224;
float[] mean = new float[] { 0.48145466f, 0.4578275f, 0.40821073f };
float[] std = new float[] { 0.26862954f, 0.26130258f, 0.27577711f };
int context_length = 52;
int len_text_feature = 512;
Net net;
float[] image_features_input;
SessionOptions options;
InferenceSession onnx_session;
Tensor input_tensor;
List input_container;
IDisposableReadOnlyCollection result_infer;
DisposableNamedOnnxValue[] results_onnxvalue;
Tensor result_tensors;
TokenizerBase tokenizer;
int[] text_tokens_input;
float[,] text_features_input;
public int imgnum = 0;
public List imglist = new List();
public Clip(string image_modelpath, string text_modelpath, string vocab_path)
{
net = CvDnn.ReadNetFromOnnx(image_modelpath);
// 创建输出会话,用于输出模型读取信息
options = new SessionOptions();
options.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO;
options.AppendExecutionProvider_CPU(0);// 设置为CPU上运行
// 创建推理模型类,读取本地模型文件
onnx_session = new InferenceSession(text_modelpath, options);//model_path 为onnx模型文件的路径
// 创建输入容器
input_container = new List();
load_tokenizer(vocab_path);
}
void load_tokenizer(string vocab_path)
{
tokenizer = new TokenizerClipChinese();
tokenizer.load_tokenize(vocab_path);
text_tokens_input = new int[1024 * context_length];
}
Mat normalize_(Mat src)
{
Cv2.CvtColor(src, src, ColorConversionCodes.BGR2RGB);
Mat[] bgr = src.Split();
for (int i = 0; i texts)
{
List> text_token = new List>(texts.Count);
for (int i = 0; i ());
}
for (int i = 0; i text_tokens_input.Length)
{
text_tokens_input = new int[text_token.Count * context_length];
}
foreach (int i in text_tokens_input) { text_tokens_input[i] = 0; }
for (int i = 0; i context_length)
{
Console.WriteLine("text_features index " + i + " ,bigger than " + context_length + "n");
continue;
}
for (int j = 0; j (text_tokens_input_64, new[] { 1, 52 });
input_container.Clear();
input_container.Add(NamedOnnxValue.CreateFromTensor("text", input_tensor));
//运行 Inference 并获取结果
result_infer = onnx_session.Run(input_container);
// 将输出结果转为DisposableNamedOnnxValue数组
results_onnxvalue = result_infer.ToArray();
// 读取第一个节点输出并转为Tensor数据
result_tensors = results_onnxvalue[0].AsTensor();
float[] text_feature_ptr = results_onnxvalue[0].AsTensor().ToArray();
float norm = 0.0f;
for (int j = 0; j
{
if (array[pos1] > input_text_search_image(string text, float[] image_features, List imglist)
{
int imgnum = imglist.Count;
List texts = new List { text };
generate_text_feature(texts);
float[] logits_per_image = new float[imgnum];
for (int i = 0; i > top5imglist = new List>(5);
for (int i = 0; i result = new Dictionary();
result.Add(imglist[ind], logits_per_image[ind]);
top5imglist.Add(result);
}
return top5imglist;
}
public float[] generate_imagedir_features(string image_dir)
{
imglist = Common.listdir(image_dir);
imgnum = imglist.Count;
Console.WriteLine("遍历到" + imgnum + "张图片");
float[] imagedir_features = new float[0];
for (int i = 0; i
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
【直播预告】99 元的云虚拟机 9 毛 9 的云原生架构√ NGINX 向云原生演进,All inOpenNJet range 端口转发模块 1.1 需求 在很多时候,比如流量劫持、ftp被动模式代理等功能需要能够支持流量端口转发。比如需要将10000到110…