网站侧栏设计,珠海网站建设排名,网页制作图片,深圳宣传片制作一、目标识别技术概述
1、摘要
目标检测是计算机视觉中最基本和最具挑战性的问题之一#xff0c;它试图从自然图像中的大量预定义类别中定位目标实例。深度学习技术已成为直接从数据中学习特征表示的强大策略#xff0c;并在通用目标检测领域取得了显著突破。鉴于这一快速发…
一、目标识别技术概述
1、摘要
目标检测是计算机视觉中最基本和最具挑战性的问题之一它试图从自然图像中的大量预定义类别中定位目标实例。深度学习技术已成为直接从数据中学习特征表示的强大策略并在通用目标检测领域取得了显著突破。鉴于这一快速发展时期本文的目标是全面综述深度学习技术在这一领域的最新成就。这项调查包括300多项研究贡献涵盖了通用对象检测的许多方面检测框架、对象特征表示、对象提议生成、上下文建模、训练策略和评估指标。我们通过确定未来研究的前景来完成调查。
2、介绍
作为计算机视觉中的一个长期、基本和具有挑战性的问题目标检测如图1所示几十年来一直是一个活跃的研究领域Fischler和Elschlager 1973。目标检测的目标是确定图像中是否存在来自给定类别如人类、汽车、自行车、狗或猫的任何对象实例如果存在则返回每个对象实例的空间位置和范围例如通过边界框Everingham等人2010Russakovsky等人2015。作为图像理解和计算机视觉的基石目标检测是解决复杂或高级视觉任务的基础例如分割、场景理解、目标跟踪、图像字幕、事件检测和活动识别。目标检测支持广泛的应用包括机器人视觉、消费电子、安全、自动驾驶、人机交互、基于内容的图像检索、智能视频监控和增强现实。
最近深度学习技术Hinton和Salakhutdinov 2006LeCun等人2015已成为从数据中自动学习特征表示的强大方法。特别是如图3所示这些技术在对象检测方面提供了重大改进。
如图2所示物体检测可以分为两种类型之一Grauman和Leibe 2011Zhang等人2013特定实例的检测与广泛类别的检测。第一种类型旨在检测特定对象的实例例如唐纳德·特朗普的脸、埃菲尔铁塔或邻居的狗本质上是一个匹配问题。第二种类型的目标是检测某些预定义对象类别例如人、汽车、自行车和狗的实例通常以前未看到。历史上目标检测领域的大部分工作都集中在单个类别通常是人脸和行人或几个特定类别的检测上。相比之下在过去几年中研究界已开始朝着更具挑战性的目标迈进即建立通用目标检测系统在该系统中目标检测能力的广度与人类相当。
Krizhevsky等人2012a提出了一种称为AlexNet的深度卷积神经网络DCNN该网络在大规模视觉识别挑战ILSVRC中实现了破纪录的图像分类精度Russakovsky等人2015。自那时以来计算机视觉的大多数方面的研究重点都是深度学习方法实际上包括通用对象检测领域Girshick等人2014He等人2014Girshick 2015Sermanet al.2014Ren等人2017。虽然已经取得了巨大的进步如图3所示但我们不知道在过去5年中对这一主题进行了全面的调查。鉴于进展速度异常迅速本文试图跟踪最新进展并总结其成果以便更清楚地了解通用目标检测中的当前全景。
3、与之前算法的比较
如表1所示已经发布了许多著名的物体检测调查。其中包括许多关于特定物体检测问题的优秀调查例如行人检测Enzweiler和Gavrila 2009Geronimo等人2010Dollar等人2012、人脸检测Yang等人2002Zafeiriou等人2015、车辆检测Sun等人2006和文本检测Ye和Doermann 2015。除了张等人2013就对象类检测主题进行的调查外最近直接关注一般对象检测问题的调查相对较少。然而在Grauman和Leibe2011、Andreopoulos和Tsotsos2013以及Zhang等人2013中回顾的研究大多是在2012年之前因此在深度学习和相关方法最近取得显著成功并占据主导地位之前。
深度学习允许计算模型学习极其复杂、微妙和抽象的表示推动了广泛问题的重大进展如视觉识别、物体检测、语音识别、自然语言处理、医学图像分析、药物发现和基因组学。在不同类型的深度神经网络中DCNNLeCun等人1998、2015Krizhevsky等人2012a在处理图像、视频、语音和音频方面取得了突破。可以肯定的是已经发表了许多关于深度学习的调查包括Bengio等人2013、LeCun等人2015、Litjens等人2017、Gu等人2018以及最近在ICCV和CVPR的教程中发表的调查。
相比之下虽然已经提出了许多基于深度学习的目标检测方法但我们不知道最近有任何全面的调查。全面回顾和总结现有工作对于目标检测的进一步进展至关重要特别是对于希望进入该领域的研究人员而言。由于我们的重点是一般物体检测因此将不考虑针对特定物体检测的DCNN的广泛工作例如人脸检测李等人2015a张等人2016a胡等人2017、行人检测张等人2016b何桑等人2015、车辆检测周等人2016b和交通标志检测朱等人2016b。
4、范围
基于深度学习的通用目标检测的论文数量惊人。事实上有如此之多的内容以至于对最新技术的任何全面综述都超出了任何合理篇幅的论文的范围。因此有必要制定选择标准将我们的重点限制在顶级期刊和会议论文上。由于这些局限性我们真诚地向那些作品未包含在本文中的作者道歉。有关相关主题工作的调查读者请参阅表1中的文章。本综述主要关注过去5年的主要进展我们将注意力限制在静态图片上将视频对象检测这一重要课题作为未来单独考虑的主题。 二、OpenCV级联分类器CascadeClassifier生成方法
OpenCV级联分类器数据比如cascade.xml用于实现目标识别的核心数据。
CascadeClassifier则是opencv下objdetect模块中用来做目标检测的级联分类器的一个类简而言之是滑动窗口机制级联分类器的方式早期opencv版本仅支持haar特征的目标检测分别在opencv2.2和2.4之后开始支持LBP和HOG特征的目标检测。
使用现成的级联分类器数据局限性太多了工业软件都是自己制作。 1、级联分类器数据的制作流程 2、图片准备与预处理
1图片最好用现场拍摄的照片尽量不要过多的处理原本最好
2文件夹、文件名等最好不要有汉字等数字与字母最好文件夹最好不要有空格
3本文的《层级分类器集成生成环境》可以帮助你一键生成同样大小、黑白以及按数字命名的正样本图片及负样本图片。 3、正样本 Positive Images(Samples)
正样本图片是告诉程序这些 或 接近的就是目标一般来说数量至少在 1000 以上。本文只是示意性的仅仅给出几十个图片这是不够的哈。 1正样本 一般要求 20x2024x2464x64
2现在有了本文的《层级分类器集成生成环境》你随便正样本只要截取的是正方形其实也不一定的即可。
3彩色黑白无所谓。
4正样本文件 pos.txt 是为了生成 正样本矢量化数据 pos.vec 准备的
posdata/001.jpg 1 0 0 20 20
posdata/002.jpg 1 0 0 20 20
posdata/003.jpg 1 0 0 20 20
posdata/004.jpg 1 0 0 20 20
posdata/005.jpg 1 0 0 20 20
posdata/006.jpg 1 0 0 20 20
posdata/007.jpg 1 0 0 20 20
posdata/008.jpg 1 0 0 20 20
posdata/009.jpg 1 0 0 20 20
posdata/010.jpg 1 0 0 20 20
posdata/011.jpg 1 0 0 20 20
posdata/012.jpg 1 0 0 20 20正样本文件 pos.txt 每行的格式是
文件名 样本目标数 起点x 起点 y 宽度 高度
文件名可以用相对路径。样本数建议为1。起点建议为00。
本文的《层级分类器集成生成环境》可以帮助你一键生成 pos.txt 文件。图片尺寸自动提取。 4、正样本 矢量化
正样本矢量化数据 pos.vec 是训练必须的基础数据是归一化、标准化、矢量化的 正样本数据可以不再使用正样本图片及其数据因而大大提高训练效率。
正样本矢量化数据 pos.vec 用 opencv_createsamples.exe 生成。
Windows cmd:
opencv_createsamples.exe -vec pos.vec -info pos.txt -num 12 -w 20 -h 20
Windows PowerShell:
.\opencv_createsamples.exe -vec pos.vec -info pos.txt -num 12 -w 20 -h 20
参数简要说明
-vec pos.vec 生成的矢量文件
-info pos.txt 正样本文件
-num 12 正样本数量
-w 20 正样本尺寸宽
-h 20 正样本尺寸高
本文的《层级分类器集成生成环境》可以帮助你一键生成 pos.vec 文件。不需要进入 cmd 或 PowerShell 去敲键盘 5、负样本 Negative Images(Samples)
1负样本 是告诉识别程序哪些元素是目标中没有的数量至少是正样本的 3 倍。不好凑可以多复制几份哈。可以凑合的。
2负样本大小无所谓唯一的要求是不能含有正样本的物体建议尺寸为 320x240 -- 640x480
3负样本文件 neg.txt
C:/Downloads/Baidu/opencv_bin/negdata/001.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/002.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/003.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/004.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/005.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/006.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/007.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/008.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/009.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/010.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/011.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/012.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/013.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/014.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/015.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/016.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/017.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/018.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/019.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/020.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/021.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/022.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/023.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/024.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/025.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/026.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/027.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/028.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/029.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/030.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/031.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/032.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/033.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/034.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/035.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/036.jpeg
C:/Downloads/Baidu/opencv_bin/negdata/037.jpeg负样本文件只需要指定用于训练的 负样本图片即可。绝对地址绝对地址绝对地址
本文的《层级分类器集成生成环境》可以帮助你一键生成 neg.txt 文件。
正样本数 负样本数 至少是 13 6、训练 Cascade Trainning
有了 pos.vec 与 neg.txt 文件就可以进行训练了。这个过程 坑 比较多。
Windows cmd:
opencv_traincascaded.exe -data xml -vec pos.vec -bg neg.txt -numPos 12 -numNeg 37 -numStages 20 -w 20 -h 20 -maxFalseAlarmRate 0.5 -mode ALL
Windows PowerShell:
.\opencv_traincascaded.exe -data xml -vec pos.vec -bg neg.txt -numPos 12 -numNeg 37 -numStages 20 -w 20 -h 20 -maxFalseAlarmRate 0.5 -mode ALL
注意几点
1先检查 pos.vec neg.txt 文件是否存在是否符合要求
2建议创建子目录 posdata 放置 正样本 图片子目录 negdata 放置 负样本图片
3必须创建 xml 子目录生成结果就在这个子目录下
4无需生成 neg.vec
这个过程很吃资源很慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢慢要花很长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长的时间。
敲击这些参数很麻烦的。经过漫长的等待最终生成 xml/cascade.xml 文件大功告成
本文的《层级分类器集成生成环境》可以帮助你一键做好上述工作自动完成训练生成 cascade.xml 文件 三、《层级分类器集成生成环境》源代码 1、老老程序员的唠叨
自己制作 级联分类器数据 不是一件轻松、简单的事情但没有级联分类器数据几乎无法开展后续的工作。因而不得不硬着头皮做下去。
看到大多数朋友都喜欢进入 cmd 去 key key key效率实在是太低了。
我们这些从 DOS 过来的骨灰级程序员有了 Windows 或 iOS 的 GUI 终于摆脱了 KEY KEY KEY 看到没有 GUI 的程序简直是受罪。关键是效率太低了。3天的活本来1小时可以搞掂。
为了提高效率很多年前就写了 《层级分类器集成生成环境》现在按 Visual Studio 2022 做些改动与改进放出来分享。
代码并不完善有很多不足请自行修改完善之。 2、准备工作
首先需要有 openCV 训练器相关程序
1使用 openCV 开源自己或使用别人编译好的 build
2去 OpenCV 官网下载 release:
OpenCV 官网下载https://opencv.org/releases/
3多动症儿童〄的博客_CSDN博客-百度AI,笔记领域博主提供的下载
https://pan.baidu.com/s/1vCdmWnRRjRNmOCKm30602w?pwdzur8https://pan.baidu.com/s/1vCdmWnRRjRNmOCKm30602w?pwdzur8
CVTrainer项目的目录结构是供参考 3、图片预处理源代码
功能包括批量处理统一尺寸统一名称统一后缀
#region 图片批量转换/// summary
/// 原始文件夹
/// /summary
private string FromFolder { get; set; } ;
/// summary
/// 目标文件夹
/// /summary
private string SaveFolder { get; set; } ;
/// summary
/// 图片尺寸信息
/// /summary
private int[] SaveSizes { get; set; }
/// summary
/// 数字型文件名的序列号
/// /summary
private int SaveIndex { get; set; } 1;private void tpNormalize_SizeChanged(object sender, EventArgs e)
{txtFrom.Width tpNormalize.Width - txtFrom.Left - btnFrom.Width - 60;btnFrom.Left txtFrom.Left txtFrom.Width 5;btnFrom.Top txtFrom.Top;btnFrom.Height txtFrom.Height;
}/// summary
/// 浏览原始文件夹
/// /summary
/// param namesender/param
/// param namee/param
private void btnFrom_Click(object sender, EventArgs e)
{if (folderBrowserDialog1.ShowDialog() DialogResult.OK){FromFolder folderBrowserDialog1.SelectedPath;txtFrom.Text FromFolder;SaveSizes ImageSizes(FromFolder);if (SaveSizes[0] ! SaveSizes[1]) txtFromWidth.Text SaveSizes[0] ... SaveSizes[1];else txtFromWidth.Text SaveSizes[0] ;if (SaveSizes[2] ! SaveSizes[3]) txtFromHeight.Text SaveSizes[2] ... SaveSizes[3];else txtFromHeight.Text SaveSizes[2] ;txtSaveWidth.Text SaveSizes[0] ;txtSaveHeight.Text SaveSizes[2] ;}
}/// summary
/// 浏览并指定目标文件夹
/// /summary
/// param namesender/param
/// param namee/param
private void btnSave_Click(object sender, EventArgs e)
{if (folderBrowserDialog1.ShowDialog() DialogResult.OK){SaveFolder folderBrowserDialog1.SelectedPath;txtSave.Text SaveFolder;}
}/// summary
/// 图片的批量处理
/// /summary
/// param namesender/param
/// param namee/param
private void btnNormalize_Click(object sender, EventArgs e)
{if (FromFolder.Length 1){MessageBox.Show(browse the source folder.);return;}if (SaveFolder.Length 1){MessageBox.Show(browse the destination folder.);return;}int w int.Parse(0 txtSaveWidth.Text);int h int.Parse(0 txtSaveHeight.Text);try{int idx 0;SaveIndex 1;DirectoryInfo fd new DirectoryInfo(FromFolder);FileInfo[] xfiles fd.GetFiles();progressBar1.Maximum xfiles.Count();progressBar1.Visible true;foreach (FileInfo fx in xfiles){progressBar1.Value idx;progressBar1.Refresh();if (IsImageFile(fx.Extension)){string filename Path.Combine(SaveFolder, fx.Name);if (cbNumericName.Checked){filename Path.Combine(SaveFolder, GetNumericalName());}// 如果只是复制if (w SaveSizes[0] h SaveSizes[2] txtSaveExt.Text.Length 0){File.Copy(fx.FullName, filename);continue;}else{Image img Image.FromFile(fx.FullName);if (txtSaveExt.Text.Length 0){filename Path.Combine(SaveFolder, fx.Name.Replace(fx.Extension, ) txtSaveExt.Text);}if (w 0 h 0){Bitmap bmp new Bitmap(w, h);Graphics g Graphics.FromImage(bmp);g.DrawImage(img, 0, 0, w, h);if(cbGray.Checked){ToGrayImage(ref bmp);}bmp.Save(filename);}else if (w 0 h 0){h (int)(w * (double)img.Height / (double)img.Width);Bitmap bmp new Bitmap(w, h);Graphics g Graphics.FromImage(bmp);g.DrawImage(img, 0, 0, w, h);if (cbGray.Checked){ToGrayImage(ref bmp);}bmp.Save(filename);}else{w (int)(h * (double)img.Width / (double)img.Height);Bitmap bmp new Bitmap(w, h);Graphics g Graphics.FromImage(bmp);g.DrawImage(img, 0, 0, w, h);if (cbGray.Checked){ToGrayImage(ref bmp);}bmp.Save(filename);}}}}progressBar1.Visible false;MessageBox.Show(OK!);}catch (Exception ex){MessageBox.Show(ex.Message);}
}/// summary
/// 计算下一个可使用的数字型图片文件名
/// /summary
/// returns/returns
private string GetNumericalName()
{while (true){string sname String.Format({0:D5}, SaveIndex);if (!File.Exists(Path.Combine(SaveFolder, sname))){return sname;}SaveIndex;}
}
#endregion4、正样本处理相关源代码(POWER BY 315SOFT.COM)
一键生成 pos.txt 文件一键生成 pos.vec 文件。
#region 正样本private void tabPage1_SizeChanged(object sender, EventArgs e)
{txtPosFolder.Width tabPage1.Width - txtPosFolder.Left - btnPosFolder.Width - 60;btnPosFolder.Left txtPosFolder.Left txtPosFolder.Width 5;btnPosFolder.Top txtPosFolder.Top;
}/// summary
/// 浏览并指定 正样本 文件夹
/// /summary
/// param namesender/param
/// param namee/param
private void btnPosFolder_Click(object sender, EventArgs e)
{if (folderBrowserDialog1.ShowDialog() DialogResult.OK){txtPosFolder.Text folderBrowserDialog1.SelectedPath;txtPosCount.Text CountImageFile(txtPosFolder.Text) ;}
}/// summary
/// 生成 pos.txt 文件
/// /summary
/// param namesender/param
/// param namee/param
private void btnPosTxt_Click(object sender, EventArgs e)
{if (txtPosFolder.Text.Length 1){MessageBox.Show(Please browse the folder contains positive images!);return;}try{// 为复制图片做准备string imgPosFolder Path.Combine(WorkFolder, posdata);if (cbPosCopy.Checked){if (!Directory.Exists(imgPosFolder)){Directory.CreateDirectory(imgPosFolder);}}StringBuilder sb new StringBuilder();DirectoryInfo fd new DirectoryInfo(txtPosFolder.Text);FileInfo[] xfiles fd.GetFiles();foreach (FileInfo fx in xfiles){if (IsImageFile(fx.Extension)){// 将样本图片文件复制到工作文件夹/posdataif (cbPosCopy.Checked){string df Path.Combine(imgPosFolder, fx.Name);File.Copy(fx.FullName, df);}sb.Append(posdata/);sb.Append(fx.Name );sb.Append(txtSampleCount.Text );sb.Append(txtOriginX.Text );sb.Append(txtOriginY.Text );// 自动获取图片尺寸Image img Image.FromFile(fx.FullName);sb.Append(img.Width );sb.AppendLine(img.Height );// 按最小的图片设置 vector 参数if (txtSampleWidth.Text.Length 0)txtSampleWidth.Text img.Width ;else if (Int32.Parse(txtSampleWidth.Text) img.Width)txtSampleWidth.Text img.Width ;if (txtSampleHeight.Text.Length 0)txtSampleHeight.Text img.Height ;else if (Int32.Parse(txtSampleHeight.Text) img.Height)txtSampleHeight.Text img.Height ;}}if (!Directory.Exists(WorkFolder)){Directory.CreateDirectory(WorkFolder);}File.WriteAllText(Path.Combine(WorkFolder, pos.txt), sb.ToString(), Encoding.Default);webBrowser1.DocumentText sb.ToString().Replace(\r\n, br\r\n);MessageBox.Show(Path.Combine(WorkFolder, pos.txt) OK!);}catch (Exception ex){MessageBox.Show(ex.Message);}
}/// summary
/// 生成 pos.vec 矢量文件
/// /summary
/// param namesender/param
/// param namee/param
private void btnPosVec_Click(object sender, EventArgs e)
{string filename Path.Combine(WorkFolder, pos.txt);if (!File.Exists(filename)){MessageBox.Show(Should first create pos.txt !);return;}Directory.SetCurrentDirectory(WorkFolder);StringBuilder sb new StringBuilder();//sb.Append(WorkFolder \\);//sb.Append(opencv_createsamples.exe );sb.Append(-vec pos.vec );sb.Append(-info pos.txt );sb.Append(-num txtPosCount.Text );sb.Append(-w txtSampleWidth.Text );sb.Append(-h txtSampleHeight.Text);Process p new Process();p.StartInfo.FileName Path.Combine(WorkFolder, opencv_createsamples.exe);p.StartInfo.Arguments sb.ToString();//是否使用操作系统shell启动p.StartInfo.UseShellExecute false;//接受来自调用程序的输入信息p.StartInfo.RedirectStandardInput false;//由调用程序获取输出信息p.StartInfo.RedirectStandardOutput true;//重定向标准错误输出p.StartInfo.RedirectStandardError true;//不显示程序窗口p.StartInfo.CreateNoWindow true;//启动程序p.Start();//p.StandardInput.AutoFlush false;string output p.StandardOutput.ReadToEnd();//等待程序执行完退出进程p.WaitForExit();p.Close();webBrowser1.DocumentText output.Replace(\n, br\n);string filenname Path.Combine(WorkFolder, pos.vec);if (File.Exists(filename)){MessageBox.Show(filename OK!);}
}#endregion5、负样本处理相关源代码
一键生成 neg.txt 文件
#region 负样本private void tabPage2_SizeChanged(object sender, EventArgs e)
{txtNegFolder.Width tabPage2.Width - txtNegFolder.Left - btnNegFolder.Width - 60;btnNegFolder.Left txtNegFolder.Left txtNegFolder.Width 5;btnNegFolder.Top txtNegFolder.Top;
}/// summary
/// 浏览并指定 负样本 文件夹
/// /summary
/// param namesender/param
/// param namee/param
private void btnNegFolder_Click(object sender, EventArgs e)
{if (folderBrowserDialog1.ShowDialog() DialogResult.OK){txtNegFolder.Text folderBrowserDialog1.SelectedPath;txtNegCount.Text CountImageFile(txtNegFolder.Text) ;}
}/// summary
/// 生成负样本 neg.txt 文件
/// /summary
/// param namesender/param
/// param namee/param
private void btnNegTxt_Click(object sender, EventArgs e)
{string imgNegFolder Path.Combine(WorkFolder, negdata);StringBuilder sb new StringBuilder();DirectoryInfo fd new DirectoryInfo(txtNegFolder.Text);FileInfo[] xfiles fd.GetFiles();foreach (FileInfo fx in xfiles){if (IsImageFile(fx.Extension)){// 将样本图片文件复制到工作文件夹/negdataif (cbNegCopy.Checked){string df Path.Combine(imgNegFolder, fx.Name);File.Copy(fx.FullName, df);sb.AppendLine(Path.Combine(imgNegFolder, fx.Name).Replace(\\, /));}else{sb.AppendLine(fx.FullName.Replace(\\, /));}}}if (!Directory.Exists(WorkFolder)){Directory.CreateDirectory(WorkFolder);}File.WriteAllText(Path.Combine(WorkFolder, neg.txt), sb.ToString(), Encoding.Default);webBrowser1.DocumentText sb.ToString().Replace(\r\n, br\r\n);MessageBox.Show(Path.Combine(WorkFolder, neg.txt) OK!);
}#endregion6、训练源代码
一键生成 xml/cascade.xml 文件
#region 训练
private void btnTrainning_Click(object sender, EventArgs e)
{string filename Path.Combine(WorkFolder, pos.vec);if (!File.Exists(filename)){MessageBox.Show(Should first create pos.vec !);return;}filename Path.Combine(WorkFolder, neg.txt);if (!File.Exists(filename)){MessageBox.Show(Should first create neg.txt !);return;}Directory.SetCurrentDirectory(WorkFolder);StringBuilder sb new StringBuilder();sb.Append(-data xml );sb.Append(-vec txtVecFile.Text );sb.Append(-bg txtNegFile.Text );sb.Append(-numPos txtNumPos.Text );sb.Append(-numNeg txtNumNeg.Text );sb.Append(-numStages 20 );sb.Append(-w txtPosWidth.Text );sb.Append(-h txtPosHeight.Text );sb.Append(-minHitRate txtHitRate.Text );sb.Append(-weightTrimRate txtTrimRate.Text );sb.Append(-maxFalseAlarmRate txtFalseAlarm.Text );sb.Append(-stagetype txtStage.Text );sb.Append(-boosttype cxBoost.SelectedItem.ToString() );sb.Append(-featuretype cxFeature.SelectedItem.ToString() );sb.Append(-mode cxMode.SelectedItem.ToString() );Process p new Process();p.StartInfo.FileName Path.Combine(WorkFolder, opencv_traincascade.exe);p.StartInfo.Arguments sb.ToString();//是否使用操作系统shell启动p.StartInfo.UseShellExecute false;//接受来自调用程序的输入信息p.StartInfo.RedirectStandardInput false;//由调用程序获取输出信息p.StartInfo.RedirectStandardOutput true;//重定向标准错误输出p.StartInfo.RedirectStandardError true;//不显示程序窗口p.StartInfo.CreateNoWindow true;//启动程序this.Cursor Cursors.WaitCursor;p.Start();//p.StandardInput.AutoFlush false;string output p.StandardOutput.ReadToEnd();//等待程序执行完退出进程p.WaitForExit();p.Close();this.Cursor Cursors.Default;webBrowser1.DocumentText output.Replace(\n, br\n);string xmlname Path.Combine(WorkFolder, xml, cascade.xml);if (File.Exists(xmlname)){MessageBox.Show(xmlname OK!);}
}#endregion7、基础函数
Form1.cs
using System;
using System.IO;
using System.Text;
using System.Linq;
using System.Drawing;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;namespace Legalsoft.CVTrainer
{/// summary/// OpenCV 训练集继承生成环境/// 北京联高软件开发有限公司/// Beijing Legal Software Ltd./// /summarypublic partial class Form1 : Form{/// summary/// 工作目录/// 一般是 CVTrainer.exe 下的 opencv_bin /// /summaryprivate string WorkFolder { get; set; } ;public Form1(){InitializeComponent();#region 正样本相关btnPosFolder.Height txtPosFolder.Height;WorkFolder Path.Combine(Application.StartupPath, opencv_bin);lbWorkFolderValue.Text WorkFolder;cbPosCopy.Checked true;cbPosCopy.Cursor Cursors.Hand;btnPosTxt.Cursor Cursors.Hand;btnPosVec.Cursor Cursors.Hand;#endregion#region 负样本相关label14.Text WorkFolder;cbNegCopy.Cursor Cursors.Hand;btnNegTxt.Cursor Cursors.Hand;#endregion#region 训练相关label17.Text WorkFolder;btnTrainning.Cursor Cursors.Hand;cxBoost.SelectedIndex 0;cxFeature.SelectedIndex 0;cxMode.SelectedIndex 2;#endregion#region 图片预处理相关cbGray.Cursor Cursors.Hand;txtSaveExt.Text ;cbNumericName.Cursor Cursors.Hand;btnNormalize.Cursor Cursors.Hand;txtFrom.ReadOnly true;txtFromWidth.ReadOnly true;txtFromHeight.ReadOnly true;btnFrom.Cursor Cursors.Hand;txtSave.ReadOnly true;btnSave.Cursor Cursors.Hand;progressBar1.Visible false;#endregiontabPage1.Text Positive Images ;tabPage2.Text Negative Images ;tabPage3.Text Cascade Train ;tpNormalize.Text Image Normalization ;panel1.Dock DockStyle.Top;tabControl1.Dock DockStyle.Fill;panel2.Dock DockStyle.Fill;webBrowser1.Dock DockStyle.Fill;this.Text C#OpenCV Object Detect Images Trainer ——BEIJING LEGAL SOFTWARE LTD.;this.StartPosition FormStartPosition.CenterScreen;}private void Form1_Load(object sender, EventArgs e){Summary();}private void tabControl1_SelectedIndexChanged(object sender, EventArgs e){if (tabControl1.SelectedIndex ! 0){Summary();}}/// summary/// 计算一些概要信息/// /summaryprivate void Summary(){StringBuilder sb new StringBuilder();sb.AppendLine(styleb { font-weight:bold;color:#AA0000; } /style);sb.AppendLine(Work folder: WorkFolder br);string folder WorkFolder;if (!Directory.Exists(folder)){sb.AppendLine(!Create Work folder WorkFolder br);MessageBox.Show(Work folder not exist!\nYou can do nothing!);return;}folder Path.Combine(WorkFolder, xml);sb.AppendLine(Parameters folder: folder br);if (!Directory.Exists(folder)){sb.AppendLine(!Create parameter(xml) folder folder br);Directory.CreateDirectory(folder);}folder Path.Combine(WorkFolder, posdata);sb.AppendLine(Positive folder: folder br);if (!Directory.Exists(folder)){sb.AppendLine(!Create Positive folder folder br);Directory.CreateDirectory(folder);}else{int count CountImageFile(folder);if (count 0){sb.AppendLine(There have count imagesbr);txtPosCount.Text count ;txtNumPos.Text count ;txtPosFolder.Text folder;}if (File.Exists(Path.Combine(WorkFolder, pos.txt))){sb.AppendLine(There have bpos.txt/bbr);int[] sz ImageSizes(Path.Combine(WorkFolder, posdata));txtSampleWidth.Text sz[0] ;txtSampleHeight.Text sz[2] ;txtPosWidth.Text sz[0] ;txtPosHeight.Text sz[2] ;sb.AppendLine(Image size: sz[0] , sz[2] br);}else{sb.AppendLine(There havet bpos.txt/bbr);}if (File.Exists(Path.Combine(WorkFolder, pos.vec))){sb.AppendLine(There have bpos.vec/bbr);}else{sb.AppendLine(There have bnot pos.vec/bbr);}cbPosCopy.Checked (count 0);}folder Path.Combine(WorkFolder, negdata);sb.AppendLine(Negative folder: folder br);if (!Directory.Exists(folder)){sb.AppendLine(!Create Negative folder folder br);Directory.CreateDirectory(folder);}else{int count CountImageFile(folder);if (count 0){sb.AppendLine(There have count imagesbr);txtNegCount.Text count ;txtNumNeg.Text count ;txtNegFolder.Text folder;}if (File.Exists(Path.Combine(WorkFolder, neg.txt))){sb.AppendLine(There have bneg.txt/bbr);}else{sb.AppendLine(There have bnot neg.txt/bbr);}cbNegCopy.Checked (count 0);}webBrowser1.DocumentText sb.ToString();}//...// 这里添加上面的其他代码}
}基础函数
#region 基础函数/// summary
/// 文件是图片吗
/// 按文件后缀判别可自行添加
/// /summary
/// param nameext/param
/// returns/returns
private bool IsImageFile(string ext)
{ext ext.ToLower();if (ext .bmp) return true;if (ext .gif) return true;if (ext .png) return true;if (ext .jpg || ext .jpeg) return true;return false;
}/// summary
/// 统计指定目录下的图片文件数量
/// /summary
/// param namefolder/param
/// returns/returns
private int CountImageFile(string folder)
{DirectoryInfo fd new DirectoryInfo(folder);int count 0;FileInfo[] xfiles fd.GetFiles();foreach (FileInfo fx in xfiles){if (IsImageFile(fx.Extension)){count;}}return count;
}/// summary
/// 提取指定文件夹下图片的尺寸最小、最大的高度、宽度
/// /summary
/// param namefolder/param
/// returns/returns
private int[] ImageSizes(string folder)
{int min_width Int16.MaxValue;int max_width 0;int min_height Int16.MaxValue;int max_height 0;DirectoryInfo fd new DirectoryInfo(folder);FileInfo[] xfiles fd.GetFiles();foreach (FileInfo fx in xfiles){if (IsImageFile(fx.Extension)){Image img Image.FromFile(fx.FullName);if (img.Width max_width) max_width img.Width;if (img.Width min_width) min_width img.Width;if (img.Height max_height) max_height img.Height;if (img.Height min_height) min_height img.Height;}}return new int[] { min_width, max_width, min_height, max_height };
}/// summary
/// 图片转为黑白的
/// 简单的代码看得懂一些效率低下
/// 不过图片不多的够用了。
/// /summary
/// param namebmp/param
private void ToGrayImage(ref Bitmap bmp)
{for (int y 0; y bmp.Height; y){for (int x 0; x bmp.Width; x){Color cc bmp.GetPixel(x, y);int cx Math.Min(255, (int)(cc.R * 0.299 cc.G * 0.587 cc.B * 0.114));bmp.SetPixel(x, y, Color.FromArgb(cx, cx, cx));}}
}#endregion8、界面相关代码略 以上代码经 验证 基本可用享受编程的乐趣吧。