本文测试环境:
win10 64位
vistual studio 2019
Emgu CV 4.6.0
环境配置准备:
1 新增控制台项目,.net framework为4.7.2
2 把win-x64目录的native目录下的文件全部拷贝到项目的运行目录Debug目录下
3 项目选择x64
4 添加项目引用Emgu.CV.dll、Emgu.CV.Platform.NetFramework.dll、System.Drawing.dll和System.Runtime.InteropServices.RuntimeInformation.dll
具体配置参考:
Emgu CV4图像处理之环境搭建1(C#)_zxy2847225301的博客-CSDN博客
Tensorflow模型下载链接(Tensorflow模型太难找了,找了一圈才找到这个,免积分下载,如果csdn自动调整了该资源的积分,请联系我,我这边修改回0积分):
https://download.csdn.net/download/zxy13826134783/86954448
把下载的文件,解压后,全部复制到项目的Debug目录下
中文的找了一圈都没有找到EmguCV操作tensorflow模型的,幸好在stack overflow中找到了,参考链接如下:
c# - How to detect custom object using EmguCV - Stack Overflow
c++写的参考链接:
OpenCV调用TensorFlow预训练模型_AI吃大瓜的博客-CSDN博客_opencv tensorflow
打开Tensorflow模型函数原型为:
DnnInvoke.ReadNetFromTensorflow(string model,[string config = null])
第一个参数model为pb模型文件路径
第二个参数config为配置文件路径,可选
程序中测试的原图如下:
street.png
cat1.png
cat2.png
cat3.png
参考代码如下:
using Emgu.CV;
using Emgu.CV.Dnn;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EmguCVDemo2
{
class Program
{
static void Main(string[] args)
{
OpenTensorflowModel("street.png", "frozen_inference_graph.pb", "ssd_inception_v2_coco_2017_11_17.pbtxt");
CvInvoke.WaitKey(0);
Console.ReadLine();
}
/// <summary>
/// 打开Tensorflow模型
/// </summary>
private static void OpenTensorflowModel(string imgFileName, string pbFileName, string configFileName)
{
using (Image<Bgr, byte> image1 = new Image<Bgr, byte>(imgFileName))
{
int interception = 0;
int cols = image1.Width;
int rows = image1.Height;
Net netcfg = DnnInvoke.ReadNetFromTensorflow(pbFileName, configFileName);//(Directory.GetCurrentDirectory() + @"\fldr\CO.pb", Directory.GetCurrentDirectory() + @"\fldr\graph.pbtxt");
netcfg.SetInput(DnnInvoke.BlobFromImage(image1.Mat, 1, new System.Drawing.Size(300, 300), default(MCvScalar), true, false));
Mat mat = netcfg.Forward();
#region mat.GetData()返回的类型要根据模型的实践情况来,后面的解析识别结果也会不一样
float[,,,] flt = (float[,,,])mat.GetData();
string[] getMessage = {"Index0", "man", "Index2", "car","Index4", "Index5", "Index6", "Index7", "Index8"
,"Index9", "light", "Index11", "Index12", "Index13"
,"Index14", "Index15", "Index16", "cat", "Index18"
,"Index19", "Index20", "Index21", "Index22", "Index23"};
for (int x = 0; x < flt.GetLength(2); x++)
{
//分值大于0.9
if (flt[0, 0, x, 2] > 0.9)
{
int left = Convert.ToInt32(flt[0, 0, x, 3] * cols);
int top = Convert.ToInt32(flt[0, 0, x, 4] * rows);
int right = Convert.ToInt32(flt[0, 0, x, 5] * cols);
int bottom = Convert.ToInt32(flt[0, 0, x, 6] * rows);
Console.WriteLine("分值:" + flt[0, 0, x, 2] + " 下标:" + flt[0, 0, x, 1]);
int index = (int)flt[0, 0, x, 1];
if (index < 23)
{
CvInvoke.PutText(image1, getMessage[index], new Point((left + right) / 2, (top + bottom) / 2), Emgu.CV.CvEnum.FontFace.HersheySimplex, 1, new MCvScalar(0, 0, 255));
}
image1.Draw(new Rectangle(left, top, right - left, bottom - top), new Bgr(0, 0, 255), 2);
}
}
#endregion
CvInvoke.Imshow("image1", image1);
image1.Save("testing-1.png");
}
}
}
}
经过多方测试,发现flt[0, 0, x, 1]是识别结果信息,flt[0, 0, x, 2]为识别的分值;getMessage 中的信息要自己试了,我试了人、猫、汽车
运行结果:
把代码中的street.png换成cat1.png,运行结果如下:
再换成cat2.png后运行结果如下:
再换成cat3.png后运行结果如下: