Commit 79de92b9 张士柳

1 个父辈 37ea7eac
...@@ -20,11 +20,6 @@ namespace eyemLib_Sharp ...@@ -20,11 +20,6 @@ namespace eyemLib_Sharp
public int iHeight; // 图像内存 y 方向大小 public int iHeight; // 图像内存 y 方向大小
public int iDepth; // 图像位深度(详见说明) public int iDepth; // 图像位深度(详见说明)
public int iChannels; // 图像通道数 public int iChannels; // 图像通道数
public static implicit operator EyemImage(UnmanagedBitmap v)
{
return v.Image;
}
} }
// 矩形定义 // 矩形定义
...@@ -473,12 +468,12 @@ namespace eyemLib_Sharp ...@@ -473,12 +468,12 @@ namespace eyemLib_Sharp
/// 读取图像文件 /// 读取图像文件
/// </summary> /// </summary>
/// <param name="filename">文件名</param> /// <param name="filename">文件名</param>
/// <param name="iFalgs">读取标志,-1:按照原样加载图像 0:始终将图像转化成单通道灰度图像 1:如果设置,请始终将图像转换为3通道BGR彩色图像 /// <param name="iFlsgs">读取标志,-1:按照原样加载图像 0:始终将图像转化成单通道灰度图像 1:如果设置,请始终将图像转换为3通道BGR彩色图像
/// 2:在输入具有相应深度时返回16位/32位图像,否则将其转换为8位 4:以任何可能的颜色格式读取图像 </param> /// 2:在输入具有相应深度时返回16位/32位图像,否则将其转换为8位 4:以任何可能的颜色格式读取图像 </param>
/// <param name="tpImage">图像</param> /// <param name="tpImage">图像</param>
/// <returns></returns> /// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)] [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemImageRead(string filename, int iFalgs, out EyemImage tpImage); private static extern int eyemImageRead(string filename, int iFlags, out EyemImage tpImage);
/// <summary> /// <summary>
/// 从指针创建图像 /// 从指针创建图像
/// </summary> /// </summary>
...@@ -1103,7 +1098,7 @@ namespace eyemLib_Sharp ...@@ -1103,7 +1098,7 @@ namespace eyemLib_Sharp
private static extern int eyemInitNNDataCodeModel(string detectorConfigPath, string detectorModelPath, string superResolutionConfigPath, string superResolutionModelPath); private static extern int eyemInitNNDataCodeModel(string detectorConfigPath, string detectorModelPath, string superResolutionConfigPath, string superResolutionModelPath);
//背景变化跟踪 //背景变化跟踪
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)] [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemTrackFeature(EyemImage tpRefImg, EyemImage tpNextImg, IntPtr tpArray, int iArraySize, IntPtr ipResults, out EyemImage tpDstImg); private static extern int eyemTrackFeature(EyemImage tpImage, EyemImage tpMask, EyemRect tpRoi, IntPtr tpRois, int ipRoiNum, EyemHSVModel tpHSVModel, [MarshalAs(UnmanagedType.LPArray)]int[] ipResults, out EyemImage tpDstImg);
//插件机 //插件机
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)] [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, IntPtr tpArray, int iArraySize); private static extern int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, IntPtr tpArray, int iArraySize);
...@@ -1205,24 +1200,6 @@ namespace eyemLib_Sharp ...@@ -1205,24 +1200,6 @@ namespace eyemLib_Sharp
#endregion #endregion
//list元素随机打乱
public static void RandomShuffle<T>(List<T> list)
{
List<T> cache = new List<T>();
int currentIndex;
while (list.Count > 0)
{
Random rd = new Random(unchecked((int)DateTime.Now.Ticks));
currentIndex = rd.Next(0, list.Count);
cache.Add(list[currentIndex]);
list.RemoveAt(currentIndex);
}
for (int i = 0; i < cache.Count; i++)
{
list.Add(cache[i]);
}
}
public static void eyemReadImageTool(string fileName) public static void eyemReadImageTool(string fileName)
{ {
EyemImage image; EyemImage image;
...@@ -1237,7 +1214,6 @@ namespace eyemLib_Sharp ...@@ -1237,7 +1214,6 @@ namespace eyemLib_Sharp
sw.Restart(); sw.Restart();
string file = fileName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries)[2]; string file = fileName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries)[2];
//string[] fileNames = Directory.GetFiles(@"C:\Users\nzslw\PycharmProjects\pythonProject\venv\data\AntBee\test\ants", "*.jpg", SearchOption.AllDirectories); //string[] fileNames = Directory.GetFiles(@"C:\Users\nzslw\PycharmProjects\pythonProject\venv\data\AntBee\test\ants", "*.jpg", SearchOption.AllDirectories);
//eyemBuildTrainFile(@"D:\darknet-master\build\darknet\x64\data\val_images", "D:/val.txt");
//return; //return;
//foreach (var item in fileNames) //foreach (var item in fileNames)
//{ //{
...@@ -1245,11 +1221,6 @@ namespace eyemLib_Sharp ...@@ -1245,11 +1221,6 @@ namespace eyemLib_Sharp
//} //}
//return; //return;
//List<string> random_shuffle = new List<string>(fileNames);
////随机打乱顺序
//RandomShuffle(random_shuffle);
//bool HaveDuplicates = random_shuffle.GroupBy(i => i).Where(g => g.Count() > 1).Count() >= 1;
//for (int i = 0; i < fileNames.Length; i++) //for (int i = 0; i < fileNames.Length; i++)
//{ //{
// string item = fileNames[i]; // string item = fileNames[i];
...@@ -1258,6 +1229,7 @@ namespace eyemLib_Sharp ...@@ -1258,6 +1229,7 @@ namespace eyemLib_Sharp
// fi.MoveTo(@"D:\日志\" + (i+83).ToString() + ".png"); // fi.MoveTo(@"D:\日志\" + (i+83).ToString() + ".png");
//} //}
//return; //return;
//StreamWriter swr = new StreamWriter("D:\\val.txt", true); //StreamWriter swr = new StreamWriter("D:\\val.txt", true);
//foreach (var item in random_shuffle) //foreach (var item in random_shuffle)
//{ //{
...@@ -1280,8 +1252,6 @@ namespace eyemLib_Sharp ...@@ -1280,8 +1252,6 @@ namespace eyemLib_Sharp
//eyemImageFree(ref tpDstImg); //eyemImageFree(ref tpDstImg);
//eyemImageFree(ref image); //eyemImageFree(ref image);
//return; //return;
//UnmanagedBitmap umBitmap = new UnmanagedBitmap("D:\\算法测试图像\\circle_plate_04.png");
//return;
//flag = eyemInitNNDataCodeModel(".\\darknet\\detect-tiny.cfg", ".\\darknet\\detect-tiny.weights", "", "") & eyemInitNNDetector(".\\darknet\\detect-tiny-label.cfg", ".\\darknet\\detect-tiny-label.weights"); //flag = eyemInitNNDataCodeModel(".\\darknet\\detect-tiny.cfg", ".\\darknet\\detect-tiny.weights", "", "") & eyemInitNNDetector(".\\darknet\\detect-tiny-label.cfg", ".\\darknet\\detect-tiny-label.weights");
...@@ -1290,17 +1260,57 @@ namespace eyemLib_Sharp ...@@ -1290,17 +1260,57 @@ namespace eyemLib_Sharp
//tpHsvModel.dpRangeL = new double[] { 0, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 10, 255, 255 }; //tpHsvModel.dpRangeL = new double[] { 0, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 10, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 156, 43, 46 }; tpHsvModel.dpRangeUExt = new double[] { 180, 255, 255 }; //tpHsvModel.dpRangeLExt = new double[] { 156, 43, 46 }; tpHsvModel.dpRangeUExt = new double[] { 180, 255, 255 };
////绿色分割 //绿色分割模型
//EyemHSVModel tpHsvModel = new EyemHSVModel(); EyemHSVModel tpHsvModel = new EyemHSVModel();
//tpHsvModel.dpRangeL = new double[] { 35, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 77, 255, 255 }; tpHsvModel.dpRangeL = new double[] { 55, 10, 35 }; tpHsvModel.dpRangeU = new double[] { 100, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 };
EyemRect tpRoi0 = new EyemRect();
tpRoi0.iXs = 0; tpRoi0.iYs = 0;
tpRoi0.iWidth = image.iWidth;
tpRoi0.iHeight = image.iHeight;
sw.Restart();
List<EyemRect> tpRois = new List<EyemRect>();
EyemRect roi1 = new EyemRect();
roi1.iXs = 533; roi1.iYs = 187; roi1.iWidth = 345; roi1.iHeight = 310;
EyemRect roi2 = new EyemRect();
roi2.iXs = 900; roi2.iYs = 137; roi2.iWidth = 240; roi2.iHeight = 197;
//添加需要监控的位置信息
tpRois.Add(roi1); tpRois.Add(roi2);
//结构体转内存指针
IntPtr hGlobal = eyemStructArray2IntPtr(tpRois.ToArray());
//加载mask
EyemImage mask;
eyemImageRead("mask.png", -1, out mask);
//
int[] ipResults = new int[tpRois.Count];
eyemTrackFeature(image, mask, tpRoi0, hGlobal, ipResults.Length, tpHsvModel, ipResults, out tpDstImg);
for (int i = 0; i < ipResults.Length; i++)
{
if (ipResults[i] == 1)
{
Console.WriteLine("检测到{0}位置有料盘", i);
}
}
//sw.Stop();
//Console.WriteLine("时间花费:" + sw.ElapsedMilliseconds.ToString());
////蓝色分割 ////蓝色分割
//EyemHSVModel tpHsvModel = new EyemHSVModel(); //EyemHSVModel tpHsvModel = new EyemHSVModel();
//tpHsvModel.dpRangeL = new double[] { 100, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 124, 255, 255 }; //tpHsvModel.dpRangeL = new double[] { 100, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 124, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 }; //tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 };
//分类器
//eyemClassifier(image); //eyemClassifier(image);
//sw.Restart();
//flag = eyemLibImpl(image, out tpDstImg); //flag = eyemLibImpl(image, out tpDstImg);
//sw.Stop();
//Console.WriteLine("时间花费:" + sw.ElapsedMilliseconds.ToString());
//float[] fFeatures = new float[512]; //float[] fFeatures = new float[512];
//eyemExtractWithONNX(image, fFeatures); //eyemExtractWithONNX(image, fFeatures);
//string ftrs = string.Join(" ", fFeatures).Trim(); //string ftrs = string.Join(" ", fFeatures).Trim();
...@@ -1314,26 +1324,29 @@ namespace eyemLib_Sharp ...@@ -1314,26 +1324,29 @@ namespace eyemLib_Sharp
//} //}
//EyemImage tpMatchImg; //EyemImage tpMatchImg;
//eyemTrainImageSampler(image, 128, "PID012", "D:\\ResOut", out tpMatchImg, out tpDstImg); //eyemTrainImageSampler(image, 128, "PID012", "D:\\ResOut", out tpMatchImg, out tpDstImg);
//eyemBuildTrainFile("D:\\test", ""); Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg); if (bitmap != null)
//if (bitmap != null) {
//{ bitmap.Save("D:\\ResOut\\" + file);
// bitmap.Save("D:\\ResOut\\" + file); }
//} //释放资源
//eyemImageFree(ref tpMatchImg); Marshal.FreeHGlobal(hGlobal);
//eyemImageFree(ref tpDstImg); //每运行检测一次释放一次
//eyemImageFree(ref image); eyemImageFree(ref tpDstImg);
//return; eyemImageFree(ref image);
//mask可以在程序启动与关闭时加载/释放
eyemImageFree(ref mask);
return;
//EyemImage templ, search; //EyemImage templ, search;
//flag = eyemImageRead("D://批量测试图像//template.png", -1, out templ); //flag = eyemImageRead("D://算法测试图像//fiducial_template.png", -1, out templ);
//if (flag != 0) //if (flag != 0)
//{ //{
// Console.WriteLine("读图失败!"); // Console.WriteLine("读图失败!");
// return; // return;
//} //}
//flag = eyemImageRead("D://批量测试图像//search1.png", -1, out search); //flag = eyemImageRead("D://算法测试图像//fiducial_input.png", -1, out search);
//if (flag != 0) //if (flag != 0)
//{ //{
// Console.WriteLine("读图失败!"); // Console.WriteLine("读图失败!");
...@@ -1342,7 +1355,7 @@ namespace eyemLib_Sharp ...@@ -1342,7 +1355,7 @@ namespace eyemLib_Sharp
//flag = eyemMakeShapeModel(templ, 100, 10); //flag = eyemMakeShapeModel(templ, 100, 10);
//flag = eyemFindShapeModel(search, 10, 0, 90, 1, 10, 100, 0.9, 0.9); //flag = eyemFindShapeModel(search, 10, 0, 90, 1, 10, 100, 0.7, 0.7);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg); //Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null) //if (bitmap != null)
//{ //{
...@@ -1623,11 +1636,11 @@ namespace eyemLib_Sharp ...@@ -1623,11 +1636,11 @@ namespace eyemLib_Sharp
//移除模板 //移除模板
//flag = eyemRemoveModelByName(hModelID, "D:\\模板文件及图像\\df871193-6632-48f9-abfe-540c3fc49c3f.tpl"); //flag = eyemRemoveModelByName(hModelID, "D:\\模板文件及图像\\df871193-6632-48f9-abfe-540c3fc49c3f.tpl");
Bitmap bitmap = eyemCvtToBitmap(tpDstImg); //Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
if (bitmap != null) //if (bitmap != null)
{ //{
bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file); // bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
} //}
////< 解码测试 ////< 解码测试
//int ipNum; EyemBarCode* tpResults; //int ipNum; EyemBarCode* tpResults;
...@@ -1712,37 +1725,37 @@ namespace eyemLib_Sharp ...@@ -1712,37 +1725,37 @@ namespace eyemLib_Sharp
public static void eyemTestVideoCapture(string fileName) public static void eyemTestVideoCapture(string fileName)
{ {
List<EyemRect3> tpRois = new List<EyemRect3>(); //List<EyemRect3> tpRois = new List<EyemRect3>();
EyemRect3 roi1 = new EyemRect3(); //EyemRect3 roi1 = new EyemRect3();
roi1.iXs = 0; roi1.iYs = 400; roi1.iWidth = 100; roi1.iHeight = 100; roi1.dVar = 0.35; //roi1.iXs = 0; roi1.iYs = 400; roi1.iWidth = 100; roi1.iHeight = 100; roi1.dVar = 0.35;
EyemRect3 roi2 = new EyemRect3(); //EyemRect3 roi2 = new EyemRect3();
roi2.iXs = 101; roi2.iYs = 400; roi2.iWidth = 100; roi2.iHeight = 100; roi2.dVar = 0.35; //roi2.iXs = 101; roi2.iYs = 400; roi2.iWidth = 100; roi2.iHeight = 100; roi2.dVar = 0.35;
EyemRect3 roi3 = new EyemRect3(); //EyemRect3 roi3 = new EyemRect3();
roi3.iXs = 202; roi3.iYs = 400; roi3.iWidth = 100; roi3.iHeight = 100; roi3.dVar = 0.35; //roi3.iXs = 202; roi3.iYs = 400; roi3.iWidth = 100; roi3.iHeight = 100; roi3.dVar = 0.35;
EyemRect3 roi4 = new EyemRect3(); //EyemRect3 roi4 = new EyemRect3();
roi4.iXs = 303; roi4.iYs = 400; roi4.iWidth = 100; roi4.iHeight = 100; roi4.dVar = 0.35; //roi4.iXs = 303; roi4.iYs = 400; roi4.iWidth = 100; roi4.iHeight = 100; roi4.dVar = 0.35;
//需要监控的位置信息 ////需要监控的位置信息
tpRois.Add(roi1); tpRois.Add(roi2); tpRois.Add(roi3); tpRois.Add(roi4); //tpRois.Add(roi1); tpRois.Add(roi2); tpRois.Add(roi3); tpRois.Add(roi4);
//结构体转内存指针 ////结构体转内存指针
IntPtr hGlobal = eyemStructArray2IntPtr(tpRois.ToArray()); //IntPtr hGlobal = eyemStructArray2IntPtr(tpRois.ToArray());
//信号值,用于后续处理 ////信号值,用于后续处理
int[] bitSingle = new int[tpRois.Count]; //int[] bitSingle = new int[tpRois.Count];
EyemImage tpDstImg, tpRefImg, tpNextImg; //EyemImage tpDstImg, tpRefImg, tpNextImg;
eyemImageRead(fileName + "\\右侧BOX_12 2021-06-22-10-33-06-Original.png", -1, out tpRefImg); //eyemImageRead(fileName + "\\右侧BOX_12 2021-06-22-10-33-06-Original.png", -1, out tpRefImg);
eyemImageRead(fileName + "\\右侧BOX_12 2021-06-22-08-35-38-Comp.png", -1, out tpNextImg); //eyemImageRead(fileName + "\\右侧BOX_12 2021-06-22-08-35-38-Comp.png", -1, out tpNextImg);
//存放结果 ////存放结果
int[] iArrRes = new int[tpRois.Count]; //int[] iArrRes = new int[tpRois.Count];
//int iRet = eyemAOIForTSAV(tpImages[0], tpImages[i], hGlobal, tpRois.Count); ////int iRet = eyemAOIForTSAV(tpImages[0], tpImages[i], hGlobal, tpRois.Count);
int iRet = eyemTrackFeature(tpRefImg, tpNextImg, hGlobal, tpRois.Count, Marshal.UnsafeAddrOfPinnedArrayElement(iArrRes, 0), out tpDstImg); //int iRet = eyemTrackFeature(tpRefImg, tpNextImg, hGlobal, tpRois.Count, Marshal.UnsafeAddrOfPinnedArrayElement(iArrRes, 0), out tpDstImg);
eyemImageFree(ref tpDstImg); //eyemImageFree(ref tpDstImg);
//释放资源 ////释放资源
Marshal.FreeHGlobal(hGlobal); //Marshal.FreeHGlobal(hGlobal);
} }
#region 文件重新命名 #region 文件重新命名
...@@ -1788,9 +1801,7 @@ namespace eyemLib_Sharp ...@@ -1788,9 +1801,7 @@ namespace eyemLib_Sharp
{ {
if (tpImage.vpImage == IntPtr.Zero || tpImage.iDepth != 0) if (tpImage.vpImage == IntPtr.Zero || tpImage.iDepth != 0)
return null; return null;
PixelFormat format; PixelFormat format;
switch (tpImage.iChannels) switch (tpImage.iChannels)
{ {
case 1: case 1:
...@@ -1807,7 +1818,6 @@ namespace eyemLib_Sharp ...@@ -1807,7 +1818,6 @@ namespace eyemLib_Sharp
} }
Bitmap bitmap = new Bitmap(tpImage.iWidth, tpImage.iHeight, format); Bitmap bitmap = new Bitmap(tpImage.iWidth, tpImage.iHeight, format);
//对于输出灰度图像 //对于输出灰度图像
if (format == PixelFormat.Format8bppIndexed) if (format == PixelFormat.Format8bppIndexed)
{ {
...@@ -1818,22 +1828,17 @@ namespace eyemLib_Sharp ...@@ -1818,22 +1828,17 @@ namespace eyemLib_Sharp
} }
bitmap.Palette = palette; bitmap.Palette = palette;
} }
//锁定数据区 //锁定数据区
BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, tpImage.iWidth, tpImage.iHeight), BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, tpImage.iWidth, tpImage.iHeight),
ImageLockMode.WriteOnly, format); ImageLockMode.WriteOnly, format);
try try
{ {
int pd = ((tpImage.iWidth * tpImage.iChannels) + 3) / 4 * 4; int pd = ((tpImage.iWidth * tpImage.iChannels) + 3) / 4 * 4;
long bytesToCopy = tpImage.iWidth * tpImage.iChannels; long bytesToCopy = tpImage.iWidth * tpImage.iChannels;
for (int y = 0; y < tpImage.iHeight; y++) for (int y = 0; y < tpImage.iHeight; y++)
{ {
long offsetSrc = (y * tpImage.iWidth * tpImage.iChannels); long offsetSrc = (y * tpImage.iWidth * tpImage.iChannels);
long offsetDst = (y * pd); long offsetDst = (y * pd);
Buffer.MemoryCopy((byte*)(tpImage.vpImage.ToPointer()) + offsetSrc, (byte*)(bd.Scan0.ToPointer()) + offsetDst, bytesToCopy, bytesToCopy); Buffer.MemoryCopy((byte*)(tpImage.vpImage.ToPointer()) + offsetSrc, (byte*)(bd.Scan0.ToPointer()) + offsetDst, bytesToCopy, bytesToCopy);
} }
} }
......
...@@ -7,36 +7,42 @@ namespace eyemLib_Sharp ...@@ -7,36 +7,42 @@ namespace eyemLib_Sharp
{ {
public unsafe class UnmanagedBitmap : IDisposable public unsafe class UnmanagedBitmap : IDisposable
{ {
#region 接口
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemImageRead(string filename, int iFalgs, out EyemImage tpImage);
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern void eyemImageFree(ref EyemImage tpImage);
#endregion
private EyemImage image; private EyemImage image;
public EyemImage Image public EyemImage Image
{ {
get { return image; } get { return image; }
} }
/// <summary>
/// 初始化新实例
/// </summary>
public UnmanagedBitmap() public UnmanagedBitmap()
{ {
image = new EyemImage(); image = new EyemImage();
} }
/// <summary>
/// 从指定文件初始化UnmanagedBitmap的新实例(支持BMP、DIB、PNG、PBM、PGM、PPM、EXR、JPEG、JPG、JPE、TIF等格式图像)
/// </summary>
/// <param name="fileName">文件名</param>
public UnmanagedBitmap(string fileName) public UnmanagedBitmap(string fileName)
{ {
eyemImageRead(fileName, -1, out image); eyemImageRead(fileName, -1, out image);
} }
/// <summary>
/// 从Bitmap初始化Unmanaged新实例(GDI不支持除8位以外深度的图像;若要加载不同深度图像请使用从文件名加载)
/// </summary>
/// <param name="bitmap"></param>
public UnmanagedBitmap(Bitmap bitmap) public UnmanagedBitmap(Bitmap bitmap)
{ {
mustbeDispose = true;
image = eyemCvtToEyemImage(bitmap); image = eyemCvtToEyemImage(bitmap);
} }
/// <summary>
private bool mustbeDispose = false; /// 隐式转换成EyemImage
/// </summary>
/// <param name="operand"></param>
public static implicit operator EyemImage(UnmanagedBitmap operand)
{
return operand.Image;
}
~UnmanagedBitmap() ~UnmanagedBitmap()
{ {
...@@ -55,86 +61,39 @@ namespace eyemLib_Sharp ...@@ -55,86 +61,39 @@ namespace eyemLib_Sharp
{ {
// dispose managed resources // dispose managed resources
} }
if (mustbeDispose) //这里特别修改了eyemCvtToEyemImage的内存分配,因此皆可以由此接口释放
{
image.iChannels = image.iDepth = image.iHeight = image.iWidth = 0;
Marshal.FreeHGlobal(image.vpImage);
image.vpImage = IntPtr.Zero;
}
else
{
eyemImageFree(ref image); eyemImageFree(ref image);
} }
}
#region EyemImageBitmap相互转换
public static Bitmap eyemCvtToBitmap(EyemImage tpImage)
{
if (tpImage.vpImage == IntPtr.Zero || tpImage.iDepth != 0)
return null;
PixelFormat format;
switch (tpImage.iChannels)
{
case 1:
format = PixelFormat.Format8bppIndexed;
break;
case 3:
format = PixelFormat.Format24bppRgb;
break;
case 4:
format = PixelFormat.Format32bppArgb;
break;
default:
return null;
}
Bitmap bitmap = new Bitmap(tpImage.iWidth, tpImage.iHeight, format);
//对于输出灰度图像
if (format == PixelFormat.Format8bppIndexed)
{
ColorPalette palette = bitmap.Palette;
for (int i = 0; i < 256; i++)
{
palette.Entries[i] = Color.FromArgb(i, i, i);
}
bitmap.Palette = palette;
}
//锁定数据区
BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, tpImage.iWidth, tpImage.iHeight),
ImageLockMode.WriteOnly, format);
try
{
int pd = ((tpImage.iWidth * tpImage.iChannels) + 3) / 4 * 4;
long bytesToCopy = tpImage.iWidth * tpImage.iChannels; #region 接口
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
for (int y = 0; y < tpImage.iHeight; y++) private static extern int eyemImageRead(string filename, int iFalgs, out EyemImage tpImage);
{ [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
long offsetSrc = (y * tpImage.iWidth * tpImage.iChannels); private static extern void eyemImageFree(ref EyemImage tpImage);
long offsetDst = (y * pd); [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemCvtImageType(EyemImage tpImage, string ccSubType, double alpha, double beta, ref EyemImage tpDstImg);
Buffer.MemoryCopy((byte*)(tpImage.vpImage.ToPointer()) + offsetSrc, (byte*)(bd.Scan0.ToPointer()) + offsetDst, bytesToCopy, bytesToCopy); /// <summary>
} /// 从进程中的非托管内存分配指定长度的内存
} /// </summary>
finally /// <param name="cb">长度</param>
{ /// <returns>地址</returns>
bitmap.UnlockBits(bd); [DllImport("eyemLib.dll", CallingConvention = CallingConvention.Cdecl)]
} private static extern IntPtr eyemMallocMemBlock(int cb);
return bitmap; /// <summary>
} /// 释放从非托管内存中分配的内存
/// </summary>
/// <param name="block">地址</param>
[DllImport("eyemLib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void eyemFreeMemBlock(IntPtr block);
#endregion
#region EyemImageBitmap相互转换
public static EyemImage eyemCvtToEyemImage(Bitmap bitmap) public static EyemImage eyemCvtToEyemImage(Bitmap bitmap)
{ {
EyemImage tpImage = new EyemImage(); EyemImage tpImage = new EyemImage();
//锁定数据区 //锁定数据区
BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, bitmap.PixelFormat); ImageLockMode.ReadOnly, bitmap.PixelFormat);
switch (bitmap.PixelFormat) switch (bitmap.PixelFormat)
{ {
case PixelFormat.Format8bppIndexed: case PixelFormat.Format8bppIndexed:
...@@ -153,19 +112,16 @@ namespace eyemLib_Sharp ...@@ -153,19 +112,16 @@ namespace eyemLib_Sharp
tpImage.iDepth = 0; tpImage.iDepth = 0;
//图像尺寸 //图像尺寸
tpImage.iWidth = bitmap.Width; tpImage.iHeight = bitmap.Height; tpImage.iWidth = bitmap.Width; tpImage.iHeight = bitmap.Height;
//分配内存(释放不是用eyemImageFree,用Marshal.FreeHGlobal(tpImage.vpImage)) //分配内存(此函数分配的内存可由默认接口释放)
tpImage.vpImage = Marshal.AllocHGlobal(bd.Stride * bd.Height); tpImage.vpImage = eyemMallocMemBlock(bd.Stride * bd.Height);
try try
{ {
int pd = ((tpImage.iWidth * tpImage.iChannels) + 3) / 4 * 4; int pd = ((tpImage.iWidth * tpImage.iChannels) + 3) / 4 * 4;
long bytesToCopy = tpImage.iWidth * tpImage.iChannels; long bytesToCopy = tpImage.iWidth * tpImage.iChannels;
for (int y = 0; y < tpImage.iHeight; y++) for (int y = 0; y < tpImage.iHeight; y++)
{ {
long offsetSrc = y * pd; long offsetSrc = y * pd;
long offsetDst = y * tpImage.iWidth * tpImage.iChannels; long offsetDst = y * tpImage.iWidth * tpImage.iChannels;
Buffer.MemoryCopy((byte*)(bd.Scan0.ToPointer()) + offsetSrc, (byte*)(tpImage.vpImage.ToPointer()) + offsetDst, bytesToCopy, bytesToCopy); Buffer.MemoryCopy((byte*)(bd.Scan0.ToPointer()) + offsetSrc, (byte*)(tpImage.vpImage.ToPointer()) + offsetDst, bytesToCopy, bytesToCopy);
} }
} }
......
...@@ -141,7 +141,7 @@ int eyemEdge1dFindLine(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLine ...@@ -141,7 +141,7 @@ int eyemEdge1dFindLine(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLine
std::vector<EyemOcsDXY> *tpResults = new std::vector<EyemOcsDXY>(); std::vector<EyemOcsDXY> *tpResults = new std::vector<EyemOcsDXY>();
for (int n = 1; n <= nCalipers; n++) for (int n = 1; n <= nCalipers; n++)
{ {
float *pMag = new float[szMap.width*szMap.height * sizeof(float_t)]; float *pMag = new float[szMap.width*szMap.height];
for (int m = 0; m <= iCapWidth; m++) for (int m = 0; m <= iCapWidth; m++)
{ {
float plusX, plusY; float plusX, plusY;
...@@ -204,7 +204,7 @@ int eyemEdge1dFindLine(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLine ...@@ -204,7 +204,7 @@ int eyemEdge1dFindLine(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLine
cv::Mat projectedMap; cv::Mat projectedMap;
cv::reduce(interMap, projectedMap, 0, cv::REDUCE_AVG, CV_32F); cv::reduce(interMap, projectedMap, 0, cv::REDUCE_AVG, CV_32F);
//差分过滤(TODO:加高斯滤波) //差分过滤(TODO:加高斯滤波)
float *pFilteredMap = new float[szMap.width * sizeof(float_t)]; float *pFilteredMap = new float[szMap.width];
cv::Mat filteredMap(cv::Size(szMap.width, 1), CV_32FC1, pFilteredMap); cv::Mat filteredMap(cv::Size(szMap.width, 1), CV_32FC1, pFilteredMap);
cv::sepFilter2D(projectedMap, filteredMap, CV_32F, whalf, cv::Mat::ones(1, 1, CV_32F)); cv::sepFilter2D(projectedMap, filteredMap, CV_32F, whalf, cv::Mat::ones(1, 1, CV_32F));
//投影峰值查找 //投影峰值查找
...@@ -307,6 +307,11 @@ int eyemEdge1dFindLine(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLine ...@@ -307,6 +307,11 @@ int eyemEdge1dFindLine(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLine
} }
} }
#endif #endif
//遍历结果
//for (auto it = tpResults->begin(); it != tpResults->end(); ++it)
//{
// it->dX; it->dY;
//}
//释放资源(Tips:当存在越界时候在用free释放时会报错) //释放资源(Tips:当存在越界时候在用free释放时会报错)
delete[] filterK; delete[] filterK;
filterK = NULL; filterK = NULL;
...@@ -366,7 +371,7 @@ int eyemEdge1dFindCircle(EyemImage tpImage, EyemOcsDXY tpPoint, int iRadius, int ...@@ -366,7 +371,7 @@ int eyemEdge1dFindCircle(EyemImage tpImage, EyemOcsDXY tpPoint, int iRadius, int
float x = float(tpPoint.dX + (float)iRadius*cos(t)); float x = float(tpPoint.dX + (float)iRadius*cos(t));
float y = float(tpPoint.dY + (float)iRadius*sin(t)); float y = float(tpPoint.dY + (float)iRadius*sin(t));
//采样图像 //采样图像
float *pMag = new float[szMap.width*szMap.height * sizeof(float_t)]; float *pMag = new float[szMap.width*szMap.height];
for (float n = -(float)iCapWidth / 2.0f; n <= (float)iCapWidth / 2.0f; n += 1.0f, m++) for (float n = -(float)iCapWidth / 2.0f; n <= (float)iCapWidth / 2.0f; n += 1.0f, m++)
{ {
for (int iR = -iCapLength; iR <= iCapLength; iR++) { for (int iR = -iCapLength; iR <= iCapLength; iR++) {
...@@ -402,7 +407,7 @@ int eyemEdge1dFindCircle(EyemImage tpImage, EyemOcsDXY tpPoint, int iRadius, int ...@@ -402,7 +407,7 @@ int eyemEdge1dFindCircle(EyemImage tpImage, EyemOcsDXY tpPoint, int iRadius, int
cv::Mat projectedMap; cv::Mat projectedMap;
cv::reduce(interMap, projectedMap, 0, cv::REDUCE_AVG, CV_32F); cv::reduce(interMap, projectedMap, 0, cv::REDUCE_AVG, CV_32F);
//差分过滤(TODO:加高斯滤波) //差分过滤(TODO:加高斯滤波)
float *pFilteredMap = new float[szMap.width * sizeof(float_t)]; float *pFilteredMap = new float[szMap.width];
cv::Mat filteredMap(cv::Size(szMap.width, 1), CV_32FC1, pFilteredMap); cv::Mat filteredMap(cv::Size(szMap.width, 1), CV_32FC1, pFilteredMap);
cv::sepFilter2D(projectedMap, filteredMap, CV_32F, whalf, cv::Mat::ones(1, 1, CV_32F)); cv::sepFilter2D(projectedMap, filteredMap, CV_32F, whalf, cv::Mat::ones(1, 1, CV_32F));
//投影峰值查找 //投影峰值查找
...@@ -581,7 +586,7 @@ int eyemPolarTrans(EyemImage tpImage, EyemOcsDXY tpCenter, int iRadius, int iSap ...@@ -581,7 +586,7 @@ int eyemPolarTrans(EyemImage tpImage, EyemOcsDXY tpCenter, int iRadius, int iSap
return FUNC_OK; return FUNC_OK;
} }
bool eyemEdge1dGenMeasureFree(IntPtr hObject) bool eyemEdge1dGenFree(IntPtr hObject)
{ {
std::vector<EyemOcsDXY> *tpEdges = reinterpret_cast<std::vector<EyemOcsDXY>*>(hObject); std::vector<EyemOcsDXY> *tpEdges = reinterpret_cast<std::vector<EyemOcsDXY>*>(hObject);
delete tpEdges; delete tpEdges;
......
...@@ -779,6 +779,3 @@ int eyemRobustFitEllipse(int iPtnNum, EyemOcsDXY * taPoint, int iCalcMode, doubl ...@@ -779,6 +779,3 @@ int eyemRobustFitEllipse(int iPtnNum, EyemOcsDXY * taPoint, int iCalcMode, doubl
return FUNC_OK; return FUNC_OK;
} }
...@@ -91,7 +91,8 @@ int eyemImageReadRaw(const char *filename, int iWidth, int iHeight, int iDepth, ...@@ -91,7 +91,8 @@ int eyemImageReadRaw(const char *filename, int iWidth, int iHeight, int iDepth,
{ {
if (std::strlen(filename) == 0) if (std::strlen(filename) == 0)
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
//
//tpImage->iChannels = 1; tpImage->iDepth = 2; tpImage->iWidth = iWidth; tpImage->iHeight = iHeight;
FILE *fp = fopen(filename, "rb+"); FILE *fp = fopen(filename, "rb+");
if (NULL != fp) if (NULL != fp)
{ {
...@@ -118,7 +119,6 @@ int eyemImageReadRaw(const char *filename, int iWidth, int iHeight, int iDepth, ...@@ -118,7 +119,6 @@ int eyemImageReadRaw(const char *filename, int iWidth, int iHeight, int iDepth,
} }
else else
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
//关闭文件 //关闭文件
fclose(fp); fclose(fp);
return FUNC_OK; return FUNC_OK;
...@@ -262,11 +262,9 @@ bool eyemVideoCaptureFree(IntPtr hObject) ...@@ -262,11 +262,9 @@ bool eyemVideoCaptureFree(IntPtr hObject)
} }
//清空 //清空
tpImages->clear(); tpImages->clear();
//释放 //释放
delete tpImages; delete tpImages;
tpImages = NULL; tpImages = NULL;
return true; return true;
} }
......
...@@ -688,7 +688,7 @@ extern "C" { ...@@ -688,7 +688,7 @@ extern "C" {
EXPORTS int eyemEdge1dFindCircle(EyemImage tpImage, EyemOcsDXY tpPoint, int iRadius, int iCapLength, int iCapWidth, int nCalipers, int nFilterSize, int iSearchDirec, double dAmpThreshold, const char *ccTransition, IntPtr *hObject); EXPORTS int eyemEdge1dFindCircle(EyemImage tpImage, EyemOcsDXY tpPoint, int iRadius, int iCapLength, int iCapWidth, int nCalipers, int nFilterSize, int iSearchDirec, double dAmpThreshold, const char *ccTransition, IntPtr *hObject);
EXPORTS int eyemEdge1dFindLine(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLineEd, int iCapLength, int iCapWidth, int nCalipers, int iFilterSize, int iSearchDirec, double dAmpThreshold, const char *ccTransition, IntPtr *hObject); EXPORTS int eyemEdge1dFindLine(EyemImage tpImage, EyemOcsDXY tpLineSt, EyemOcsDXY tpLineEd, int iCapLength, int iCapWidth, int nCalipers, int iFilterSize, int iSearchDirec, double dAmpThreshold, const char *ccTransition, IntPtr *hObject);
EXPORTS int eyemPolarTrans(EyemImage tpImage, EyemOcsDXY tpCenter, int iRadius, int iSapWidth); EXPORTS int eyemPolarTrans(EyemImage tpImage, EyemOcsDXY tpCenter, int iRadius, int iSapWidth);
EXPORTS bool eyemEdge1dGenMeasureFree(IntPtr hObject); EXPORTS bool eyemEdge1dGenFree(IntPtr hObject);
#ifdef __cplusplus #ifdef __cplusplus
} }
...@@ -925,7 +925,7 @@ extern "C" { ...@@ -925,7 +925,7 @@ extern "C" {
EXPORTS int eyemInsertModel(IntPtr hModelID, const char *ccTplName); EXPORTS int eyemInsertModel(IntPtr hModelID, const char *ccTplName);
EXPORTS int eyemRemoveModelByName(IntPtr hModelID, const char *ccTplName); EXPORTS int eyemRemoveModelByName(IntPtr hModelID, const char *ccTplName);
EXPORTS int eyemReleaseModel(IntPtr &hModelID); EXPORTS int eyemReleaseModel(IntPtr &hModelID);
EXPORTS int eyemTrackFeature(EyemImage tpPrevImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum, int *ipResults, EyemImage *tpDstImg); EXPORTS int eyemTrackFeature(EyemImage tpImage, EyemImage tpMask, EyemRect tpRoi, EyemRect *tpRois, int iRoiNum, EyemHSVModel tpHSVModel, int *ipResults, EyemImage *tpDstImg);
EXPORTS int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum); EXPORTS int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum);
EXPORTS int eyemMarkerTracing(EyemImage tpImage, EyemHSVModel tpHSVModel, EyemOcsFXYR *tpCircle, EyemImage *tpDstImg, bool bHighAccuracy = false); EXPORTS int eyemMarkerTracing(EyemImage tpImage, EyemHSVModel tpHSVModel, EyemOcsFXYR *tpCircle, EyemImage *tpDstImg, bool bHighAccuracy = false);
EXPORTS int eyemDetectCircleUseHough(EyemImage tpImage, EyemRect tpRoi, EyemRect limRoi, EyemOcsDXYR *tpCircle, EyemImage *tpDstImg, double dp, double dMinDist, double dParam1, double dParam2, double dMinRadius, double dMaxRadius, int iMethod = 3, bool useValLimit = false); EXPORTS int eyemDetectCircleUseHough(EyemImage tpImage, EyemRect tpRoi, EyemRect limRoi, EyemOcsDXYR *tpCircle, EyemImage *tpDstImg, double dp, double dMinDist, double dParam1, double dParam2, double dMinRadius, double dMaxRadius, int iMethod = 3, bool useValLimit = false);
......
此文件类型无法预览
...@@ -74,8 +74,8 @@ ...@@ -74,8 +74,8 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>D:\opencv420\build\include;D:\opencv420\build\include\opencv2;D:\tbb2017_20170604oss\include;D:\zxing-cpp-master\core\src;D:\zxing-cpp-master\opencv\src;D:\darknet\include;D:\3rdparty\pthreads\include;$(IncludePath)</IncludePath> <IncludePath>D:\opencv420\build\include;D:\opencv420\build\include\opencv2;D:\tbb2017_20170604oss\include;D:\zxing-cpp-master\core\src;D:\zxing-cpp-master\opencv\src;$(IncludePath)</IncludePath>
<LibraryPath>D:\opencv420\build\x64\vc14\lib;D:\tbb2017_20170604oss\lib\intel64\vc14;D:\zxing-cpp-master\build\Debug;D:\darknet\lib;D:\3rdparty\pthreads\lib;$(LibraryPath)</LibraryPath> <LibraryPath>D:\opencv420\build\x64\vc14\lib;D:\tbb2017_20170604oss\lib\intel64\vc14;D:\zxing-cpp-master\build\Debug;$(LibraryPath)</LibraryPath>
<TargetExt>.dll</TargetExt> <TargetExt>.dll</TargetExt>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libdmtx.lib;libzxing-debug.lib;libdecoded.lib;darknetd.lib;pthreadVC2.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libdmtx.lib;libzxing-debug.lib;libdecoded.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
......
...@@ -410,14 +410,11 @@ int eyemBitwiseNot(EyemImage &tpImage) ...@@ -410,14 +410,11 @@ int eyemBitwiseNot(EyemImage &tpImage)
int eyemCvtImageType(EyemImage tpImage, const char *ccSubType, double alpha, double beta, EyemImage &tpDstImg) int eyemCvtImageType(EyemImage tpImage, const char *ccSubType, double alpha, double beta, EyemImage &tpDstImg)
{ {
CV_Assert(NULL != tpImage.vpImage); CV_Assert(NULL != tpImage.vpImage);
cv::Mat _src = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone(); cv::Mat _src = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
//在这里重新创建 //在这里重新创建
if (NULL != tpDstImg.vpImage) { if (NULL != tpDstImg.vpImage) {
_free(tpDstImg); _free(tpDstImg);
} }
//内存尺寸(图像数据类型转换不涉及通道、尺寸) //内存尺寸(图像数据类型转换不涉及通道、尺寸)
int _Size = tpImage.iWidth*tpImage.iHeight*tpImage.iChannels; int _Size = tpImage.iWidth*tpImage.iHeight*tpImage.iChannels;
......
...@@ -139,8 +139,6 @@ double shape_based_matching::find_shape_model(cv::Mat tpImage, double minScore, ...@@ -139,8 +139,6 @@ double shape_based_matching::find_shape_model(cv::Mat tpImage, double minScore,
} }
draw_match_shapes(showMat, resultPoint, cv::Scalar(151, 243, 121), 1); draw_match_shapes(showMat, resultPoint, cv::Scalar(151, 243, 121), 1);
} }
cv::imwrite("result.png", showMat);
return 0; return 0;
} }
...@@ -154,8 +152,11 @@ void shape_based_matching::draw_match_shapes(cv::Mat &showMat, cv::Point cog, cv ...@@ -154,8 +152,11 @@ void shape_based_matching::draw_match_shapes(cv::Mat &showMat, cv::Point cog, cv
contours.push_back(results[i].Offset + cv::Point2d(cog)); contours.push_back(results[i].Offset + cv::Point2d(cog));
} }
for (auto&point : contours) { for (auto&point : contours) {
if (point.x > 0 && point.x < showMat.cols&&point.y>0 && point.y < showMat.rows)
{
showMat.at<cv::Vec3b>(point) = cv::Vec3b((uchar)color[0], (uchar)color[1], (uchar)color[2]); showMat.at<cv::Vec3b>(point) = cv::Vec3b((uchar)color[0], (uchar)color[1], (uchar)color[2]);
} }
}
} }
int eyemMakeShapeModel(EyemImage tpImage, double dContrast, double dMinContrast, int iApertureSize, bool bL2gradient) int eyemMakeShapeModel(EyemImage tpImage, double dContrast, double dMinContrast, int iApertureSize, bool bL2gradient)
......
...@@ -546,6 +546,23 @@ static double getThreshVal_Otsu_8u(const cv::Mat& _src) ...@@ -546,6 +546,23 @@ static double getThreshVal_Otsu_8u(const cv::Mat& _src)
return max_val; return max_val;
} }
static double getThreshVal_Otsu_8u_mask(const cv::Mat& _src, const cv::Mat& _mask)
{
std::vector<uint8_t> data;
for (int y = 0; y < _mask.rows; y++) {
for (int x = 0; x < _mask.cols; x++) {
if (_mask.ptr<uint8_t>(y)[x] == 255) {
data.push_back(_src.ptr<uint8_t>(y)[x]);
}
}
}
int elemSize = cvFloor(sqrt((float)data.size()));
std::vector<uint8_t> pixVal(elemSize*elemSize);
//拷贝指定部分
memcpy(&pixVal[0], &data[0], elemSize*elemSize);
return getThreshVal_Otsu_8u(cv::Mat(elemSize, elemSize, CV_8UC1, &pixVal[0]));
}
/** 计算元件尺寸 /** 计算元件尺寸
srcPrev 输入图像 srcPrev 输入图像
mask 输入掩膜 mask 输入掩膜
...@@ -4506,10 +4523,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -4506,10 +4523,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
double match; double match;
tMap() {} tMap() {}
tMap(TE te, double match) :te(te), match(match) {} tMap(TE te, double match) :te(te), match(match) {}
bool operator >(const tMap &te)const
{
return match > te.match;
}
bool operator <(const tMap &te)const bool operator <(const tMap &te)const
{ {
return match < te.match; return match < te.match;
...@@ -4525,12 +4538,14 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -4525,12 +4538,14 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
} }
tMaps.push_back(tMap(Tes[i], sumMatch)); tMaps.push_back(tMap(Tes[i], sumMatch));
} }
if (tMaps.empty())
return FUNC_CANNOT_CALC;
//排序 //排序
std::sort(tMaps.begin(), tMaps.end(), std::less<tMap>()); std::sort(tMaps.begin(), tMaps.end(), std::less<tMap>());
//确定单个元件尺寸与灰度值 //确定单个元件尺寸与灰度值
double sinPartsArea = tMaps[0].te.Area; double sinPartsMean = tMaps[0].te.Mean; double sinPartsArea = tMaps[0].te.Area; double sinPartsMean = tMaps[0].te.Mean;
//根据灰度值重新进行二值化 //根据灰度值重新进行二值化
cv::threshold(srcPrev, binary, sinPartsMean*0.75, 255, cv::THRESH_BINARY); cv::threshold(srcPrev, binary, sinPartsMean*0.85, 255, cv::THRESH_BINARY);
//重新计算连通域 //重新计算连通域
nccomps = cv::connectedComponentsWithStats(binary, labels, stats, centroids); nccomps = cv::connectedComponentsWithStats(binary, labels, stats, centroids);
//对连通域过滤 //对连通域过滤
...@@ -4673,7 +4688,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in ...@@ -4673,7 +4688,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
cv::Mat bin; cv::Mat bin;
cv::threshold(dst, bin, 10, 255, cv::THRESH_BINARY); cv::threshold(dst, bin, 10, 255, cv::THRESH_BINARY);
//连接在一起 //连接在一起
cv::morphologyEx(bin, bin, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(45, 45))); cv::morphologyEx(bin, bin, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(45, 45)));
//获取最大轮廓 //获取最大轮廓
std::vector<std::vector<cv::Point>> _contours; std::vector<std::vector<cv::Point>> _contours;
...@@ -4732,7 +4747,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in ...@@ -4732,7 +4747,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
cv::Mat binary; cv::Mat binary;
cv::threshold(src8U, binary, (255 - backThresh), 255, cv::THRESH_BINARY); cv::threshold(src8U, binary, (255 - backThresh), 255, cv::THRESH_BINARY);
//连接在一起 //连接在一起
cv::morphologyEx(binary, binary, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(45, 45))); cv::morphologyEx(binary, binary, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(75, 75)));
//寻找料盘 //寻找料盘
std::vector<std::vector<cv::Point>> contoursFilter; std::vector<std::vector<cv::Point>> contoursFilter;
cv::findContours(binary, contoursFilter, cv::RETR_TREE, cv::CHAIN_APPROX_NONE); cv::findContours(binary, contoursFilter, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
...@@ -4860,7 +4875,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in ...@@ -4860,7 +4875,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
//判断适用哪种算法 //判断适用哪种算法
if (!useTrackMethod) if (!useTrackMethod)
{ {
const int filterSize = 17;//因为移远改成17,原12 const int filterSize = 12;//因为移远改成17,原12
//去掉料盘深色部分干扰 //去掉料盘深色部分干扰
const int winSize = sinPartSize > 15 ? 5 : 3;//对于部分器件过小的窗口会漏料 const int winSize = sinPartSize > 15 ? 5 : 3;//对于部分器件过小的窗口会漏料
cv::Mat srcPrevEx; cv::Mat srcPrevEx;
...@@ -7087,6 +7102,7 @@ int eyemAchvMatchMat(EyemImage tpImage, EyemRect tpRoi, EyemImage *tpDstImg) ...@@ -7087,6 +7102,7 @@ int eyemAchvMatchMat(EyemImage tpImage, EyemRect tpRoi, EyemImage *tpDstImg)
}); });
//方便显示 //方便显示
cc += cv::Scalar((162 - backThresh), (162 - backThresh), (162 - backThresh)); cc += cv::Scalar((162 - backThresh), (162 - backThresh), (162 - backThresh));
output += cv::Scalar(162 - backThresh);
//inv //inv
cv::bitwise_not(src8U, src8U); cv::bitwise_not(src8U, src8U);
cv::Mat binary; cv::Mat binary;
...@@ -7168,7 +7184,7 @@ int eyemAchvMatchMat(EyemImage tpImage, EyemRect tpRoi, EyemImage *tpDstImg) ...@@ -7168,7 +7184,7 @@ int eyemAchvMatchMat(EyemImage tpImage, EyemRect tpRoi, EyemImage *tpDstImg)
} }
//保存中间图作为匹配 //保存中间图作为匹配
cv::Point mid = idx[idx.size() / 2]; cv::Point mid = idx[idx.size() / 2];
templateMat = src8U(cv::Rect(cv::Point(mid.x - 64, mid.y - 64), cv::Point(mid.x + 64, mid.y + 64))&cv::Rect(0, 0, X, Y)).clone(); templateMat = output(cv::Rect(cv::Point(mid.x - 64, mid.y - 64), cv::Point(mid.x + 64, mid.y + 64))&cv::Rect(0, 0, X, Y)).clone();
cv::cvtColor(templateMat, templateMat, cv::COLOR_GRAY2RGB); cv::cvtColor(templateMat, templateMat, cv::COLOR_GRAY2RGB);
break; break;
} }
...@@ -7411,7 +7427,6 @@ int eyemAchvModelByName(const char *ccTplName, IntPtr hModelID, EyemModelID &tpM ...@@ -7411,7 +7427,6 @@ int eyemAchvModelByName(const char *ccTplName, IntPtr hModelID, EyemModelID &tpM
break; break;
} }
} }
return FUNC_OK; return FUNC_OK;
} }
...@@ -7419,13 +7434,10 @@ int eyemInsertModel(IntPtr hModelID, const char *ccTplName) ...@@ -7419,13 +7434,10 @@ int eyemInsertModel(IntPtr hModelID, const char *ccTplName)
{ {
std::string logModule = ""; std::string logModule = "";
logModule += __func__; logModule += __func__;
logModule += "(" + std::to_string(*(uint32_t *)(&std::this_thread::get_id())) + "):"; logModule += "(" + std::to_string(*(uint32_t *)(&std::this_thread::get_id())) + "):";
if (NULL == hModelID) if (NULL == hModelID)
return FUNC_CANNOT_CALC; return FUNC_CANNOT_CALC;
logger.t(logModule + "从指针获取模板对象..."); logger.t(logModule + "从指针获取模板对象...");
std::vector<EyemModelID> *tpModelID = reinterpret_cast<std::vector<EyemModelID>*>(hModelID); std::vector<EyemModelID> *tpModelID = reinterpret_cast<std::vector<EyemModelID>*>(hModelID);
...@@ -7439,7 +7451,6 @@ int eyemInsertModel(IntPtr hModelID, const char *ccTplName) ...@@ -7439,7 +7451,6 @@ int eyemInsertModel(IntPtr hModelID, const char *ccTplName)
//加载指定模板 //加载指定模板
cv::Mat tplMat; double matchDeg; cv::Mat tplMat; double matchDeg;
try try
{ {
logger.t(logModule + "开始从本地加载模板文件..."); logger.t(logModule + "开始从本地加载模板文件...");
...@@ -7449,7 +7460,6 @@ int eyemInsertModel(IntPtr hModelID, const char *ccTplName) ...@@ -7449,7 +7460,6 @@ int eyemInsertModel(IntPtr hModelID, const char *ccTplName)
logger.t(logModule + "从本地加载模板文件异常..."); logger.t(logModule + "从本地加载模板文件异常...");
return FUNC_CANNOT_CALC; return FUNC_CANNOT_CALC;
} }
//插到容器末尾 //插到容器末尾
if (!tplMat.empty()) { if (!tplMat.empty()) {
...@@ -7501,7 +7511,6 @@ int eyemInsertModel(IntPtr hModelID, const char *ccTplName) ...@@ -7501,7 +7511,6 @@ int eyemInsertModel(IntPtr hModelID, const char *ccTplName)
else { else {
return FUNC_CANNOT_CALC; return FUNC_CANNOT_CALC;
} }
return FUNC_OK; return FUNC_OK;
} }
...@@ -7539,14 +7548,11 @@ int eyemRemoveModelByID(IntPtr hModelID, const int iTplID) ...@@ -7539,14 +7548,11 @@ int eyemRemoveModelByID(IntPtr hModelID, const int iTplID)
int eyemMatchTemplateModel(EyemImage tpImage, IntPtr hModelID, char **lpszTplName) int eyemMatchTemplateModel(EyemImage tpImage, IntPtr hModelID, char **lpszTplName)
{ {
cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone(); cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
//判断图像是否存在 //判断图像是否存在
if (image.empty() || NULL == hModelID) if (image.empty() || NULL == hModelID)
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
//反转 //反转
cv::bitwise_not(image, image); cv::bitwise_not(image, image);
struct Track { struct Track {
double dMatchDeg; double dMatchDeg;
std::string tplName; std::string tplName;
...@@ -7630,14 +7636,12 @@ int eyemMatchTemplateModel(EyemImage tpImage, IntPtr hModelID, char **lpszTplNam ...@@ -7630,14 +7636,12 @@ int eyemMatchTemplateModel(EyemImage tpImage, IntPtr hModelID, char **lpszTplNam
//最匹配模板 //最匹配模板
std::string bestMatch = ""; std::string bestMatch = "";
int select = 0; int select = 0;
do do
{ {
bestMatch += tplMats[select].tplName + ","; bestMatch += tplMats[select].tplName + ",";
select++; select++;
} while (select < 5 && select < tplMats.size()); } while (select < 5 && select < tplMats.size());
//输出结果 //输出结果
*lpszTplName = (char *)CoTaskMemAlloc(bestMatch.length() + 1); *lpszTplName = (char *)CoTaskMemAlloc(bestMatch.length() + 1);
if (NULL != lpszTplName) if (NULL != lpszTplName)
...@@ -7647,7 +7651,6 @@ int eyemMatchTemplateModel(EyemImage tpImage, IntPtr hModelID, char **lpszTplNam ...@@ -7647,7 +7651,6 @@ int eyemMatchTemplateModel(EyemImage tpImage, IntPtr hModelID, char **lpszTplNam
else { else {
return FUNC_NOT_ENOUGH_MEM; return FUNC_NOT_ENOUGH_MEM;
} }
return FUNC_OK; return FUNC_OK;
} }
...@@ -7671,67 +7674,161 @@ int eyemReleaseModel(IntPtr &hModelID) ...@@ -7671,67 +7674,161 @@ int eyemReleaseModel(IntPtr &hModelID)
return FUNC_OK; return FUNC_OK;
} }
int eyemTrackFeature(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum, int *ipResults, EyemImage *tpDstImg) int eyemTrackFeature(EyemImage tpImage, EyemImage tpMask, EyemRect tpRoi, EyemRect *tpRois, int iRoiNum, EyemHSVModel tpHSVModel, int *ipResults, EyemImage *tpDstImg)
{ {
cv::Mat refImg = cv::Mat(tpRefImg.iHeight, tpRefImg.iWidth, MAKETYPE(tpRefImg.iDepth, tpRefImg.iChannels), tpRefImg.vpImage).clone(); cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
cv::Mat nextImg = cv::Mat(tpNextImg.iHeight, tpNextImg.iWidth, MAKETYPE(tpNextImg.iDepth, tpNextImg.iChannels), tpNextImg.vpImage).clone(); if (image.empty())
if (refImg.empty() | nextImg.empty())
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
//显示图像
cv::Mat showMat; if (image.channels() == 4) {
showMat = nextImg.clone(); cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
//转灰度图像 }
if (refImg.channels() != 1) {
cv::cvtColor(refImg, refImg, cv::COLOR_BGR2GRAY); cv::Mat mask = cv::Mat(tpMask.iHeight, tpMask.iWidth, MAKETYPE(tpMask.iDepth, tpMask.iChannels), tpMask.vpImage).clone();
if (mask.empty())
return FUNC_IMAGE_NOT_EXIST;
if (mask.channels() != 1) {
cv::cvtColor(mask, mask, cv::COLOR_BGR2GRAY);
} }
if (nextImg.channels() != 1) {
cv::cvtColor(nextImg, nextImg, cv::COLOR_BGR2GRAY); //判断图像是否符合
if (image.channels() == 1 || mask.channels() != 1) {
return FUNC_ILLEGAL_ARGUMENT;
} }
cv::Mat dst;
cv::absdiff(nextImg, refImg, dst);
cv::Mat binary; //cv::copyMakeBorder(image, image, 0, 8, 0, 0, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
cv::threshold(dst, binary, 25, 255, cv::THRESH_BINARY);
const int X = image.cols; const int Y = image.rows;
//滤波
cv::blur(image, image, cv::Size(5, 5));
//用于显示
cv::Mat cc;
image.copyTo(cc);
//转hsv空间
cv::Mat imgHSV;
cv::cvtColor(image, imgHSV, cv::COLOR_BGR2HSV);
//红色比较特殊,分两个区间
cv::Mat mask1, mask2(cv::Size(X, Y), CV_8UC1, cv::Scalar(0));
cv::inRange(imgHSV, cv::Scalar(tpHSVModel.dpRangeL[0], tpHSVModel.dpRangeL[1], tpHSVModel.dpRangeL[2]),
cv::Scalar(tpHSVModel.dpRangeU[0], tpHSVModel.dpRangeU[1], tpHSVModel.dpRangeU[2]), mask1);
//多个分割阈值
if ((tpHSVModel.dpRangeLExt[0] + tpHSVModel.dpRangeLExt[1] + tpHSVModel.dpRangeLExt[2]) != 0 ||
(tpHSVModel.dpRangeUExt[0] + tpHSVModel.dpRangeUExt[1] + tpHSVModel.dpRangeUExt[2]) != 0) {
cv::inRange(imgHSV, cv::Scalar(tpHSVModel.dpRangeLExt[0], tpHSVModel.dpRangeLExt[1], tpHSVModel.dpRangeLExt[2]),
cv::Scalar(tpHSVModel.dpRangeUExt[0], tpHSVModel.dpRangeUExt[1], tpHSVModel.dpRangeUExt[2]), mask2);
}
//合并
cv::Mat maskj;
cv::bitwise_or(mask1, mask2, maskj);
//腐蚀处理掉一些干扰
cv::morphologyEx(maskj, maskj, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)));
//将皮带部分融合
cv::morphologyEx(maskj, maskj, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15)));
//判断图像尺寸是否符合
if (image.cols != mask.cols || image.rows != mask.rows) {
return FUNC_ILLEGAL_ARGUMENT;
}
//分割出目标
cv::Mat target;
cv::bitwise_xor(maskj, mask, target);
//去掉干扰
cv::morphologyEx(target, target, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15)));
cv::Mat labels, stats, centroids;
int nccomps = cv::connectedComponentsWithStats(target, labels, stats, centroids);
//过滤连通域面积不符合的
std::vector<uchar> colors(nccomps + 1, 0); std::vector<cv::Rect> targets;
for (int i = 1; i < nccomps; i++) {
colors[i] = 255;
double dArea = (double)stats.ptr<int>(i)[cv::CC_STAT_AREA];
if (dArea < 11000)
{
colors[i] = 0;
}
else {
targets.push_back(cv::Rect(stats.ptr<int>(i)[cv::CC_STAT_LEFT], stats.ptr<int>(i)[cv::CC_STAT_TOP],
stats.ptr<int>(i)[cv::CC_STAT_WIDTH], stats.ptr<int>(i)[cv::CC_STAT_HEIGHT]));
}
}
//过滤
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range& range)->void {
for (int y = range.start; y < range.end; y++)
{
uint8_t *ptrRow = target.ptr<uint8_t>(y);
for (int x = 0; x < X; x++)
{
int label = labels.ptr<int>(y)[x];
CV_Assert(0 <= label && label <= nccomps);
ptrRow[x] = colors[label];
}
}
});
//判断有无料盘
if (targets.empty()) {
return FUNC_FAILED_DETECT;
}
//判断料盘位置
for (int i = 0; i < iRoiNum; i++) for (int i = 0; i < iRoiNum; i++)
{ {
cv::Mat labels, stats, centroids; for (auto&it : targets)
int nccomps = cv::connectedComponentsWithStats(binary(cv::Rect(tpRois[i].iXs, tpRois[i].iYs, tpRois[i].iWidth, tpRois[i].iHeight)), \
labels, stats, centroids);
//判断结果
if (((double)cv::countNonZero(labels) / (double(tpRois[i].iWidth*(double)tpRois[i].iHeight))) > tpRois[i].dVar)
{ {
if (cv::Rect(tpRois[i].iXs, tpRois[i].iYs, tpRois[i].iWidth, tpRois[i].iHeight).contains((it.tl() + it.br()) / 2)) {
ipResults[i] = 1; ipResults[i] = 1;
} }
else }
ipResults[i] = 0; }
//寻找轮廓 for (int idx = 0; idx < targets.size(); idx++) {
std::vector<std::vector<cv::Point>> contours; cv::Rect bbox = targets[idx] & cv::Rect(0, 0, X, Y);
cv::findContours(binary(cv::Rect(tpRois[i].iXs, tpRois[i].iYs, tpRois[i].iWidth, tpRois[i].iHeight)), contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE); //标签
std::string label = "Reel";
int baseLine;
cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 1.5, 2, &baseLine);
cv::Scalar pal(0, 255, 255);
cv::rectangle(cc, bbox, pal);
cv::rectangle(cc, cv::Point(bbox.x, bbox.y - labelSize.height - baseLine), cv::Point(bbox.x + labelSize.width, bbox.y), pal, cv::FILLED);
cv::putText(cc, label, cv::Point(bbox.tl().x + 2, bbox.tl().y - baseLine + 2), cv::FONT_HERSHEY_SIMPLEX, 1.5, cv::Scalar(0, 0, 0), 2);
}
//画图 //透明蒙版
for (int j = 0; j < contours.size(); j++) cv::Mat transpMask;
{ image.copyTo(transpMask);
cv::drawContours(showMat, contours, j, cv::Scalar(0, 0, 255), 3, 8, cv::noArray(), 2147483647, cv::Point(tpRois[i].iXs, tpRois[i].iYs));
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range range)->void {
for (int y = range.start; y < range.end; y++) {
for (int x = 0; x < X; x++) {
if (maskj.ptr<uint8_t>(y)[x] == 255) {
transpMask.ptr<cv::Vec3b>(y)[x] = cv::Vec3b(0, 200, 0);
} }
if (target.ptr<uint8_t>(y)[x] == 255) {
transpMask.ptr<cv::Vec3b>(y)[x] = cv::Vec3b(0, 0, 200);
} }
//<输出结果图像 }
{ }
tpDstImg->iWidth = showMat.cols; tpDstImg->iHeight = showMat.rows; tpDstImg->iDepth = showMat.depth(); tpDstImg->iChannels = showMat.channels(); });
cv::addWeighted(cc, 0.7, transpMask, 0.3, 0, cc);
//<输出结果图像
tpDstImg->iWidth = cc.cols; tpDstImg->iHeight = cc.rows; tpDstImg->iDepth = cc.depth(); tpDstImg->iChannels = cc.channels();
//内存尺寸 //内存尺寸
int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t); int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t);
//分配初始化内存 //分配初始化内存
tpDstImg->vpImage = (uint8_t *)malloc(_Size); tpDstImg->vpImage = (uint8_t *)malloc(_Size);
if (NULL == tpDstImg->vpImage) if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM; return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size); memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据 //拷贝数据
memcpy(tpDstImg->vpImage, showMat.data, _Size); memcpy(tpDstImg->vpImage, cc.data, _Size);
}
return FUNC_OK; return FUNC_OK;
} }
...@@ -7894,7 +7991,7 @@ int eyemMarkerTracing(EyemImage tpImage, EyemHSVModel tpHSVModel, EyemOcsFXYR *t ...@@ -7894,7 +7991,7 @@ int eyemMarkerTracing(EyemImage tpImage, EyemHSVModel tpHSVModel, EyemOcsFXYR *t
tpCircle->fY = (float)_tpCircle.dY; tpCircle->fY = (float)_tpCircle.dY;
tpCircle->fR = (float)_tpCircle.dR; tpCircle->fR = (float)_tpCircle.dR;
//释放 //释放
eyemEdge1dGenMeasureFree(hObject); eyemEdge1dGenFree(hObject);
} }
else { else {
//输出 //输出
...@@ -8174,6 +8271,7 @@ int eyemTrainImageSampler(EyemImage tpImage, int iSize, const char *ccClassName, ...@@ -8174,6 +8271,7 @@ int eyemTrainImageSampler(EyemImage tpImage, int iSize, const char *ccClassName,
}); });
//方便显示 //方便显示
cc += cv::Scalar((162 - backThresh), (162 - backThresh), (162 - backThresh)); cc += cv::Scalar((162 - backThresh), (162 - backThresh), (162 - backThresh));
output += cv::Scalar(162 - backThresh);
//inv //inv
cv::bitwise_not(src8U, src8U); cv::bitwise_not(src8U, src8U);
cv::Mat binary; cv::Mat binary;
...@@ -8255,17 +8353,17 @@ int eyemTrainImageSampler(EyemImage tpImage, int iSize, const char *ccClassName, ...@@ -8255,17 +8353,17 @@ int eyemTrainImageSampler(EyemImage tpImage, int iSize, const char *ccClassName,
if (ofset.x == 0 && ofset.y == 0) if (ofset.x == 0 && ofset.y == 0)
{ {
cv::Point mid = idx[idx.size() / 2]; cv::Point mid = idx[idx.size() / 2];
templateMat = src8U(cv::Rect(cv::Point(mid.x - 64, mid.y - 64), cv::Point(mid.x + 64, mid.y + 64))&cv::Rect(0, 0, X, Y)).clone(); templateMat = output(cv::Rect(cv::Point(mid.x - 64, mid.y - 64), cv::Point(mid.x + 64, mid.y + 64))&cv::Rect(0, 0, X, Y)).clone();
cv::cvtColor(templateMat, templateMat, cv::COLOR_GRAY2RGB); cv::cvtColor(templateMat, templateMat, cv::COLOR_GRAY2RGB);
} }
int step = (idx.size() / 27); int step = ((int)idx.size() / 27);
if (step < 1) { if (step < 1) {
step = 1; step = 1;
} }
for (int i = 0; i < idx.size() - 1; i += step) for (int i = 0; i < idx.size() - 1; i += step)
{ {
auto p = idx[i]; auto p = idx[i];
cv::Mat mat = src8U(cv::Rect(cv::Point(p.x - 64, p.y - 64), cv::Point(p.x + 64, p.y + 64))&cv::Rect(0, 0, X, Y)).clone(); cv::Mat mat = output(cv::Rect(cv::Point(p.x - 64, p.y - 64), cv::Point(p.x + 64, p.y + 64))&cv::Rect(0, 0, X, Y)).clone();
if (mat.cols == mat.rows) if (mat.cols == mat.rows)
{ {
mats.push_back(mat); mats.push_back(mat);
...@@ -8308,7 +8406,7 @@ int eyemTrainImageSampler(EyemImage tpImage, int iSize, const char *ccClassName, ...@@ -8308,7 +8406,7 @@ int eyemTrainImageSampler(EyemImage tpImage, int iSize, const char *ccClassName,
return FUNC_OK; return FUNC_OK;
} }
//#include "eyemMatchShapes.h"
#include "eyemStopwatch.h" #include "eyemStopwatch.h"
int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg) int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
{ {
...@@ -8317,33 +8415,1545 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg) ...@@ -8317,33 +8415,1545 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
if (image.empty()) if (image.empty())
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
////图像尺寸 cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
//int X = image.cols, Y = image.rows;
////用于去除黑色坏点干扰
//cv::Mat medBlur;
//cv::medianBlur(image, medBlur, 3);
////去除局部量斑影响(默认亮斑尺寸不会大于15个像素)
//cv::morphologyEx(medBlur, medBlur, cv::MORPH_ERODE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15)));
////图像增强
//double min, max;
//cv::minMaxLoc(medBlur, &min, &max, NULL);
//image.convertTo(image, CV_64FC1);
//image -= min;
//image /= (max - min);
//image *= 65535;
//image.convertTo(image, CV_16UC1);
//cv::Mat image8U;
//image.convertTo(image8U, CV_8UC1, 1 / 255.);
//cv::cvtColor(image8U, image8U, cv::COLOR_BGR2GRAY);
//cv::Mat eqhist;
//cv::equalizeHist(image8U, eqhist);
//cv::imwrite("0.png",image8U);
return FUNC_OK; return FUNC_OK;
// //转单通道
// if (image.channels() != 1)
// cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
// //图像裁剪
// image = image(cv::Rect(50, 50, image.cols - 100, image.rows - 100)).clone();
// //图像尺寸
// int X = image.cols, Y = image.rows;
// //测试用,用于去除黑色坏点干扰
// cv::Mat medBlur;
// cv::medianBlur(image, medBlur, 3);
// //去除局部量斑影响(默认亮斑尺寸不会大于15个像素)
// cv::morphologyEx(medBlur, medBlur, cv::MORPH_ERODE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15)));
// //图像增强
// double min, max;
// cv::Point maxId;
// cv::minMaxLoc(medBlur, &min, &max, NULL, &maxId);
// image.convertTo(image, CV_64FC1);
//
// image -= min;
// image /= (max - min);
// image *= 65535;
// image.convertTo(image, CV_16UC1);
//
// cv::Mat image8U;
// image.convertTo(image8U, CV_8UC1, 1 / 255.);
//
// //显示结果图像
// cv::Mat cc;
// cv::cvtColor(image8U, cc, cv::COLOR_GRAY2BGRA);
//
// //设置直方图数量
// const int histSize = 128;
// //直方图范围
// float range[] = { 0,255 };
// const float* histRange = { range };
// //统计直方图
// cv::Mat hist;
// cv::calcHist(&image8U, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange);
//
// //获取背景像素值
// int maxIdx[2] = { 255,255 };
// cv::minMaxIdx(hist, NULL, NULL, NULL, maxIdx);
// double backT = ((double)maxIdx[0] * (256.0 / (double)histSize))*0.829;
// //分割出料盘
// image8U.forEach<uint8_t>([&](uint8_t& val, const int *p)->void {
// val = val >= backT ? backT : val;
// });
// //方便显示
// cc += cv::Scalar((162 - backT), (162 - backT), (162 - backT));
// //二值化确定料盘区域
// cv::Mat binary;
// cv::threshold(image8U, binary, backT, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
// //连接在一起(这里主要确定料盘可以膨胀,膨胀也能避免仅剩一圈被漏掉的情况)
// cv::morphologyEx(binary, binary, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(25, 25)), cv::Point(-1, -1), 2);
// //寻找料盘
// std::vector<std::vector<cv::Point>> contoursFilter;
// cv::findContours(binary, contoursFilter, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
// //填充内部确定料盘
// cv::Mat image4Loc = cv::Mat::zeros(image8U.size(), CV_8UC1);
// for (int i = 0; i < contoursFilter.size(); i++)
// {
// //根据尺寸判断是不是料盘
// cv::Rect bbox = cv::boundingRect(contoursFilter[i]);
// if (cv::contourArea(contoursFilter[i]) > 100000 && cv::min(bbox.height, bbox.width) > 300)
// {
// cv::drawContours(image4Loc, contoursFilter, i, cv::Scalar(255), -1);
// }
// }
// //剩下即料盘区域(面积大于100000均认为是料盘)
// cv::findContours(image4Loc, contoursFilter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// //区分多个料盘
// struct TrayPos
// {
// int iDir = -1;//0左上1左下2右下3右上
// double dBackThresh;
// bool bSorted;
// cv::Point2f Center;
// cv::Mat Tray;
// cv::Rect BBox;
// TrayPos() {};
// TrayPos(cv::Point2f center, cv::Mat tray, cv::Rect BBox, bool bSorted, double dBackThresh) :Center(center), Tray(tray), BBox(BBox), bSorted(bSorted), dBackThresh(dBackThresh) {}
// };
// std::vector <TrayPos> trays;
// for (int i = 0; i < contoursFilter.size(); i++)
// {
// //定位中心
// cv::Moments mu = cv::moments(contoursFilter[i]);
// cv::Point reelCenter(cvRound(mu.m10 / mu.m00), cvRound(mu.m01 / mu.m00));
// //掩膜
// cv::Mat trayMask = cv::Mat::zeros(Y, X, CV_8UC1);
// cv::drawContours(trayMask, contoursFilter, i, cv::Scalar(255), -1);
// //拷贝料盘区域
// cv::Mat tray = cv::Mat(Y, X, CV_8UC1, backT);
// image8U.copyTo(tray, trayMask);
// trays.push_back(TrayPos(reelCenter, tray, cv::boundingRect(contoursFilter[i]), false, backT));
// }
// //判断可能无料,不能100%判断
// if (trays.size() < 1) {
// //for (int i = 0; i < 4; i++) {
// // ipReelNum[i] = 0;
// //}
// return FUNC_CANNOT_CALC;
// }
// //图像中心
// cv::Point reelCenter(X / 2, Y / 2);
// //料盘排序
// std::vector <TrayPos> sortedTrays;
// for (int i = 0; i < trays.size(); i++)
// {
// //左上角
// if ((int)trays[i].Center.x <= reelCenter.x && (int)trays[i].Center.y <= reelCenter.y)
// {
// if (trays[i].bSorted == false)
// {
// trays[i].iDir = 0;
// trays[i].bSorted = true;
// sortedTrays.push_back(trays[i]);
// }
// }
// }
// for (int i = 0; i < trays.size(); i++)
// {
// //左下角
// if ((int)trays[i].Center.x <= reelCenter.x && (int)trays[i].Center.y >= reelCenter.y)
// {
// if (trays[i].bSorted == false)
// {
// trays[i].iDir = 1;
// trays[i].bSorted = true;
// sortedTrays.push_back(trays[i]);
// }
// }
// }
// for (int i = 0; i < trays.size(); i++)
// {
// //右下角
// if ((int)trays[i].Center.x >= reelCenter.x && (int)trays[i].Center.y >= reelCenter.y)
// {
// if (trays[i].bSorted == false)
// {
// trays[i].iDir = 2;
// trays[i].bSorted = true;
// sortedTrays.push_back(trays[i]);
// }
// }
// }
// for (int i = 0; i < trays.size(); i++)
// {
// //右上角
// if ((int)trays[i].Center.x >= reelCenter.x && (int)trays[i].Center.y <= reelCenter.y)
// {
// if (trays[i].bSorted == false)
// {
// trays[i].iDir = 3;
// trays[i].bSorted = true;
// sortedTrays.push_back(trays[i]);
// }
// }
// }
// image = image4Loc;
// //分料盘计数(这一步已经确定每一个sortedTrays对象必包含料盘)
// std::vector<int> trayNum(4);
// const char icvCodeDeltas[3][3][2] = { { { 0, -1 },{ 1, -1 },{ 1, 0 } },{ { 1, 1 },{ 0, 1 },{ -1, 1 } },{ { -1, 0 },{ -1, -1 },{ 0, -1 } } };
// for (int i = 0; i < sortedTrays.size(); i++)
// {
// cv::Mat srcPrev;
// cv::bitwise_not(sortedTrays[i].Tray, srcPrev);
// //备份
// cv::Mat srcPrevB = srcPrev.clone();
// //二值化
// cv::Mat sinParts;
// cv::threshold(srcPrev(sortedTrays[i].BBox), sinParts, backT, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
// //填充像素
// cv::copyMakeBorder(sinParts, sinParts, 75, 75, 75, 75, cv::BORDER_CONSTANT, cv::Scalar(0));
// //将背景部分填充
// cv::Mat mask;
// cv::morphologyEx(sinParts, mask, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(75, 75)));
// //
// cv::Mat srcPrevb = srcPrev(sortedTrays[i].BBox);
// cv::copyMakeBorder(srcPrevb, srcPrevb, 75, 75, 75, 75, cv::BORDER_CONSTANT, cv::Scalar(sortedTrays[i].dBackThresh));
//
// //获取二值化阈值(假设这一步处理后料盘背景仍存在)
// double threshVal = getThreshVal_Otsu_8u_mask(srcPrevb, mask);
// //二值化
// cv::threshold(srcPrev, binary, threshVal, 255, cv::THRESH_BINARY);
//
// //判断这些连通域相似性(从面积、平均灰度等判断)再确定阈值与面积过滤参数
// cv::Mat labels, stats, centroids;
// int nccomps = cv::connectedComponentsWithStats(binary, labels, stats, centroids);
// //统计每个连通域的信息
// struct TE
// {
// double Area, Mean;
// TE() {}
// TE(double Area, double Mean) :Area(Area), Mean(Mean) {}
// };
//
// std::vector<TE> Tes;
// for (int i = 1; i < nccomps; i++)
// {
// auto meanRect = cv::Rect(stats.ptr<int>(i)[cv::CC_STAT_LEFT], stats.ptr<int>(i)[cv::CC_STAT_TOP],
// stats.ptr<int>(i)[cv::CC_STAT_WIDTH], stats.ptr<int>(i)[cv::CC_STAT_HEIGHT]);
// cv::Mat mask = (labels(meanRect) == i);
// //计算每个连通域的最大类间方差,进行二值化
// if (stats.ptr<int>(i)[cv::CC_STAT_AREA] > 8)
// {
// cv::Mat _src = srcPrev(meanRect);
// double t = getThreshVal_Otsu_8u_mask(_src, mask);
// //
// cv::Mat _binary = _src >= t;
// _binary.copyTo(binary(meanRect));
// }
// ////默认最大元件尺寸不会超过128x128并且最小元件大于2个像素,超过此尺寸不参与计算
// //if (cv::max(meanRect.width, meanRect.height) <= 128 && stats.ptr<int>(i)[cv::CC_STAT_AREA] > 2) {
// // Tes.push_back(TE(stats.ptr<int>(i)[cv::CC_STAT_AREA], cv::mean(srcPrev(meanRect), mask)[0]));
// //}
// }
// cc = binary;
// break;
//
// //
// nccomps = cv::connectedComponentsWithStats(binary, labels, stats, centroids);
// for (int i = 1; i < nccomps; i++)
// {
// auto meanRect = cv::Rect(stats.ptr<int>(i)[cv::CC_STAT_LEFT], stats.ptr<int>(i)[cv::CC_STAT_TOP],
// stats.ptr<int>(i)[cv::CC_STAT_WIDTH], stats.ptr<int>(i)[cv::CC_STAT_HEIGHT]);
// cv::Mat mask = (labels(meanRect) == i);
// //默认最大元件尺寸不会超过128x128并且最小元件大于2个像素,超过此尺寸不参与计算
// if (cv::max(meanRect.width, meanRect.height) <= 128 && stats.ptr<int>(i)[cv::CC_STAT_AREA] > 2) {
// Tes.push_back(TE(stats.ptr<int>(i)[cv::CC_STAT_AREA], cv::mean(srcPrev(meanRect), mask)[0]));
// }
// }
// cv::Mat featureMap = cv::Mat::zeros(256, 128 * 128, CV_32FC1);
// for (auto&item : Tes)
// {
// featureMap.ptr<float_t>(cvRound(item.Mean))[cvRound(item.Area)] += 1;
// }
//
// //此时当元件过大元件尺寸可能会算错,确定相似度(每一点计算距离其他点的欧氏距离)
// struct tMap
// {
// TE te;
// double match;
// tMap() {}
// tMap(TE te, double match) :te(te), match(match) {}
// bool operator <(const tMap &te)const
// {
// return match < te.match;
// }
// bool operator >(const tMap &te)const
// {
// return match > te.match;
// }
// };
// //对特征点进行计分
// std::vector<cv::Point> idx;
// cv::findNonZero(featureMap, idx);
// //
// std::vector<tMap> tMaps;
// for (int i = 0; i < (int)idx.size(); i++)
// {
// double sumMatch = 0.0;
// for (int j = 0; j < (int)idx.size(); j++)
// {
// sumMatch += std::sqrt(std::pow(idx[i].x - idx[j].x, 2) + std::pow(idx[i].y - idx[j].y, 2))*featureMap.ptr<float>(idx[i].y)[idx[i].x];
// }
// tMaps.push_back(tMap(TE(idx[i].x, idx[i].y), sumMatch));
// }
// if (tMaps.empty())
// return FUNC_CANNOT_CALC;
// //按照分数排序
// std::sort(tMaps.begin(), tMaps.end(), std::less<tMap>());
//
// //将数据归一化
// double xmin, xmax;
// xmin = tMaps.front().match; xmax = tMaps.back().match;
// for (auto&it : tMaps)
// {
// it.match = (1.0 - (it.match - xmin) / (xmax - xmin));
// }
// //对featureMat进行计分
// for (auto&it : tMaps)
// {
// featureMap.ptr<float>(cvRound(it.te.Mean))[cvRound(it.te.Area)] *= it.match;
// }
//
// //纵向投影计算元件尺寸
// cv::Mat areaMap;
// cv::reduce(featureMap, areaMap, 0, cv::REDUCE_SUM, CV_32F);
// //横向投影计算元件灰度
// cv::Mat valMap;
// cv::reduce(featureMap, valMap, 1, cv::REDUCE_SUM, CV_32F);
//
// //确定单个元件尺寸与灰度值
// int maxIdx[2] = { 255,255 };
// cv::minMaxIdx(valMap, NULL, NULL, NULL, maxIdx);
// double sinPartsMean = maxIdx[0];
// cv::minMaxIdx(areaMap, NULL, NULL, NULL, maxIdx);
// double sinPartsArea = maxIdx[1];
//
// //判断是否使用追踪算法
// int sinPartSize = sinPartsArea;
// sinParts = binary.clone();
// bool useTrackMethod = sinPartsArea >= 14;
//
// cv::Mat m1, m2, m3;
// nccomps = cv::connectedComponentsWithStats(sinParts, m1, m2, m3);
// //判断适用哪种算法
// if (!useTrackMethod)
// {
// const int filterSize = 12;//因为移远改成17,原12
// //去掉料盘深色部分干扰
// const int winSize = sinPartSize > 15 ? 5 : 3;//对于部分器件过小的窗口会漏料
// cv::Mat srcPrevEx;
// cv::morphologyEx(srcPrev, srcPrevEx, cv::MORPH_TOPHAT, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(winSize, winSize)));
// //二值化元件区域,用OTSU还是其他?
// cv::Mat sinPartMask;
// cv::threshold(srcPrevEx, sinPartMask, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
// //连在一起
// cv::morphologyEx(sinPartMask, srcPrevEx, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)));
// //去除孔洞
// cv::morphologyEx(srcPrevEx, srcPrevEx, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(21, 21)));
// //去除深色部分备份
// cv::Mat removeDark = srcPrevEx.clone();
// //最大外包
// cv::morphologyEx(srcPrevEx, srcPrevEx, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(45, 45)));
// //定位料盘中心
// cv::findContours(srcPrevEx, contoursFilter, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
// image = cv::Scalar(0);
// for (int i = 0; i < contoursFilter.size(); i++)
// {
// cv::drawContours(image, contoursFilter, i, cv::Scalar(255), -1);
// }
// image -= srcPrevEx;
// //获取最大轮廓
// cv::findContours(image, contoursFilter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// if (contoursFilter.size() <= 0) {
// //极有可能是不满足一圈的料//2021/09/26修改
// cv::findContours(srcPrevEx, contoursFilter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// }
// std::vector<cv::Point> contourMax = contoursFilter[0];
// for (int i = 1; i < contoursFilter.size(); i++)
// {
// if (cv::contourArea(contoursFilter[i]) > cv::contourArea(contourMax))
// {
// contourMax = contoursFilter[i];
// }
// }
// //20211029修改,测试用
// cv::Rect _bboxx = cv::boundingRect(contourMax);
// if (cv::contourArea(contourMax) < 65000 || cv::min(_bboxx.width, _bboxx.height) < 300)
// continue;//不满足料盘大小,或者由于料盘颜色深影响到了定位
//
// cv::Moments mu = cv::moments(contourMax);
// cv::Point2f reelCenter(float(mu.m10 / mu.m00), float(mu.m01 / mu.m00));
// //计算最大外接圆半径
// float tFRadius = 0;
// cv::minEnclosingCircle(contourMax, cv::Point2f(), tFRadius);
// reelCenter.x = reelCenter.x > 0 && reelCenter.x < X ? reelCenter.x : 0;
// reelCenter.y = reelCenter.y > 0 && reelCenter.y < Y ? reelCenter.y : 0;
// cv::drawMarker(cc, reelCenter, cv::Scalar(0, 0, 238, 255), 1, 35, 2);
// //去掉中心1/3区域
// cv::circle(sinPartMask, reelCenter, cvRound(tFRadius / 2), cv::Scalar(0), -1);
// //20210926新增测试用
// cv::Mat llbabels;
// int totalSize = cv::connectedComponents(sinPartMask, llbabels);
// //判断为仅剩几圈的料
// if (totalSize < 265) {
// cv::Mat srcPrevEEx;
// cv::morphologyEx(srcPrev, srcPrevEEx, cv::MORPH_TOPHAT, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)));
// //非极大值抑制
// cv::Mat mask;
// cv::threshold(srcPrevEEx, mask, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
// //去掉分数过低的
// double mmval = cv::mean(srcPrevEEx, mask)[0];
// mask &= cv::Mat(srcPrevEEx >mmval*0.75);
// //
// sinPartSize = 10;
// sinPartMask = mask.clone();
// }
// //掩膜区域,用于区分处理区域
// uchar *upMask = sinPartMask.data;
// //最小料不进行粘连判断
// cv::Mat mulParts(Y, X, CV_8UC1, cv::Scalar(0));
// //
// std::vector<uchar> colors(nccomps + 1, 0);
// if (sinPartSize >= filterSize)
// {
// upMask = mulParts.data;
// //根据元件大小确定是否进行粘连处理
// for (int i = 1; i < nccomps; i++) {
// colors[i] = 0;
// if (((int *)m2.data)[(cv::CC_STAT_AREA) + (i)*m2.cols] >= 1.6*sinPartSize)//经验值
// {
// colors[i] = 255;
// }
// }
// //认为是粘连
// cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range& range)->void {
// for (int y = range.start; y < range.end; y++)
// {
// for (int x = 0; x < X; x++)
// {
// int label = ((int *)m1.data)[(x)+(y)*m1.cols];
// CV_Assert(0 <= label && label <= nccomps);
// (mulParts.data)[(x)+(y)*X] = colors[label];
// }
// }
// });
// sinParts &= removeDark;
// mulParts &= removeDark;
// sinParts -= mulParts;
// cv::circle(sinParts, reelCenter, cvRound(tFRadius / 2), cv::Scalar(0), -1);
// cv::circle(mulParts, reelCenter, cvRound(tFRadius / 2), cv::Scalar(0), -1);
// }
// //标签图像
// unsigned char *pLabelImg = (unsigned char *)malloc(Y*X * sizeof(unsigned char));
// memset(pLabelImg, 0, X*Y * sizeof(unsigned char));
// cv::Mat lbImage(Y, X, CV_8UC1, pLabelImg);
// //区分不同大小器件用不同的图处理
//#define upSrc(x, y) (srcPrev.data)[(x) + (y)*X]
// //连通域非极大值处理
// for (int y = 1; y < Y - 1; y++)
// {
// for (int x = 1; x < X - 1; x++)
// {
// //属于连通域内,并且尚未被标记
// if (upMask[(x)+(y)*X] != 0 && pLabelImg[(x)+(y)*X] != 255)
// {
// //生长种子点
// auto pixval = upSrc(x, y);
// if (pixval >= upSrc((x - 1), (y - 1)) && pixval >= upSrc((x), (y - 1)) && pixval >= upSrc((x + 1), (y - 1))\
// && pixval >= upSrc((x + 1), (y)) && pixval >= upSrc((x + 1), (y + 1)) && pixval >= upSrc((x), (y + 1))\
// && pixval >= upSrc((x - 1), (y + 1)) && pixval >= upSrc((x - 1), (y)))
// {
// //标记已处理
// pLabelImg[(x)+(y)*X] = 255;
// unsigned char direction = 0;
// unsigned int xx = x;
// unsigned int yy = y;
// bool growEnd = false;
// do
// {
// for (unsigned int n = 0; n < 3; n++)
// {
// bool found = false;
// for (unsigned char i = 0; i < 3; i++)
// {
// int nx = xx + icvCodeDeltas[direction][i][0];
// int ny = yy + icvCodeDeltas[direction][i][1];
// //越界处理
// if (nx < 2 || ny < 2 || nx>srcPrev.cols - 2 || ny>srcPrev.rows - 2)
// continue;
//
// //考虑多加个条件限制峰值
// auto val = upSrc((nx), (ny));
// if (val >= pixval&&pLabelImg[(nx)+(ny)*X] != 255)
// {
// found = true;
// xx = nx;
// yy = ny;
// //next
// direction = icvCodeDeltas[direction][i][2];
// //标记已处理
// pLabelImg[(xx)+(yy)*X] = 255;
// break;
// }
// }
// if (!found)
// {
// direction = (direction + 1) % 4;
// }
//
// if (growEnd = (direction == 3))
// break;
// }
// } while (!growEnd);
// }
// }
// }
// }
// //合并
// lbImage += sinPartSize >= filterSize ? sinParts : mulParts;
// //粗略计数
// cv::Mat labels, stats, centroids;
// int numObj = cv::connectedComponentsWithStats(lbImage, labels, stats, centroids);
// //清空
// memset(pLabelImg, 0, X*Y * sizeof(unsigned char));
// //画图
//#define dpCent(x,y) ((double *)centroids.data)[(x)+(y)*2]
// for (int j = 1; j < numObj; j++)
// {
// cv::Point ms(cvRound(dpCent(0, j)), cvRound(dpCent(1, j)));
// pLabelImg[(ms.x) + (ms.y)*X] = 255;
// }
// //计数
// std::vector<cv::Point> vLocations;
// cv::findNonZero(lbImage, vLocations);
// for (int c = 0; c < vLocations.size(); c++)
// {
// cc.at<cv::Vec4b>(vLocations[c]) = cv::Vec4b(0, 0, 200, 255);
// cv::circle(cc, vLocations[c], 1, cv::Scalar(0, 255, 0, 255), 1);
// }
// //测试用,对已经寻找到的元件进行筛选
//
// //cv::putText(cc, std::to_string(sortedTrays[i].iDir), cv::Point(cvRound(reelCenter.x), cvRound(reelCenter.y) - 50), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
// numObj = (int)vLocations.size();
// std::string text = std::to_string(i + 1) + ": Reel Number = ";
// text += std::to_string(numObj);
// text += " ; PartSize = " + std::to_string(sinPartSize);
// cv::putText(cc, text, cv::Point(35, 35 + i * 35), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
// //
// trayNum[sortedTrays[i].iDir] = numObj;
// //释放资源
// free((void *)pLabelImg);
// }
// else
// {
// //采用追踪算法
// nccomps = cv::connectedComponentsWithStats(sinParts, m1, m2, m3);
// //连在一起
// cv::Mat srcPrevEx0;
// cv::morphologyEx(sinParts, srcPrevEx0, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(45, 45)));
// //定位料盘中心
// cv::findContours(srcPrevEx0, contoursFilter, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
// image = cv::Scalar(0);
// for (int i = 0; i < contoursFilter.size(); i++)
// {
// cv::drawContours(image, contoursFilter, i, cv::Scalar(255), -1);
// }
// image -= srcPrevEx0;
// //获取最大轮廓
// cv::findContours(image, contoursFilter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// if (contoursFilter.size() <= 0)
// continue;
// std::vector<cv::Point> contourMax = contoursFilter[0];
// for (int i = 1; i < contoursFilter.size(); i++)
// {
// if (cv::contourArea(contoursFilter[i]) > cv::contourArea(contourMax))
// {
// contourMax = contoursFilter[i];
// }
// }
// //20210927测试用
// //如果最大轮廓面积小于85000判断中间料盘影响到了定位
// if (cv::contourArea(contourMax) < 85000) {
// cv::findContours(srcPrevEx0, contoursFilter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// contourMax = contoursFilter[0];
// for (int i = 1; i < contoursFilter.size(); i++)
// {
// if (cv::contourArea(contoursFilter[i]) > cv::contourArea(contourMax))
// {
// contourMax = contoursFilter[i];
// }
// }
// }
// //计算最大外接圆半径
// float tFRadius = 0;
// cv::minEnclosingCircle(contourMax, cv::Point2f(), tFRadius);
// cv::Moments mu = cv::moments(contourMax);
// cv::Point2f reelCenter(float(mu.m10 / mu.m00), float(mu.m01 / mu.m00));
// //画中心
// reelCenter.x = reelCenter.x > 0 && reelCenter.x < X ? reelCenter.x : 0;
// reelCenter.y = reelCenter.y > 0 && reelCenter.y < Y ? reelCenter.y : 0;
// cv::drawMarker(cc, reelCenter, cv::Scalar(0, 0, 238, 255), 1, 35, 2);
// //包含未粘连器件
// image = cv::Scalar(0);
// std::vector<uchar> colors(nccomps + 1, 0);
// for (int i = 1; i < nccomps; i++) {
// colors[i] = 255;
// if ((((int *)m2.data)[(cv::CC_STAT_AREA) + (i)*m2.cols] >= 1.5*sinPartSize) || (((int *)m2.data)[(cv::CC_STAT_AREA) + (i)*m2.cols] < 0.4*sinPartSize))//经验值
// {
// colors[i] = 0;
// }
// }
// //认为是粘连
// cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range& range)->void {
// for (int y = range.start; y < range.end; y++) {
// for (int x = 0; x < X; x++) {
// int label = ((int *)m1.data)[(x)+(y)*m1.cols];
// CV_Assert(0 <= label && label <= nccomps);
// (image.data)[(x)+(y)*X] = colors[label];
// }
// }
// });
// //去掉中心1/3区域
// cv::circle(image, reelCenter, cvRound(tFRadius / 3), cv::Scalar(0), -1);
// struct TracingAnchor
// {
// float Size;
// float Length, Height;
// cv::Point2f Anchor;
// cv::RotatedRect RBox;
// TracingAnchor(cv::Point2f Anchor, float Length, float Height, float Size, cv::RotatedRect RBox) :Anchor(Anchor), Length(Length), Height(Height), Size(Size), RBox(RBox) {}
// bool operator >(const TracingAnchor &te)const
// {
// return Size > te.Size;
// }
// bool operator <(const TracingAnchor &te)const
// {
// return Size < te.Size;
// }
// };
// std::vector<std::vector<cv::Point>> contourTracing;
// cv::findContours(image, contourTracing, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
// //所有追踪锚点
// std::vector<TracingAnchor> tracingAnchors;
// for (auto&contour : contourTracing) {
// cv::RotatedRect rbox = cv::minAreaRect(contour);
// if (cv::min(rbox.size.width, rbox.size.height) > 2.0f) {
// tracingAnchors.push_back(TracingAnchor(rbox.center, cv::max(rbox.size.width, rbox.size.height), cv::min(rbox.size.width, rbox.size.height), rbox.size.area(), rbox));
// }
// }
// //不存在独立元件
// if (tracingAnchors.empty()) {
// return FUNC_CANNOT_CALC;
// }
// //尺寸只计算一次
// std::sort(tracingAnchors.begin(), tracingAnchors.end(), std::greater<TracingAnchor>());
// //
// struct Track {
// int iLimit, iPartSize;
// double dMatchDeg = 0.0;
// cv::Point2f Pos;
// std::vector<cv::Point2f> Rect;
//
// Track() {};
//
// Track(int iLimit, int iPartSize, double dMatchDeg, cv::Point2f Pos, std::vector<cv::Point2f> Rect) :iLimit(iLimit), iPartSize(iPartSize), dMatchDeg(dMatchDeg), Pos(Pos), Rect(Rect) {};
//
// bool operator >(const Track &te)const
// {
// return dMatchDeg > te.dMatchDeg;
// }
// bool operator <(const Track &te)const
// {
// return dMatchDeg < te.dMatchDeg;
// }
// };
// //缩放比例
// float coeff = 1.0f;
// //填充值
// const int fillVal = 255 - backT;
// //元件尺寸
// const double taLength = tracingAnchors[tracingAnchors.size() / 2].Length; const double taHeight = tracingAnchors[tracingAnchors.size() / 2].Height;
// //元件灰度值
// double taMaxGray = 0.0;
// //标签图
// unsigned char *ucpTrackLabel = new unsigned char[Y*X]();
// cv::Mat trackMat(Y, X, CV_8UC1, ucpTrackLabel);
// //计数图像
// cv::Mat lbMat(Y, X, CV_8UC1, cv::Scalar(0));
// //定位图像
// cv::Mat srcPrevS, tplMat;//模板文件
// srcPrevB.convertTo(srcPrevS, CV_32F);
// //随机打乱顺序(降低计算错误dChordL的可能性,也为了测试在起点信息不同时的稳定性)
// std::random_shuffle(tracingAnchors.begin(), tracingAnchors.end());
// //开始确定起点(现在是用圆轨迹来追踪,不排除用螺旋线轨迹来追踪)
// for (std::vector<TracingAnchor>::iterator itvx = tracingAnchors.begin(); itvx != tracingAnchors.end(); ++itvx) {
// //跳过执行
// if (killProcessID == 0) {
// logger.t("eyemCountObjectIrregularParts 点料阶段被跳过执行...");
// break;
// }
// //起始位置信息
// TracingAnchor ta = (*itvx);
// //起始位置坐标
// cv::Point2f startCenter(ta.Anchor.x, ta.Anchor.y);
// //最小外包矩形
// cv::Point2f _pts[4];
// ta.RBox.points(_pts);
// //已做标记(TODO:考虑增加判断哪些是起点哪些不是,20211018增加为四联通判断当前起点是否追踪过)
// if (trackMat.ptr<uint8_t>(cvRound(startCenter.y))[cvRound(startCenter.x)] == 255 || trackMat.ptr<uint8_t>(cvRound(startCenter.y))[cvRound(startCenter.x) - 1] == 255 ||
// trackMat.ptr<uint8_t>(cvRound(startCenter.y) - 1)[cvRound(startCenter.x)] == 255 || trackMat.ptr<uint8_t>(cvRound(startCenter.y))[cvRound(startCenter.x) + 1] == 255 ||
// trackMat.ptr<uint8_t>(cvRound(startCenter.y) + 1)[cvRound(startCenter.x)] == 255) {
// continue;
// }
// //获取模板图像(是否每次起点都计算模板,如果元件变形过大是否还会有用?)
// if (tplMat.empty())
// {
// float tDist = ta.Height / 2.0f;
// //理论范围扩展
// cv::Rect _rLimits = cv::Rect(cv::Point2i(cvRound((float)ta.RBox.boundingRect2f().tl().x - tDist),
// cvRound((float)ta.RBox.boundingRect2f().tl().y - tDist)), cv::Point2i(cvRound((float)ta.RBox.boundingRect2f().br().x + tDist),
// cvRound((float)ta.RBox.boundingRect2f().br().y + tDist))
// )&cv::Rect(0, 0, X, Y);
//
// //确定元件位置根据旋转后的位置确定(前提是料盘中心定位的准确)
// double t = atan2((double)startCenter.y - reelCenter.y, (double)startCenter.x - reelCenter.x) * 180.0 / PI;
// //计算旋转角度
// cv::Mat traceMat = srcPrevB(_rLimits);
// //这里计算得出的模板不是很对
// float matx[6];
// tplMat = getTrackMat(traceMat, t + 90.0, 0, matx);
// //变换后的坐标
// cv::Point2f __pts[4];
// for (int j = 0; j < 4; j++)
// {
// __pts[j].x = matx[0] * (_pts[j].x - (float)_rLimits.x) + matx[1] * (_pts[j].y - (float)_rLimits.y) + matx[2];
// __pts[j].y = matx[3] * (_pts[j].x - (float)_rLimits.x) + matx[4] * (_pts[j].y - (float)_rLimits.y) + matx[5];
// }
// cv::Point2f __ptsc((__pts[0].x + __pts[1].x + __pts[2].x + __pts[3].x) / 4.0f, (__pts[0].y + __pts[1].y + __pts[2].y + __pts[3].y) / 4.0f);
// //确定各顶点方位
// struct DIR {
// int i = -1;
// cv::Point2f pt;
// DIR() {};
//
// DIR(int i, cv::Point2f pt) :i(i), pt(pt) {};
// };
// auto _dir_l = std::vector<DIR>(); auto _dir_r = std::vector<DIR>();
// for (int j = 0; j < 4; j++)
// {
// if (__pts[j].x < __ptsc.x) {
// _dir_l.push_back(DIR(j, __pts[j]));
// }
// else {
// _dir_r.push_back(DIR(j, __pts[j]));
// }
// }
// //重新选点计算模板
// if (_dir_l.size() != _dir_r.size()) {
// continue;
// }
// //确定顶点方向
// cv::Point2f p0, p1, p2, p3;
// if (_dir_l[0].pt.y < _dir_l[1].pt.y) {
// p0 = _pts[_dir_l[0].i];
// p1 = _pts[_dir_l[1].i];
// }
// else {
// p0 = _pts[_dir_l[1].i];
// p1 = _pts[_dir_l[0].i];
// }
//
// if (_dir_r[0].pt.y > _dir_r[1].pt.y) {
// p2 = _pts[_dir_r[0].i];
// p3 = _pts[_dir_r[1].i];
// }
// else {
// p2 = _pts[_dir_r[1].i];
// p3 = _pts[_dir_r[0].i];
// }
// //计算精确角度
// cv::Point2f p01((p0.x + p1.x) / 2.0f, (p0.y + p1.y) / 2.0f), p23((p2.x + p3.x) / 2.0f, (p2.y + p3.y) / 2.0f);
//
// double realT = atan2((double)p23.y - (double)p01.y, (double)p23.x - (double)p01.x) * 180.0 / PI;
// cv::Mat realTplMat = getTrackMat(traceMat, realT, 0, matx);
//
// cv::Point2f __mpts[4];
// for (int j = 0; j < 4; j++)
// {
// __mpts[j].x = matx[0] * (_pts[j].x - (float)_rLimits.x) + matx[1] * (_pts[j].y - (float)_rLimits.y) + matx[2];
// __mpts[j].y = matx[3] * (_pts[j].x - (float)_rLimits.x) + matx[4] * (_pts[j].y - (float)_rLimits.y) + matx[5];
// }
//
// cv::Rect _rr(cvFloor(std::min(std::min(std::min(__mpts[0].x, __mpts[1].x), __mpts[2].x), __mpts[3].x)),
// cvFloor(std::min(std::min(std::min(__mpts[0].y, __mpts[1].y), __mpts[2].y), __mpts[3].y)),
// cvCeil(std::max(std::max(std::max(__mpts[0].x, __mpts[1].x), __mpts[2].x), __mpts[3].x)),
// cvCeil(std::max(std::max(std::max(__mpts[0].y, __mpts[1].y), __mpts[2].y), __mpts[3].y))); _rr.width -= _rr.x - 1; _rr.height -= _rr.y - 1;
//
// //最终模板
// tplMat = realTplMat(_rr).clone();
// //缩放比例
// if (MIN(tplMat.size().width, tplMat.size().height) < 12.0) {
// coeff = 2.0f;
// }
// //最大值
// cv::minMaxLoc(tplMat, NULL, &taMaxGray);
// }
// //标记为已追踪过
// std::vector<cv::Point> vT = { cv::Point(_pts[0]),cv::Point(_pts[1]) ,cv::Point(_pts[2]) ,cv::Point(_pts[3]) };
// cv::fillConvexPoly(trackMat, vT, cv::Scalar(255));
// //标记计数
// lbMat.ptr<uint8_t>(cvRound(startCenter.y))[cvRound(startCenter.x)] = 255;
// //标记当前位置
// cv::drawMarker(cc, cv::Point(startCenter), cv::Scalar(0, 255, 0, 255), cv::MARKER_DIAMOND, 5);
// //扫描步长
// const double dMinorStep = 0.1;
// //追踪长宽
// const double trackLength = taLength / 2.0, trackWidth = taHeight / 4.0;//是否用较小尺寸的窗口
// //起始扫描角度
// const double startAngle = atan2((double)startCenter.y - reelCenter.y, (double)startCenter.x - reelCenter.x) * 180.0 / PI;
// //起始扫描半径
// const double startRadius = cv::norm(startCenter - reelCenter);
// //偏移角度(元件尺寸)
// const double dOffset = (2.0 * asin(2.0 * trackLength / (2.0 * startRadius))) * 180.0 / PI;
// //扫描角度(默认15度范围内存在元件)
// const double dScanRange = 15.0;
// //追踪元件间距(弦长,可以尽量避免因个别器件偏离导致的追踪中断)
// double dChordL = .0;
// for (double t = startAngle + dOffset / 1.5; t < startAngle + dScanRange; t += dMinorStep)
// {
// float x = float(reelCenter.x + startRadius*cos(t*c));
// float y = float(reelCenter.y + startRadius*sin(t*c));
// //防止超出图像范围
// if (cvRound(x) < 0 || (cvRound(x) > X - 1) || cvRound(y) < 0 || (cvRound(y) > Y - 1)) {
// break;
// }
// //确定是否是下一个元件
// if (trackMat.ptr<uint8_t>(cvRound(y))[cvRound(x)] == 255) {
// continue;
// }
// //初次确定元件间距
// const double angle = atan2((double)reelCenter.y - y, (double)reelCenter.x - x);
//
// cv::Point p1 = cv::Point(cvRound(x + trackWidth * cos(angle)),
// cvRound(y + trackWidth * sin(angle)));
//
// cv::Point p2 = cv::Point(cvRound(x + trackWidth * cos(angle + CV_PI)),
// cvRound(y + trackWidth * sin(angle + CV_PI)));
//#ifdef _DEBUG
// cv::line(cc, p1, p2, cv::Scalar(0, 215, 255, 255), 1);
//#endif
// cv::LineIterator it(sinParts, p1, p2, 4);
// for (int n = 0; n < it.count; n++, ++it)
// {
// if (sinParts.ptr<uint8_t>(it.pos().y)[it.pos().x] == 255)
// {
// //计算元件间距(弦长)
// dChordL = 2.0 * startRadius*sin(((2.0 * asin((cv::norm(startCenter - cv::Point2f(x, y))) / (2.0 * startRadius))) * 180.0 / PI - dOffset / 2.0)*PI / 180.0 / 2.0);
// break;
// }
// }
// if (dChordL > 2.1)
// break;
// }
// //没确定出元件间距一般为结尾或单个元件,继续从下一个起点计算弦长并开始追踪
// if (dChordL <= 2.1) {
// continue;
// }
// //顺时针(是否并行取决于在windows下运行还是树莓派上)
// {
// //追踪中心
// cv::Point2f trackCenter = cv::Point2f(startCenter.x, startCenter.y);
// //追踪角度、半径
// double trackAngle = startAngle, trackRadius = startRadius;
// //元件本身所占角度
// double trackOffset = dOffset;
// //元件间间距
// double partDist = (2.0 * asin(dChordL / (2.0 * trackRadius))) * 180.0 / PI;
// //开始追踪
// bool trackEnd = true;
// do
// {
// bool found = true; bool trayEnd = false;
// std::vector<Track> vParts;
// for (double t = trackAngle + (trackOffset + partDist - trackOffset / 12.0); t < trackAngle + (trackOffset + partDist - trackOffset / 12.0) + trackOffset / 6.0; t += dMinorStep)
// {
// cv::Point2f predicPos;
// predicPos.x = reelCenter.x + (float)trackRadius*(float)cos((trackAngle + (trackOffset + partDist))*c);
// predicPos.y = reelCenter.y + (float)trackRadius*(float)sin((trackAngle + (trackOffset + partDist))*c);
// //如果追踪到图像外则追踪终止
// if (cvRound(predicPos.x) < 0 || (cvRound(predicPos.x) > X - 1) || cvRound(predicPos.y) < 0 || (cvRound(predicPos.y) > Y - 1)) {
// trayEnd = true;
// break;
// }
// //感兴趣区域(向外扩展了一个元件,防止中心定位出现偏差或者料盘本身变形导致的偏差)
// cv::Point2f predictBox[4];
// calcRotateRect(predicPos, (float)(trackAngle + (trackOffset + partDist)), (float)trackLength + (float)trackLength, (float)trackWidth + (float)trackWidth, predictBox);
//
// cv::RotatedRect r(predictBox[0], predictBox[1], predictBox[2]);
// cv::Rect rLimits = r.boundingRect()&cv::Rect(0, 0, X, Y);
//
// //获取感兴趣区域
// float matx[6];
// cv::Mat traceMat = getTrackMat(srcPrevS(rLimits).clone()
// , (trackAngle + (trackOffset + partDist)) + 90.0, fillVal, matx);
//
// //计算原图中的点在旋转后的位置(即在traceMat中的精确位置)
// cv::Point2f predictBoxR[4];
// for (int j = 0; j < 4; j++)
// {
// predictBoxR[j].x = matx[0] * (predictBox[j].x - (float)rLimits.x) + matx[1] * (predictBox[j].y - (float)rLimits.y) + matx[2];
// predictBoxR[j].y = matx[3] * (predictBox[j].x - (float)rLimits.x) + matx[4] * (predictBox[j].y - (float)rLimits.y) + matx[5];
// }
// //中点
// cv::Point2f predicPosR((predictBoxR[0].x + predictBoxR[1].x + predictBoxR[2].x + predictBoxR[3].x) / 4.0f,
// (predictBoxR[0].y + predictBoxR[1].y + predictBoxR[2].y + predictBoxR[3].y) / 4.0f);
//
// //理论区域
// cv::Rect tRec = cv::Rect(cv::Point(cvRound((predicPosR.x*2.0f - (float)trackLength*2.0f) / 2.0f),
// cvRound((predicPosR.y*2.0f - (float)trackWidth*4.0f) / 2.0f)),
// cv::Size(cvRound(trackLength*2.0), cvRound(trackWidth*4.0)))
// &cv::Rect(0, 0, traceMat.cols, traceMat.rows);
//
// //高精度理论区域
// cv::Rect_<float> tRecF = cv::Rect_<float>(cv::Point2f((predicPosR.x*2.0f - (float)trackLength*2.0f) / 2.0f,
// (predicPosR.y*2.0f - (float)trackWidth*4.0f) / 2.0f),
// cv::Size2f((float)trackLength*2.0f, (float)trackWidth*4.0f))
// &cv::Rect_<float>(0.0f, 0.0f, (float)traceMat.cols, (float)traceMat.rows);
//
// //理论区域向外扩展(即predictBox范围)
// cv::Rect rr = cv::Rect(cv::Point(cvRound((double)predicPosR.x - trackLength*2.0),
// cvRound((double)predicPosR.y - trackWidth*4.0)), cv::Size(cvRound(trackLength*2.0*2.0),
// cvRound(trackWidth*4.0*2.0)))&cv::Rect(0, 0, traceMat.cols, traceMat.rows);
//
// cv::Rect_<float> rrf = cv::Rect2f(cv::Point2f((predicPosR.x*2.0f - (float)trackLength*4.0f) / 2.0f,
// (predicPosR.y*2.0f - (float)trackWidth*8.0f) / 2.0f), cv::Size2f((float)trackLength*4.0f, (float)trackWidth*8.0f))
// &cv::Rect2f(0.0f, 0.0f, (float)traceMat.cols, (float)traceMat.rows);
//
// //元件尺寸太小放大N倍处理,这样坐标会精细些,考虑元件的80%尺寸作为kernel,防止元件尺寸变化太大
// cv::Mat kernel = cv::Mat::ones(cv::Size(cv::max(cvRound((float)(trackLength*2.0) * coeff),
// cvRound((float)(trackWidth*4.0) * coeff)), cv::min(cvRound((float)(trackLength*2.0) * coeff),
// cvRound((float)(trackWidth*4.0) * coeff))), CV_32FC1);
//
// cv::Mat _traceMat = traceMat.clone();
// //放大
// if (coeff > 1.0f) {
// cv::resize(_traceMat, _traceMat, cv::Size(cvRound(traceMat.size().width * coeff), cvRound(traceMat.size().height * coeff)));
// }
//
// //计算最大值(当_traceMat尺寸小于kernel会报错)
// cv::Mat dst;
// cv::filter2D(_traceMat, dst, CV_32F, kernel);
//
// //归一化
// cv::Mat mmRescaling;
// cv::normalize(dst, mmRescaling, 1.0, 0.0, cv::NORM_MINMAX);
//
// //模板匹配做辅助判断,为了尽量避免定位出错
// cv::Mat _tplMat;
// tplMat.convertTo(_tplMat, CV_32FC1);
// if (coeff > 1.0f) {
// cv::resize(_tplMat, _tplMat, cv::Size(), coeff, coeff);
// }
// //防止报错
// if (_tplMat.cols > _traceMat.cols || _tplMat.rows > _traceMat.rows) {
// return FUNC_CANNOT_CALC;
// }
// //考虑并行计算两个模板结果
// cv::Mat tplResult0;
// cv::matchTemplate(_traceMat, _tplMat, tplResult0, cv::TM_SQDIFF_NORMED);
//
// int modx = _tplMat.cols % 2, mody = _tplMat.rows % 2;
// cv::Mat tplResultMap;
// cv::copyMakeBorder(tplResult0, tplResultMap, (_tplMat.rows - mody) / 2, _traceMat.rows - tplResult0.rows - (_tplMat.rows - mody) / 2,
// (_tplMat.cols - modx) / 2, _traceMat.cols - tplResult0.cols - (_tplMat.cols - modx) / 2, cv::BORDER_REPLICATE);
//
// //减去模板匹配的结果
// mmRescaling -= tplResultMap;
// //非极大值抑制
// cv::Mat mask;
// cv::dilate(mmRescaling, mask, cv::Mat());
// cv::compare(mmRescaling, mask, mask, cv::CMP_GE);
//
// cv::Mat non_plateau_mask;
// cv::erode(mmRescaling, non_plateau_mask, cv::Mat());
// cv::compare(mmRescaling, non_plateau_mask, non_plateau_mask, cv::CMP_GT);
// cv::bitwise_and(mask, non_plateau_mask, mask);
//
// //去掉分数过低的
// mask &= cv::Mat(mmRescaling > 0.36);
// //限定区域(mmRescaling范围内)
// cv::Rect _rr = cv::Rect(cvRound(rr.x*coeff), cvRound(rr.y*coeff), cvRound(rr.width*coeff), cvRound(rr.height*coeff));
//
// //候选元件位置
// std::vector<cv::Point> candidates;
// cv::findNonZero(mask(_rr), candidates);
//
// //过滤
// std::vector<Track> _vParts;
// for (auto&candidate : candidates) {
// cv::Point pt(candidate.x + _rr.x, candidate.y + _rr.y);
// float confidence = mmRescaling.ptr<float>(pt.y)[pt.x];
// if (confidence > 0.5f) {
// _vParts.push_back(Track(0, 0, confidence, cv::Point2f((float)pt.x, (float)pt.y), std::vector<cv::Point2f>()));
// }
// }
//
// //目标元件在小图中的位置
// cv::Point2f maxLox;
// //元件位置判断
// if (_vParts.size() <= 0) {
// //大概率终止
// trayEnd = true;
// }
// else if (_vParts.size() == 1) {
// //有可能会出错
// maxLox = cv::Point2f(_vParts[0].Pos.x / coeff, _vParts[0].Pos.y / coeff);
// if (tRecF.contains(maxLox)) {
// //计算旋转前的坐标(即匹配的最终坐标)
// float realX = 0.0f, realY = 0.0f;
// realX = (float)rLimits.tl().x + ((maxLox.x - matx[2])*matx[4] - (maxLox.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
// realY = (float)rLimits.tl().y + ((maxLox.x - matx[2])*matx[3] - (maxLox.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
//
// //外包矩形顶点
// cv::Point2f pts[4];
// calcRotateRect(cv::Point2f(realX, realY), (float)(trackAngle + (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, pts);
//
// //
// std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
// vParts.push_back(Track(0, 0, 0, cv::Point2f(realX, realY), vRect));
// }
// else {
// //这里负责处理意外情况(极大可能是元件偏离过多或者料盘中心定位不准确导致的),
// //采用距离理论位置最近的点(两种方式都失效的概率比较低,如果真的失效那就听天由命吧)
// cv::Mat _mmRescaling, _tplResultMap;
// _mmRescaling = mmRescaling.clone(); _tplResultMap = tplResultMap.clone();
//
// //累加的方式
// double maxVal; cv::Point maxLoc;
// cv::minMaxLoc(_mmRescaling(_rr), NULL, &maxVal, NULL, &maxLoc);
// maxLoc += _rr.tl();
//
// //模板匹配的方式
// double minVal; cv::Point minLoc;
// cv::minMaxLoc(_tplResultMap(_rr), &minVal, NULL, &minLoc, NULL);
// minLoc += _rr.tl();
//
// std::vector<Track> __vParts;
// __vParts.push_back(Track(0, 0, cv::norm(cv::Point2f((float)maxLoc.x, (float)maxLoc.y) - cv::Point2f(floorf((float)_traceMat.cols / 2.0f), floorf((float)_traceMat.rows / 2.0f))),
// cv::Point2f((float)maxLoc.x, (float)maxLoc.y), std::vector<cv::Point2f>()));
//
// __vParts.push_back(Track(0, 0, cv::norm(cv::Point2f((float)minLoc.x, (float)minLoc.y) - cv::Point2f(floorf((float)_traceMat.cols / 2.0f), floorf((float)_traceMat.rows / 2.0f))),
// cv::Point2f((float)minLoc.x, (float)minLoc.y), std::vector<cv::Point2f>()));
//
// //排序
// std::sort(__vParts.begin(), __vParts.end(), std::less<Track>());
//
// //在小图中的位置
// maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff);
//
// //计算旋转前的坐标(即匹配的最终坐标)
// float realX = 0.0f, realY = 0.0f;
// realX = (float)rLimits.tl().x + ((maxLox.x - matx[2])*matx[4] - (maxLox.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
// realY = (float)rLimits.tl().y + ((maxLox.x - matx[2])*matx[3] - (maxLox.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
//
// //外包矩形顶点
// cv::Point2f pts[4];
// calcRotateRect(cv::Point2f(realX, realY), (float)(trackAngle + (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, pts);
//
// //
// std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
// vParts.push_back(Track(0, 0, 0, cv::Point2f(realX, realY), vRect));
//#ifdef _DEBUG
// for (int j = 0; j < 4; j++)
// {
// cv::line(cc, predictBox[j], predictBox[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
// }
//#endif
// }
// }
// else {
// //存在多个峰值,先判断分数最高是否位于理论位置
// std::sort(_vParts.begin(), _vParts.end(), std::greater<Track>());
// for (auto&_vPart : _vParts) {
// maxLox = cv::Point2f(_vPart.Pos.x / coeff, _vPart.Pos.y / coeff);
// if (tRecF.contains(maxLox)) {
// //计算旋转前的坐标(即匹配的最终坐标)
// float realX = 0.0f, realY = 0.0f;
// realX = (float)rLimits.tl().x + ((maxLox.x - matx[2])*matx[4] - (maxLox.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
// realY = (float)rLimits.tl().y + ((maxLox.x - matx[2])*matx[3] - (maxLox.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
//
// //外包矩形顶点
// cv::Point2f pts[4];
// calcRotateRect(cv::Point2f(realX, realY), (float)(trackAngle + (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, pts);
//
// //
// std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
// vParts.push_back(Track(0, 0, 0, cv::Point2f(realX, realY), vRect));
// break;
// }
// }
// //如果不在则选取距离理论位置最近的
// if (vParts.empty()) {
// //这里负责处理意外情况(极大可能是元件偏离过多或者中心定位不准确)
// //,采用距离理论位置最近的点(两种方式都失效的概率比较低)
// cv::Mat _mmRescaling, _tplResultMap;
// _mmRescaling = mmRescaling.clone(); _tplResultMap = tplResultMap.clone();
//
// //累加的方式
// double maxVal; cv::Point maxLoc;
// cv::minMaxLoc(_mmRescaling(_rr), NULL, &maxVal, NULL, &maxLoc);
// maxLoc += _rr.tl();
//
// //模板匹配的方式
// double minVal; cv::Point minLoc;
// cv::minMaxLoc(_tplResultMap(_rr), &minVal, NULL, &minLoc, NULL);
// minLoc += _rr.tl();
//
// std::vector<Track> __vParts;
// __vParts.push_back(Track(0, 0, cv::norm(cv::Point2f((float)maxLoc.x, (float)maxLoc.y) - cv::Point2f(floorf((float)_traceMat.cols / 2.0f), floorf((float)_traceMat.rows / 2.0f))),
// cv::Point2f((float)maxLoc.x, (float)maxLoc.y), std::vector<cv::Point2f>()));
//
// __vParts.push_back(Track(0, 0, cv::norm(cv::Point2f((float)minLoc.x, (float)minLoc.y) - cv::Point2f(floorf((float)_traceMat.cols / 2.0f), floorf((float)_traceMat.rows / 2.0f))),
// cv::Point2f((float)minLoc.x, (float)minLoc.y), std::vector<cv::Point2f>()));
//
// //排序
// std::sort(__vParts.begin(), __vParts.end(), std::less<Track>());
//
// //在小图中的位置
// maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff);
//
// //计算旋转前的坐标(即匹配的最终坐标)
// float realX = 0.0f, realY = 0.0f;
// realX = (float)rLimits.tl().x + ((maxLox.x - matx[2])*matx[4] - (maxLox.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
// realY = (float)rLimits.tl().y + ((maxLox.x - matx[2])*matx[3] - (maxLox.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
//
// //外包矩形顶点
// cv::Point2f pts[4];
// calcRotateRect(cv::Point2f(realX, realY), (float)(trackAngle + (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, pts);
//
// //
// std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
// vParts.push_back(Track(0, 0, 0, cv::Point2f(realX, realY), vRect));
//#ifdef _DEBUG
// for (int j = 0; j < 4; j++)
// {
// cv::line(cc, predictBox[j], predictBox[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
// }
//#endif
// }
// }
// if (!vParts.empty()) {
// cv::Rect tRec_ = cv::Rect(cv::Point(cvFloor((((float)maxLox.x)*2.0f - (float)trackLength*2.0f) / 2.0f),
// cvFloor((((float)maxLox.y)*2.0f - (float)trackWidth*4.0f) / 2.0f)),
// cv::Size(cvRound(trackLength*2.0) + 2, cvRound(trackWidth*4.0) + 2))
// &cv::Rect(0, 0, traceMat.cols, traceMat.rows);
// //当作一种辅助手段,无需设置太严格
// double dmax;
// cv::minMaxLoc(traceMat(tRec_).clone(), NULL, &dmax);
// if (dmax < 0.7*taMaxGray) {
// trayEnd = true;
// }
// }
// break;
// }
// //追踪终止,选取下一个起点
// if (trayEnd) {
// break;
// }
// //更新位置
// trackCenter = cv::Point2f(vParts[0].Pos.x, vParts[0].Pos.y);
// //更新扫描半径
// trackRadius = cv::norm(trackCenter - reelCenter);
// //更新扫描角度
// trackAngle = atan2((double)trackCenter.y - (double)reelCenter.y, (double)trackCenter.x - (double)reelCenter.x) * 180.0 / PI;
// //更新偏移量(元件角度大小)
// trackOffset = (2 * asin(2 * trackLength / (2 * trackRadius))) * 180.0 / PI;
// //更新元件间角度
// partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180.0 / PI;
// //追踪到了重复的元件
// if ((trackCenter.x<0 || trackCenter.x>X - 1 ||
// trackCenter.y<0 || trackCenter.y>Y - 1) || trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) {
// found = false;
// }
// else {
// //计算元件位置
// cv::Point2f pts[4];
// calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
// //标记计数
// lbMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] = 255;
// //标记为已追踪过
// std::vector<cv::Point> vT = { cv::Point(pts[0]),cv::Point(pts[1]) ,cv::Point(pts[2]) ,cv::Point(pts[3]) };
// cv::fillConvexPoly(trackMat, vT, cv::Scalar(255));
// //用于显示
// cv::circle(cc, trackCenter, 2, cv::Scalar(0, 255, 0, 255), 1);
//#ifdef _DEBUG
// for (int j = 0; j < 4; j++)
// {
// cv::line(cc, pts[j], pts[(j + 1) % 4], cv::Scalar(14, 173, 238, 255), 1);
// }
//#endif
// }
// //清空下一个
// vParts.resize(0);
// //跳过执行
// if (killProcessID == 0) {
// logger.t("eyemCountObjectIrregularPartsE 追踪阶段被跳过执行...");
// found = false;
// }
// trackEnd = (!found);
// } while (!trackEnd);
// }
//
// //逆时针
// {
// //追踪起点
// cv::Point2f trackCenter(startCenter.x, startCenter.y);
// //追踪角度、半径
// double trackAngle = startAngle, trackRadius = startRadius;
// //元件本身角度
// double trackOffset = dOffset;
// //元件间间距
// double partDist = (2.0 * asin(dChordL / (2.0 * trackRadius))) * 180.0 / PI;
// //开始追踪
// bool trackEnd = true;
// //
// do
// {
// bool found = true; bool trayEnd = false;
// std::vector<Track> vParts;
// for (double t = trackAngle - (trackOffset + partDist - trackOffset / 12.0); t > trackAngle - (trackOffset + partDist - trackOffset / 12.0) - trackOffset / 6.0; t -= dMinorStep)
// {
// cv::Point2f predicPos;
// predicPos.x = reelCenter.x + (float)trackRadius*(float)cos((trackAngle - (trackOffset + partDist))*c);
// predicPos.y = reelCenter.y + (float)trackRadius*(float)sin((trackAngle - (trackOffset + partDist))*c);
// //如果追踪到图像外追踪终止
// if (cvRound(predicPos.x) < 0 || (cvRound(predicPos.x) > X - 1) || cvRound(predicPos.y) < 0 || (cvRound(predicPos.y) > Y - 1)) {
// trayEnd = true;
// break;
// }
// //感兴趣区域(向外扩展了一个元件,防止中心定位出现偏差或者料盘本身变形导致的偏差)
// cv::Point2f predicBox[4];
// calcRotateRect(predicPos, (float)(trackAngle - (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, predicBox);
//
// cv::RotatedRect r(predicBox[0], predicBox[1], predicBox[2]);
// cv::Rect rLimits = r.boundingRect()&cv::Rect(0, 0, X, Y);
//
// //获取感兴趣区域
// float matx[6];
// cv::Mat traceMat = getTrackMat(srcPrevS(rLimits).clone()
// , (trackAngle - (trackOffset + partDist)) + 90.0, fillVal, matx);
//
// //计算原图中的点在旋转后的位置(即在traceMat中的精确位置)
// cv::Point2f predictBoxR[4];
// for (int j = 0; j < 4; j++)
// {
// predictBoxR[j].x = matx[0] * (predicBox[j].x - (float)rLimits.x) + matx[1] * (predicBox[j].y - (float)rLimits.y) + matx[2];
// predictBoxR[j].y = matx[3] * (predicBox[j].x - (float)rLimits.x) + matx[4] * (predicBox[j].y - (float)rLimits.y) + matx[5];
// }
// //中点
// cv::Point2f predicPosR((predictBoxR[0].x + predictBoxR[1].x + predictBoxR[2].x + predictBoxR[3].x) / 4.0f,
// (predictBoxR[0].y + predictBoxR[1].y + predictBoxR[2].y + predictBoxR[3].y) / 4.0f);
//
// //理论区域
// cv::Rect tRec = cv::Rect(cv::Point(cvRound((predicPosR.x*2.0f - (float)trackLength*2.0f) / 2.0f),
// cvRound((predicPosR.y*2.0f - (float)trackWidth*4.0f) / 2.0f)),
// cv::Size(cvRound(trackLength*2.0), cvRound(trackWidth*4.0)))
// &cv::Rect(0, 0, traceMat.cols, traceMat.rows);
//
// //高精度理论区域
// cv::Rect_<float> tRecF = cv::Rect_<float>(cv::Point2f((predicPosR.x*2.0f - (float)trackLength*2.0f) / 2.0f,
// (predicPosR.y*2.0f - (float)trackWidth*4.0f) / 2.0f),
// cv::Size2f((float)trackLength*2.0f, (float)trackWidth*4.0f))
// &cv::Rect_<float>(0.0f, 0.0f, (float)traceMat.cols, (float)traceMat.rows);
//
// //理论区域向外扩展(即predictBox范围)
// cv::Rect rr = cv::Rect(cv::Point(cvRound((double)predicPosR.x - trackLength*2.0),
// cvRound((double)predicPosR.y - trackWidth*4.0)), cv::Size(cvRound(trackLength*2.0*2.0),
// cvRound(trackWidth*4.0*2.0)))&cv::Rect(0, 0, traceMat.cols, traceMat.rows);
//
// cv::Rect_<float> rrf = cv::Rect2f(cv::Point2f((predicPosR.x*2.0f - (float)trackLength*4.0f) / 2.0f,
// (predicPosR.y*2.0f - (float)trackWidth*8.0f) / 2.0f), cv::Size2f((float)trackLength*4.0f, (float)trackWidth*8.0f))
// &cv::Rect2f(0.0f, 0.0f, (float)traceMat.cols, (float)traceMat.rows);
//
// //元件尺寸太小放大N倍处理,这样坐标会精细些,元件的80%尺寸作为kernel,防止元件尺寸变化太大
// cv::Mat kernel = cv::Mat::ones(cv::Size(cv::max(cvRound((float)(trackLength*2.0) * coeff),
// cvRound((float)(trackWidth*4.0) * coeff)), cv::min(cvRound((float)(trackLength*2.0) * coeff),
// cvRound((float)(trackWidth*4.0) * coeff))), CV_32FC1);
// cv::Mat _traceMat = traceMat.clone();
// //放大
// if (coeff > 1.0f) {
// cv::resize(_traceMat, _traceMat, cv::Size(cvRound(traceMat.size().width * coeff), cvRound(traceMat.size().height * coeff)));
// }
// //计算最大值(当_traceMat尺寸小于kernel会报错)
// cv::Mat dst;
// cv::filter2D(_traceMat, dst, CV_32F, kernel);
// //归一化
// cv::Mat mmRescaling;
// cv::normalize(dst, mmRescaling, 1.0, 0.0, cv::NORM_MINMAX);
//
// //模板匹配,为了尽量避免定位出错
// cv::Mat _tplMat;
// tplMat.convertTo(_tplMat, CV_32FC1);
// if (coeff > 1.0f) {
// cv::resize(_tplMat, _tplMat, cv::Size(), coeff, coeff);
// }
// //防止报错
// if (_tplMat.cols > _traceMat.cols || _tplMat.rows > _traceMat.rows) {
// return FUNC_CANNOT_CALC;
// }
// //考虑并行计算两个模板结果
// cv::Mat tplResult0;
// cv::matchTemplate(_traceMat, _tplMat, tplResult0, cv::TM_SQDIFF_NORMED);
//
// int modx = _tplMat.cols % 2, mody = _tplMat.rows % 2;
// cv::Mat tplResultMap;
// cv::copyMakeBorder(tplResult0, tplResultMap, (_tplMat.rows - mody) / 2, _traceMat.rows - tplResult0.rows - (_tplMat.rows - mody) / 2,
// (_tplMat.cols - modx) / 2, _traceMat.cols - tplResult0.cols - (_tplMat.cols - modx) / 2, cv::BORDER_REPLICATE);
//
// //减去模板匹配的结果
// mmRescaling -= tplResultMap;
// //非极大值抑制
// cv::Mat mask;
// cv::dilate(mmRescaling, mask, cv::Mat());
// cv::compare(mmRescaling, mask, mask, cv::CMP_GE);
//
// cv::Mat non_plateau_mask;
// cv::erode(mmRescaling, non_plateau_mask, cv::Mat());
// cv::compare(mmRescaling, non_plateau_mask, non_plateau_mask, cv::CMP_GT);
// cv::bitwise_and(mask, non_plateau_mask, mask);
//
// //去掉分数过低的
// mask &= cv::Mat(mmRescaling > 0.36);
// //限定区域(mmRescaling范围内)
// cv::Rect _rr = cv::Rect(cvRound(rr.x*coeff), cvRound(rr.y*coeff), cvRound(rr.width*coeff), cvRound(rr.height*coeff));
// //候选元件位置
// std::vector<cv::Point> candidates;
// cv::findNonZero(mask(_rr), candidates);
//
// //过滤
// std::vector<Track> _vParts;
// for (auto&candidate : candidates) {
// cv::Point pt(candidate.x + _rr.x, candidate.y + _rr.y);
// float confidence = mmRescaling.ptr<float>(pt.y)[pt.x];
// if (confidence > 0.5f) {
// _vParts.push_back(Track(0, 0, confidence, cv::Point2f((float)pt.x, (float)pt.y), std::vector<cv::Point2f>()));
// }
// }
// //目标元件在小图中的位置
// cv::Point2f maxLox;
// //元件位置判断
// if (_vParts.size() <= 0) {
// //大概率终止
// trayEnd = true;
// }
// else if (_vParts.size() == 1) {
// maxLox = cv::Point2f(_vParts[0].Pos.x / coeff, _vParts[0].Pos.y / coeff);
// //有可能会出错,当靠的太近可能只存在一个峰值
// if (tRecF.contains(maxLox)) {
// //计算旋转前的坐标(即匹配的最终坐标)
// float realX = 0.0f, realY = 0.0f;
// realX = (float)rLimits.tl().x + ((maxLox.x - matx[2])*matx[4] - (maxLox.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
// realY = (float)rLimits.tl().y + ((maxLox.x - matx[2])*matx[3] - (maxLox.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
//
// //外包矩形顶点
// cv::Point2f pts[4];
// calcRotateRect(cv::Point2f(realX, realY), (float)(trackAngle + (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, pts);
//
// //
// std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
// vParts.push_back(Track(0, 0, 0, cv::Point2f(realX, realY), vRect));
// }
// else {
// //这里负责处理意外情况(极大可能是元件偏离过多或者中心定位不准确),采用距离理论位置最近的点(两种方式都失效的概率比较低)
// cv::Mat _mmRescaling, _tplResultMap;
// _mmRescaling = mmRescaling.clone(); _tplResultMap = tplResultMap.clone();
//
// //累加的方式
// double maxVal; cv::Point maxLoc;
// cv::minMaxLoc(_mmRescaling(_rr), NULL, &maxVal, NULL, &maxLoc);
// maxLoc += _rr.tl();
//
// //模板匹配的方式
// double minVal; cv::Point minLoc;
// cv::minMaxLoc(_tplResultMap(_rr), &minVal, NULL, &minLoc, NULL);
// minLoc += _rr.tl();
//
// std::vector<Track> __vParts;
// __vParts.push_back(Track(0, 0, cv::norm(cv::Point2f((float)maxLoc.x, (float)maxLoc.y) - cv::Point2f(floorf((float)_traceMat.cols / 2.0f), floorf((float)_traceMat.rows / 2.0f))),
// cv::Point2f((float)maxLoc.x, (float)maxLoc.y), std::vector<cv::Point2f>()));
//
// __vParts.push_back(Track(0, 0, cv::norm(cv::Point2f((float)minLoc.x, (float)minLoc.y) - cv::Point2f(floorf((float)_traceMat.cols / 2.0f), floorf((float)_traceMat.rows / 2.0f))),
// cv::Point2f((float)minLoc.x, (float)minLoc.y), std::vector<cv::Point2f>()));
//
// //排序
// std::sort(__vParts.begin(), __vParts.end(), std::less<Track>());
//
// //小图中的定位坐标
// maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff);
// //计算旋转前的坐标(即匹配的最终坐标)
// float realX = 0.0f, realY = 0.0f;
// realX = (float)rLimits.tl().x + ((maxLox.x - matx[2])*matx[4] - (maxLox.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
// realY = (float)rLimits.tl().y + ((maxLox.x - matx[2])*matx[3] - (maxLox.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
//
// //外包矩形顶点
// cv::Point2f pts[4];
// calcRotateRect(cv::Point2f(realX, realY), (float)(trackAngle - (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, pts);
//
// //
// std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
// vParts.push_back(Track(0, 0, 0, cv::Point2f(realX, realY), vRect));
//#ifdef _DEBUG
// for (int j = 0; j < 4; j++)
// {
// cv::line(cc, predicBox[j], predicBox[(j + 1) % 4], cv::Scalar(0, 0, 238, 255), 1);
// }
//#endif
// }
// }
// else {
// //存在定位出错的可能性,先判断分数最高是否位于理论位置
// std::sort(_vParts.begin(), _vParts.end(), std::greater<Track>());
// for (auto&_vPart : _vParts) {
// maxLox = cv::Point2f(_vPart.Pos.x / coeff, _vPart.Pos.y / coeff);
// if (tRecF.contains(maxLox)) {
// //计算旋转前的坐标(即匹配的最终坐标)
// float realX = 0.0f, realY = 0.0f;
// realX = (float)rLimits.tl().x + ((maxLox.x - matx[2])*matx[4] - (maxLox.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
// realY = (float)rLimits.tl().y + ((maxLox.x - matx[2])*matx[3] - (maxLox.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
//
// //外包矩形顶点
// cv::Point2f pts[4];
// calcRotateRect(cv::Point2f(realX, realY), (float)(trackAngle - (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, pts);
//
// //
// std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
// vParts.push_back(Track(0, 0, 0, cv::Point2f(realX, realY), vRect));
// break;
// }
// }
// //如果不在则选取距离理论位置最近的
// if (vParts.empty()) {
// //这里负责处理意外情况(极大可能是元件偏离过多或者中心定位不准确),采用距离理论位置最近的点(两种方式都失效的概率比较低)
// cv::Mat _mmRescaling, _tplResultMap;
// _mmRescaling = mmRescaling.clone(); _tplResultMap = tplResultMap.clone();
//
// //累加的方式
// double maxVal; cv::Point maxLoc;
// cv::minMaxLoc(_mmRescaling(_rr), NULL, &maxVal, NULL, &maxLoc);
// maxLoc += _rr.tl();
//
// //模板匹配的方式
// double minVal; cv::Point minLoc;
// cv::minMaxLoc(_tplResultMap(_rr), &minVal, NULL, &minLoc, NULL);
// minLoc += _rr.tl();
//
// std::vector<Track> __vParts;
// __vParts.push_back(Track(0, 0, cv::norm(cv::Point2f((float)maxLoc.x, (float)maxLoc.y) - cv::Point2f(floorf((float)_traceMat.cols / 2.0f), floorf((float)_traceMat.rows / 2.0f))),
// cv::Point2f((float)maxLoc.x, (float)maxLoc.y), std::vector<cv::Point2f>()));
//
// __vParts.push_back(Track(0, 0, cv::norm(cv::Point2f((float)minLoc.x, (float)minLoc.y) - cv::Point2f(floorf((float)_traceMat.cols / 2.0f), floorf((float)_traceMat.rows / 2.0f))),
// cv::Point2f((float)minLoc.x, (float)minLoc.y), std::vector<cv::Point2f>()));
//
// //排序
// std::sort(__vParts.begin(), __vParts.end(), std::less<Track>());
//
// //小图中的位置
// maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff);
// //计算旋转前的坐标(即匹配的最终坐标)
// float realX = 0.0f, realY = 0.0f;
// realX = (float)rLimits.tl().x + ((maxLox.x - matx[2])*matx[4] - (maxLox.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
// realY = (float)rLimits.tl().y + ((maxLox.x - matx[2])*matx[3] - (maxLox.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
//
// //外包矩形顶点
// cv::Point2f pts[4];
// calcRotateRect(cv::Point2f(realX, realY), (float)(trackAngle - (trackOffset + partDist)), (float)trackLength*2.0f, (float)trackWidth*2.0f, pts);
//
// //
// std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
// vParts.push_back(Track(0, 0, 0, cv::Point2f(realX, realY), vRect));
//#ifdef _DEBUG
// for (int j = 0; j < 4; j++)
// {
// cv::line(cc, predicBox[j], predicBox[(j + 1) % 4], cv::Scalar(0, 0, 238, 255), 1);
// }
//#endif
// }
// }
//
// if (!vParts.empty()) {
// cv::Rect tRec_ = cv::Rect(cv::Point(cvFloor((((float)maxLox.x)*2.0f - (float)trackLength*2.0f) / 2.0f),
// cvFloor((((float)maxLox.y)*2.0f - (float)trackWidth*4.0f) / 2.0f)),
// cv::Size(cvRound(trackLength*2.0) + 2, cvRound(trackWidth*4.0) + 2))
// &cv::Rect(0, 0, traceMat.cols, traceMat.rows);
// //当作一种辅助手段,无需设置太严格
// double dmax;
// cv::minMaxLoc(traceMat(tRec_).clone(), NULL, &dmax);
// if (dmax < 0.7*taMaxGray) {
// trayEnd = true;
// }
// }
// break;
// }
// //接着下一个起点
// if (trayEnd) {
// break;
// }
// //更新位置
// trackCenter = cv::Point2f(vParts[0].Pos.x, vParts[0].Pos.y);
// //更新扫描半径
// trackRadius = cv::norm(trackCenter - reelCenter);
// //更新扫描角度
// trackAngle = atan2((double)trackCenter.y - (double)reelCenter.y, (double)trackCenter.x - (double)reelCenter.x) * 180.0 / PI;
// //更新偏移量(元件角度大小)
// trackOffset = (2.0 * asin(2.0 * trackLength / (2.0 * trackRadius))) * 180.0 / PI;
// //更新元件间角度
// partDist = (2.0 * asin(dChordL / (2.0 * trackRadius))) * 180.0 / PI;
// //追踪到了重复的元件
// if ((trackCenter.x<0 || trackCenter.x>X - 1 ||
// trackCenter.y<0 || trackCenter.y>Y - 1) || trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) {
// found = false;
// }
// else {
// //计算元件位置
// cv::Point2f pts[4];
// calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
// //标记计数
// lbMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] = 255;
// //标记为已追踪过
// std::vector<cv::Point> vT = { cv::Point(pts[0]),cv::Point(pts[1]) ,cv::Point(pts[2]) ,cv::Point(pts[3]) };
// cv::fillConvexPoly(trackMat, vT, cv::Scalar(255));
// //用于显示
// cv::circle(cc, trackCenter, 2, cv::Scalar(0, 255, 0, 255), 1);
//#ifdef _DEBUG
// for (int j = 0; j < 4; j++)
// {
// cv::line(cc, pts[j], pts[(j + 1) % 4], cv::Scalar(102, 205, 0, 255), 1);
// }
//#endif
//}
// //继续下一个起点
// vParts.resize(0);
// //跳过执行
// if (killProcessID == 0) {
// logger.t("eyemCountObjectIrregularParts 追踪阶段被跳过执行...");
// found = false;
// }
// trackEnd = (!found);
// } while (!trackEnd);
// }
// }
// //标记料盘编号
// //cv::putText(cc, std::to_string(sortedTrays[i].iDir), cv::Point(cvRound(reelCenter.x), cvRound(reelCenter.y) - 50), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
// //计数
// int reelNum = cv::countNonZero(lbMat);
// std::string text = std::to_string(i + 1) + ": Reel Number = ";
// text += std::to_string(reelNum);
// text += " ; PartSize = " + std::to_string(sinPartSize);
// cv::putText(cc, text, cv::Point(35, 35 + i * 35), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
// //输出
// trayNum[sortedTrays[i].iDir] = reelNum;
// //释放资源
// delete[] ucpTrackLabel;
// ucpTrackLabel = NULL;
// }
// ////标记
// //std::string text = "PartSize:";
// //text += std::to_string(sinPartsArea);
// //cv::putText(cc, text, cv::Point(35, 35), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
// //std::string text2 = "PartGray:";
// //text2 += std::to_string(sinPartsMean);
// //cv::putText(cc, text2, cv::Point(35, 95), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
// }
#pragma region #pragma region
//AZONNXWrapper net; //AZONNXWrapper net;
...@@ -8533,20 +10143,16 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg) ...@@ -8533,20 +10143,16 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
#pragma endregion #pragma endregion
//if (!output.empty()) { ////<输出结果图像
// //<输出结果图像 //tpDstImg->iWidth = cc.cols; tpDstImg->iHeight = cc.rows; tpDstImg->iDepth = cc.depth(); tpDstImg->iChannels = cc.channels();
// tpDstImg->iWidth = output.cols; tpDstImg->iHeight = output.rows; tpDstImg->iDepth = output.depth(); tpDstImg->iChannels = output.channels(); ////内存尺寸
// //内存尺寸 //int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t);
// int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t); ////分配初始化内存
// //分配初始化内存 //tpDstImg->vpImage = (uint8_t *)malloc(_Size);
// tpDstImg->vpImage = (uint8_t *)malloc(_Size); //if (NULL == tpDstImg->vpImage)
// if (NULL == tpDstImg->vpImage)
// return FUNC_NOT_ENOUGH_MEM; // return FUNC_NOT_ENOUGH_MEM;
// memset(tpDstImg->vpImage, 0, _Size); //memset(tpDstImg->vpImage, 0, _Size);
// //拷贝数据 ////拷贝数据
// memcpy(tpDstImg->vpImage, output.data, _Size); //memcpy(tpDstImg->vpImage, cc.data, _Size);
//}
return FUNC_OK; return FUNC_OK;
} }
...@@ -122,40 +122,40 @@ int eyemNNDetector(EyemImage tpImage, int *ipNum, BboxContainer &container, Eyem ...@@ -122,40 +122,40 @@ int eyemNNDetector(EyemImage tpImage, int *ipNum, BboxContainer &container, Eyem
} }
#ifdef _DEBUG #ifdef _DEBUG
int eyemInitClassifier(const char *classifierConfigPath, const char *classifierModelPath, int ntype) //int eyemInitClassifier(const char *classifierConfigPath, const char *classifierModelPath, int ntype)
{ //{
try { // try {
pClassifier = cv::makePtr<YoloDarknet>(classifierConfigPath, classifierModelPath, ntype); // pClassifier = cv::makePtr<YoloDarknet>(classifierConfigPath, classifierModelPath, ntype);
} // }
catch (const std::exception& e) { // catch (const std::exception& e) {
std::cout << e.what() << std::endl; // std::cout << e.what() << std::endl;
return FUNC_CANNOT_CALC; // return FUNC_CANNOT_CALC;
} // }
return FUNC_OK; // return FUNC_OK;
} //}
//
int eyemClassifier(EyemImage tpImage) //int eyemClassifier(EyemImage tpImage)
{ //{
cv::Mat src = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone(); // cv::Mat src = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
if (src.empty()) { // if (src.empty()) {
return FUNC_IMAGE_NOT_EXIST; // return FUNC_IMAGE_NOT_EXIST;
} // }
cv::Mat input; // cv::Mat input;
int incn = src.channels(); // int incn = src.channels();
if (incn == 4) { // if (incn == 4) {
cv::cvtColor(src, input, cv::COLOR_BGRA2BGR); // cv::cvtColor(src, input, cv::COLOR_BGRA2BGR);
} // }
else if (incn == 1) { // else if (incn == 1) {
cv::cvtColor(src, input, cv::COLOR_GRAY2BGR);//根据配置支持三通道图像 // cv::cvtColor(src, input, cv::COLOR_GRAY2BGR);//根据配置支持三通道图像
} // }
else { // else {
input = src; // input = src;
} // }
pClassifier->setInput(input, 0.4, 5); // pClassifier->setInput(input, 0.4, 5);
auto predict = std::vector<int>(); auto confidence = std::vector<float>(); auto bbox = std::vector<cv::Rect>(); // auto predict = std::vector<int>(); auto confidence = std::vector<float>(); auto bbox = std::vector<cv::Rect>();
pClassifier->forward(predict, confidence, bbox); // pClassifier->forward(predict, confidence, bbox);
std::cout << "run_end!" << std::endl; // std::cout << "run_end!" << std::endl;
return FUNC_OK; // return FUNC_OK;
} //}
#endif #endif
\ No newline at end of file \ No newline at end of file
...@@ -25,7 +25,7 @@ protected: ...@@ -25,7 +25,7 @@ protected:
cv::Ptr<NNDetector> pNNDetector; cv::Ptr<NNDetector> pNNDetector;
#ifdef _DEBUG #ifdef _DEBUG
cv::Ptr<YoloDarknet> pClassifier; //cv::Ptr<YoloDarknet> pClassifier;
#endif #endif
#endif/* __EYEMNNDETECTOR_H */ #endif/* __EYEMNNDETECTOR_H */
\ No newline at end of file \ No newline at end of file
...@@ -200,8 +200,8 @@ public: ...@@ -200,8 +200,8 @@ public:
const __m128i mask2 = _mm_setr_epi8(5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10); const __m128i mask2 = _mm_setr_epi8(5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10);
const __m128i mask3 = _mm_setr_epi8(10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15); const __m128i mask3 = _mm_setr_epi8(10, 5, 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15);
const __m128i bmask1 = _mm_setr_epi8(0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0); const __m128i bmask1 = _mm_setr_epi8(0, -1, -1, 0, -1, -1, 0, -1, -1, 0, -1, -1, 0, -1, -1, 0);//原255
const __m128i bmask2 = _mm_setr_epi8(255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255); const __m128i bmask2 = _mm_setr_epi8(-1, -1, 0, -1, -1, 0, -1, -1, 0, -1, -1, 0, -1, -1, 0, -1);
a = _mm_shuffle_epi8(a, mask1); a = _mm_shuffle_epi8(a, mask1);
b = _mm_shuffle_epi8(b, mask2); b = _mm_shuffle_epi8(b, mask2);
...@@ -379,27 +379,8 @@ int eyemNonLocalMeansFilter(EyemImage tpImage, int iCMPSize, int iSearchSize, do ...@@ -379,27 +379,8 @@ int eyemNonLocalMeansFilter(EyemImage tpImage, int iCMPSize, int iSearchSize, do
if (image.empty()) { if (image.empty()) {
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
} }
//std::vector<cv::Mat> mvs(3);
//cv::split(image, mvs);
//mvs[0] = cv::imread("C:\\Users\\nzslw\\OneDrive\\程序\\VSProject\\eyemLib\\x64\\Debug\\Portada_paper_b.png", cv::IMREAD_GRAYSCALE);
//mvs[1] = cv::imread("C:\\Users\\nzslw\\OneDrive\\程序\\VSProject\\eyemLib\\x64\\Debug\\Portada_paper_g.png", 0);
//mvs[2] = cv::imread("C:\\Users\\nzslw\\OneDrive\\程序\\VSProject\\eyemLib\\x64\\Debug\\Portada_paper_r.png", 0);
cv::Mat dest; cv::Mat dest;
//cv::blur(image, dest, cv::Size(3, 3)); nonLocalMeansFilter_SSE(image, dest, cv::Size(3, 3), cv::Size(5, 5), 10.0, -1, 0);
//cv::merge(mvs, dest);
//for (int i = 0; i < 10; i++)
//{
//nonLocalMeansFilter_SSE(image, dest, cv::Size(3, 3), cv::Size(5, 5), 10.0, -1, 0);
//image = dest;
//}
dest = image < 220;
cv::imwrite("Portada_paper5.png", dest);
return FUNC_OK; return FUNC_OK;
} }
......
...@@ -83,41 +83,41 @@ std::vector<cv::Rect> YoloWrapper::forward(cv::Mat img) { ...@@ -83,41 +83,41 @@ std::vector<cv::Rect> YoloWrapper::forward(cv::Mat img) {
#ifdef _DEBUG #ifdef _DEBUG
class YoloDarknet::Impl { //class YoloDarknet::Impl {
public: //public:
Impl() {} // Impl() {}
~Impl() {} // ~Impl() {}
//
std::shared_ptr<DarkNet> net_; // std::shared_ptr<DarkNet> net_;
}; //};
//
YoloDarknet::YoloDarknet(const std::string& config_path, const std::string& model_path, const int ntype) //YoloDarknet::YoloDarknet(const std::string& config_path, const std::string& model_path, const int ntype)
{ //{
p = cv::makePtr<YoloDarknet::Impl>(); // p = cv::makePtr<YoloDarknet::Impl>();
if (!config_path.empty() && !model_path.empty()) { // if (!config_path.empty() && !model_path.empty()) {
p->net_ = std::make_shared<DarkNet>(); // p->net_ = std::make_shared<DarkNet>();
p->net_->init(config_path, model_path, ntype); // p->net_->init(config_path, model_path, ntype);
} // }
else { // else {
p->net_ = NULL; // p->net_ = NULL;
} // }
} //}
//
void YoloDarknet::setInput(cv::Mat& img, float threshold, int topk) { //void YoloDarknet::setInput(cv::Mat& img, float threshold, int topk) {
topk_ = topk; // topk_ = topk;
p->net_->setPreferableParams(threshold, topk); // p->net_->setPreferableParams(threshold, topk);
p->net_->forward(img); // p->net_->forward(img);
} //}
//
void YoloDarknet::forward(std::vector<int> &outputPredict, std::vector<float> &outputConfidence, std::vector<cv::Rect> &outputBoxes) //void YoloDarknet::forward(std::vector<int> &outputPredict, std::vector<float> &outputConfidence, std::vector<cv::Rect> &outputBoxes)
{ //{
auto bbox = std::vector<cv::Rect>(); // auto bbox = std::vector<cv::Rect>();
int *predicts = new int[topk_]; float *confidence = new float[topk_]; // int *predicts = new int[topk_]; float *confidence = new float[topk_];
p->net_->getResult(predicts, confidence, &bbox); // p->net_->getResult(predicts, confidence, &bbox);
for (int top = 0; top < topk_; top++) outputPredict.push_back(predicts[top]), outputConfidence.push_back(confidence[top]); // for (int top = 0; top < topk_; top++) outputPredict.push_back(predicts[top]), outputConfidence.push_back(confidence[top]);
for (auto&box : bbox) { // for (auto&box : bbox) {
outputBoxes.push_back(box); // outputBoxes.push_back(box);
} // }
delete[] predicts; predicts = NULL; delete[] confidence; confidence = NULL; // delete[] predicts; predicts = NULL; delete[] confidence; confidence = NULL;
} //}
#endif #endif
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#ifdef _DEBUG #ifdef _DEBUG
#include <darknet.h> //#include <darknet.h>
#include <yolo_class.h> //#include <yolo_class.h>
#endif #endif
class YoloWrapper class YoloWrapper
...@@ -27,20 +27,20 @@ private: ...@@ -27,20 +27,20 @@ private:
}; };
#ifdef _DEBUG #ifdef _DEBUG
class YoloDarknet //class YoloDarknet
{ //{
public: //public:
YoloDarknet(const std::string& config_path = "", const std::string& model_path = "", const int ntype = 0); // YoloDarknet(const std::string& config_path = "", const std::string& model_path = "", const int ntype = 0);
YoloDarknet() {}; // YoloDarknet() {};
//
void setInput(cv::Mat& img, float threshold, int topk = 2); // void setInput(cv::Mat& img, float threshold, int topk = 2);
void forward(std::vector<int> &outputPredict, std::vector<float> &outputConfidence, std::vector<cv::Rect> &outputBoxes); // void forward(std::vector<int> &outputPredict, std::vector<float> &outputConfidence, std::vector<cv::Rect> &outputBoxes);
private: //private:
int topk_ = 0; // int topk_ = 0;
protected: //protected:
class Impl; // class Impl;
cv::Ptr<Impl> p; // cv::Ptr<Impl> p;
}; //};
#endif #endif
#endif/* __YOLOWRAPPER_H */ #endif/* __YOLOWRAPPER_H */
\ No newline at end of file \ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!