Commit 0871eb39 张士柳

1 个父辈 da2526be
......@@ -995,12 +995,28 @@ namespace eyemLib_Sharp
private static extern int eyemInitNNDetector(string detectorConfigPath, string detectorModelPath, int iNetSizew, int iNetSizeh);
/// <summary>
/// 设置检测参数
/// </summary>
/// <param name="fConfidence">置信度</param>
/// <param name="fNMSThreshold">非极大值抑制阈值</param>
/// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemNNDetectorParams(float fConfidence, float fNMSThreshold);
/// <summary>
/// 目标检测器
/// </summary>
/// <param name="tpImage">输入图像</param>
/// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemNNDetector(EyemImage tpImage, out int ipNum, ref BboxContainer container, out EyemImage tpDstImg);
/// <summary>
/// 初始化darknet分类器
/// </summary>
/// <param name="classifierConfigPath">配置地址</param>
/// <param name="classifierModelPath">模型地址</param>
/// <param name="ntype">0 检测网络,1 分类网络</param>
/// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemInitClassifier(string classifierConfigPath, string classifierModelPath, int ntype);
......@@ -1085,6 +1101,14 @@ namespace eyemLib_Sharp
//多功能工具
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemMulFuncTool(EyemImage tpImage, EyemRect tpRoi, string funcName, double dThreshold, int iNumToIgnore, ref EyemOcsFXYR tpCircle, out EyemImage tpDstImg);
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemDetectCircleUseHough(EyemImage tpImage, EyemRect tpRoi, EyemRect limRoi, out EyemOcsDXYR tpCircle, out EyemImage tpDstImg, double dp, double dMinDist, double dParam1, double dParam2, double dMinRadius, double dMaxRadius, int iMethod = 3, bool useValLimit = false);
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern void loadImage2Mem(string key, EyemImage tpImage);
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int setProcessLevel(double pl);
#endregion
#region 测试专用接口
......@@ -1094,6 +1118,8 @@ namespace eyemLib_Sharp
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemEdge1dRidgeDetection(EyemImage tpImage);
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemBuildTrainFile(string filePath, string fileName);
#endregion
......@@ -1119,9 +1145,15 @@ namespace eyemLib_Sharp
OnNewLogCallback += new TCallBack(EyemLib_OnNewLogCallback);
eyemInitNNDataCodeModel(".\\darknet\\detect-tiny.cfg", ".\\darknet\\detect-tiny.weights", ".\\darknet\\sr.prototxt", ".\\darknet\\sr.caffemodel");
//setProcessLevel(2.0);
//EyemImage image_back = new EyemImage();
//eyemImageRead("D:\\Img20211028142015.png", -1, out image_back);
//loadImage2Mem("back", image_back);
eyemInitClassifier("D:\\detect-tiny-tray.cfg", "D:\\detect-tiny-tray.weights", 0);
//eyemInitNNDataCodeModel(".\\darknet\\detect-tiny.cfg", ".\\darknet\\detect-tiny.weights", ".\\darknet\\sr.prototxt", ".\\darknet\\sr.caffemodel");
//eyemInitClassifier("D:\\detect-tiny-tray.cfg", "D:\\detect-tiny-tray.weights", 0);
}
public static void Free()
......@@ -1177,13 +1209,29 @@ namespace eyemLib_Sharp
sw.Restart();
string file = fileName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries)[2];
//string[] fileNames = Directory.GetFiles(@"D:\训练数据集\点料机料盘识别\val_images", "*.png", 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;
//foreach (var item in fileNames)
//{
// eyemBuildTrainFile(item, "D:\\标签识别\\" + item.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries)[4]);
//}
//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++)
//{
// string item = fileNames[i];
// string[] items = item.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
// FileInfo fi = new FileInfo(item);
// fi.MoveTo(@"D:\日志\" + (i+83).ToString() + ".png");
//}
//return;
//StreamWriter swr = new StreamWriter("D:\\val.txt", true);
//foreach (var item in random_shuffle)
//{
......@@ -1226,7 +1274,7 @@ namespace eyemLib_Sharp
//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 };
//eyemClassifier(image);
//flag = eyemLibImpl(image, out tpDstImg);
flag = eyemLibImpl(image, out tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//{
......@@ -1234,7 +1282,7 @@ namespace eyemLib_Sharp
//}
//eyemImageFree(ref tpDstImg);
//eyemImageFree(ref image);
//return;
return;
//EyemImage templ, search;
//flag = eyemImageRead("D://批量测试图像//template.png", -1, out templ);
......@@ -1454,9 +1502,14 @@ namespace eyemLib_Sharp
tpRoi.iWidth = image.iWidth - 100;
tpRoi.iHeight = image.iHeight - 100;
//flag = eyemMulFuncTool(image, tpRoi, "__func1", 65, 75, ref tpCircle, out tpDstImg);
int[] ipReelNum = new int[4];
//flag = eyemAchvMatchMat(image, tpRoi, out tpDstImg);
//EyemOcsDXYR tpCircle = new EyemOcsDXYR();
//EyemRect limRoi = new EyemRect();
//limRoi.iXs = 222; limRoi.iYs = 222;
//limRoi.iWidth = 214;
//limRoi.iHeight = 214;
//flag = eyemDetectCircleUseHough(image, tpRoi, limRoi, out tpCircle, out tpDstImg, 1.0, 80, 100, 50, 28, 43, 3, true);
//////flag = eyemMulFuncTool(image, tpRoi, "__func1__", 65, 75, ref tpCircle, out tpDstImg);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//{
......@@ -1521,20 +1574,21 @@ namespace eyemLib_Sharp
//如果对象供其他接口使用要先释放
//eyemImageFree(ref tpDstImg);
int[] ipReelNum = new int[4];
//"IP_SMALL_PARTS","IP_LARGE_PARTS","IP_LONG_PARTS",,IP_SQUARE_PARTS
//eyemCountObject(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
//eyemCountObjectIrregularParts(image, tpRoi, file.Replace(".png", ""), "IP_LARGE_PARTS", ipReelNum, out tpDstImg);
//eyemCountObjectE(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
eyemCountObjectE(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), "D:\\模板文件\\" + "20210825095751-1.tpl", hModelID, ipReelNum, out tpDstImg);
//移除模板
//flag = eyemRemoveModelByName(hModelID, "D:\\模板文件及图像\\df871193-6632-48f9-abfe-540c3fc49c3f.tpl");
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//{
// bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
//}
Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
if (bitmap != null)
{
bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
}
//< 解码测试
//int ipNum; EyemBarCode* tpResults;
......

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eyemLib", "eyemLib\eyemLib.vcxproj", "{33D5F550-C799-4B05-8E14-ACA390DF5442}"
EndProject
......
......@@ -20,12 +20,23 @@ void setLogCallback(TCallback cb)
}
int killProcessID = -1;
void setSkipProcessID(int pid)
{
killProcessID = pid;
}
double processLevel = 2.0;
void setProcessLevel(double processLevel_)
{
processLevel = processLevel_;
}
std::map<std::string, EyemImage> imageMap;
void loadImage2Mem(const char *key, EyemImage tpImage)
{
imageMap.insert(std::pair<std::string, EyemImage>(std::string(key), tpImage));
}
Logger logger;
int main(int argc, char **argv)
{
......
......@@ -868,6 +868,7 @@ extern "C" {
// 函数接口
EXPORTS int eyemInitNNDetector(const char *detectorConfigPath, const char *detectorModelPath, int iNetSizew, int iNetSizeh);
EXPORTS int eyemNNDetectorParams(float fConfidence, float fNMSThreshold);
EXPORTS int eyemNNDetector(EyemImage tpImage, int *ipNum, BboxContainer &container, EyemImage *tpDstImg);
EXPORTS int eyemInitClassifier(const char *classifierConfigPath, const char *classifierModelPath, int ntype);
EXPORTS int eyemClassifier(EyemImage tpImage);
......@@ -925,11 +926,13 @@ extern "C" {
EXPORTS int eyemTrackFeature(EyemImage tpPrevImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum, int *ipResults, EyemImage *tpDstImg);
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 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 eyemMulFuncTool(EyemImage tpImage, EyemRect tpRoi, const char *funcName, double dThreshold, int iNumToIgnore, EyemOcsFXYR *tpCircle, EyemImage *tpDstImg);
EXPORTS int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg);
EXPORTS int eyemDrawLine(EyemImage tpImage, EyemOcsDABC tpLine);
EXPORTS int eyemDrawCircle(EyemImage tpImage, EyemOcsDXYR tpCircle);
EXPORTS int eyemDrawRectangle(EyemImage tpImag, EyemRect tpRect);
EXPORTS int eyemBuildTrainFile(const char *filePath, const char *fileName);
#ifdef __cplusplus
}
......@@ -938,6 +941,12 @@ extern "C" {
// 跳过某接口执行
extern "C" __declspec(dllexport) void setSkipProcessID(int pid);
//设置全局参数
extern "C" __declspec(dllexport) void setProcessLevel(double pl);
// 加载图像到内存
extern "C" __declspec(dllexport) void loadImage2Mem(const char *key, EyemImage tpImage);
// 日志回调定义
typedef void(__stdcall*TCallback)(const char* msg);
......
此文件类型无法预览
......@@ -83,8 +83,8 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</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>
<LibraryPath>D:\opencv420\build\x64\vc14\lib;D:\tbb2017_20170604oss\lib\intel64\vc14;D:\zxing-cpp-master\build\Release;D:\darknet\lib;D:\3rdparty\pthreads\lib;$(LibraryPath)</LibraryPath>
<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\Release;$(LibraryPath)</LibraryPath>
<TargetExt>.dll</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
......@@ -161,7 +161,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libdmtx.lib;libzxing.lib;libdecode.lib;darknet.lib;pthreadVC2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libdmtx.lib;libzxing.lib;libdecode.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
......
......@@ -4514,7 +4514,9 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
}
//图像裁剪
src = src(cv::Rect(tpRoi.iXs, tpRoi.iYs, tpRoi.iWidth, tpRoi.iHeight)).clone();
//image size
//图像备份
cv::Mat me = src.clone();
//图像尺寸
int X = src.cols, Y = src.rows;
//测试用,用于去除黑色坏点干扰
cv::Mat medBlur;
......@@ -4534,6 +4536,52 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
cv::Mat src8U;
src.convertTo(src8U, CV_8UC1, 1 / 255.);
//判断是否是料盘,20211101修改测试用
auto item = imageMap.find("back");
if (item != imageMap.end()) {
auto image_back = item->second;
//相减判断是否存在料盘
cv::Mat image_back0 = cv::Mat(image_back.iHeight, image_back.iWidth, MAKETYPE(image_back.iDepth, image_back.iChannels),
image_back.vpImage)(cv::Rect(tpRoi.iXs, tpRoi.iYs, tpRoi.iWidth, tpRoi.iHeight)).clone();
if (image_back0.channels() != 1) {
cv::cvtColor(image_back0, image_back0, cv::COLOR_BGR2GRAY);
}
//转8位
me.convertTo(me, CV_8U, 1 / 255.); image_back0.convertTo(image_back0, CV_8U, 1 / 255.);
//判断背景
cv::Mat dst;
cv::absdiff(me, image_back0, dst);
//二值化
cv::Mat bin;
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)));
//获取最大轮廓
std::vector<std::vector<cv::Point>> _contours;
cv::findContours(bin, _contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
if (_contours.empty()) {
return FUNC_CANNOT_CALC;
}
std::vector<cv::Point> contourMax = _contours[0];
for (int i = 1; i < _contours.size(); i++)
{
if (cv::contourArea(_contours[i]) > cv::contourArea(contourMax))
{
contourMax = _contours[i];
}
}
if (cv::contourArea(contourMax) < 100000)
return FUNC_CANNOT_CALC;
}
else {
//未发现图像则不进行判断
}
//显示结果图像
cv::Mat cc;
cv::cvtColor(src8U, cc, cv::COLOR_GRAY2BGRA);
......@@ -4549,7 +4597,8 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
int maxIdx[2] = { 255,255 };
cv::minMaxIdx(hist, NULL, NULL, NULL, maxIdx);
//背景阈值
int backThresh = 15 * cvRound(((double)maxIdx[0] - 2));//正常-2
processLevel = processLevel > 2.0 ? processLevel : 2.0;
int backThresh = 15 * cvRound(((double)maxIdx[0] - processLevel));//正常-2
//移除背景
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range range)->void {
for (int y = range.start; y < range.end; y++) {
......@@ -4568,14 +4617,16 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
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)));
//find the pallet
//寻找料盘
std::vector<std::vector<cv::Point>> contoursFilter;
cv::findContours(binary, contoursFilter, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
//填充内部确定料盘
cv::Mat image = cv::Mat::zeros(src8U.size(), CV_8UC1);
for (int i = 0; i < contoursFilter.size(); i++)
{
if (cv::contourArea(contoursFilter[i]) > 100000)
//根据尺寸判断是不是料盘
cv::Rect bbox = cv::boundingRect(contoursFilter[i]);
if (cv::contourArea(contoursFilter[i]) > 100000 && cv::min(bbox.height, bbox.width) > 300)//20211030修改,设置最小盘直径限制
{
cv::drawContours(image, contoursFilter, i, cv::Scalar(255), -1);
}
......@@ -4603,7 +4654,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
//掩膜
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, backThresh);
src8U.copyTo(tray, trayMask);
trays.push_back(TrayPos(reelCenter, tray, false, backThresh));
......@@ -4731,6 +4782,11 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
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));
//计算最大外接圆半径
......@@ -4922,7 +4978,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
}
}
//20210927测试用
//如果最大轮廓面积小于100000判断中间料盘影响到了定位
//如果最大轮廓面积小于85000判断中间料盘影响到了定位
if (cv::contourArea(contourMax) < 85000) {
cv::findContours(srcPrevEx0, contoursFilter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
contourMax = contoursFilter[0];
......@@ -5915,7 +5971,6 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
}
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);
......@@ -7789,6 +7844,84 @@ int eyemMarkerTracing(EyemImage tpImage, EyemHSVModel tpHSVModel, EyemOcsFXYR *t
return FUNC_OK;
}
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, bool useValLimit)
{
cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
if (image.empty())
return FUNC_IMAGE_NOT_EXIST;
int incn = image.channels();
if (incn > 3) {
cv::cvtColor(image, image, cv::COLOR_BGRA2GRAY);
}
else if (incn == 3) {
cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
}
else if (incn == 1) {
}
//裁剪
cv::Mat imageReduce = image(cv::Rect(tpRoi.iXs, tpRoi.iYs, tpRoi.iWidth, tpRoi.iHeight)).clone();
//高斯滤波
cv::Mat imagePrev;
cv::blur(imageReduce, imagePrev, cv::Size(3, 3));
cv::Mat showMat;
cv::cvtColor(image, showMat, cv::COLOR_GRAY2BGR);
std::vector<cv::Vec3f> circles;
cv::HoughCircles(imagePrev, circles, iMethod, dp, dMinDist, dParam1, dParam2, (int)dMinRadius, (int)dMaxRadius);
//
for (auto&circle : circles) {
cv::Point center = cv::Point(cvRound(circle[0]) + tpRoi.iXs,
cvRound(circle[1]) + tpRoi.iYs);
float radius = circle[2];
if (useValLimit) {
//或许加个限制
if (cv::Rect(limRoi.iXs, limRoi.iYs, limRoi.iWidth, limRoi.iHeight).contains(center)) {
//输出
tpCircle->dX = center.x;
tpCircle->dY = center.y;
tpCircle->dR = radius;
//画图
cv::circle(showMat, center, (int)radius, cv::Scalar(0, 0, 255), 3, 8, 0);
cv::circle(showMat, center, 3, cv::Scalar(0, 255, 0), -1, 8, 0);
break;
}
}
else {
//输出
tpCircle->dX = center.x;
tpCircle->dY = center.y;
tpCircle->dR = radius;
//画图
cv::circle(showMat, center, (int)radius, cv::Scalar(0, 0, 255), 3, 8, 0);
cv::circle(showMat, center, 3, cv::Scalar(0, 255, 0), -1, 8, 0);
break;
}
}
//输出结果图像
if (NULL != tpDstImg->vpImage) {
tpDstImg->iWidth = tpDstImg->iHeight = tpDstImg->iDepth = tpDstImg->iChannels = 0;
//释放
free(tpDstImg->vpImage);
tpDstImg->vpImage = NULL;
}
tpDstImg->iWidth = showMat.cols; tpDstImg->iHeight = showMat.rows; tpDstImg->iDepth = showMat.depth(); tpDstImg->iChannels = showMat.channels();
//内存尺寸
int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t);
//分配初始化内存
tpDstImg->vpImage = (uint8_t *)malloc(_Size);
if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据
memcpy(tpDstImg->vpImage, showMat.data, _Size);
return FUNC_OK;
}
int eyemMulFuncTool(EyemImage tpImage, EyemRect tpRoi, const char *funcName, double dThreshold, int iNumToIgnore, EyemOcsFXYR *tpCircle, EyemImage *tpDstImg)
{
cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone()(
......@@ -7799,7 +7932,7 @@ int eyemMulFuncTool(EyemImage tpImage, EyemRect tpRoi, const char *funcName, dou
const int X = image.cols; const int Y = image.rows;
if (strcmp(funcName, "__func1") == 0) {
if (strcmp(funcName, "__func1__") == 0) {
int incn = image.channels();
if (incn > 3) {
cv::cvtColor(image, image, cv::COLOR_BGRA2GRAY);
......@@ -7811,109 +7944,53 @@ int eyemMulFuncTool(EyemImage tpImage, EyemRect tpRoi, const char *funcName, dou
}
//高斯滤波
cv::Mat imagePrev;
cv::blur(image, imagePrev, cv::Size(15, 15));
cv::blur(image, imagePrev, cv::Size(3, 3));
//二值化
cv::Mat binary;
if (dThreshold == 0.0) {
cv::threshold(imagePrev, binary, dThreshold, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
}
else {
cv::threshold(imagePrev, binary, dThreshold, 255, cv::THRESH_BINARY_INV);
}
//去掉干扰
cv::Mat mask;
cv::morphologyEx(binary, mask, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(45, 45)));
//填充孔洞
std::vector<std::vector<cv::Point>> contours;
cv::findContours(mask, contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
for (auto contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
cv::drawContours(mask, contours, contourIdx, cv::Scalar(255), -1);
}
//计算最大连通域
cv::Mat labels, stats, centroids;
int nccomps = cv::connectedComponentsWithStats(mask, labels, stats, centroids);
double maxVal;
cv::minMaxIdx(stats(cv::Range(1, stats.rows), cv::Range(4, 5)), NULL, &maxVal);
//过滤连通域面积<=maxVal的
std::vector<uchar> colors(nccomps + 1, 0);
for (int i = 1; i < nccomps; i++) {
colors[i] = 255;
if ((stats.ptr<int>(i)[cv::CC_STAT_AREA] < maxVal))
{
colors[i] = 0;
}
}
//过滤
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range& range)->void {
for (int y = range.start; y < range.end; y++)
{
uint8_t *ptrRow = mask.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];
}
}
});
cv::Mat showMat;
cv::cvtColor(imagePrev, showMat, cv::COLOR_GRAY2BGR);
//定位
cv::findContours(mask, contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
std::vector<cv::Vec3f> circles;
cv::HoughCircles(imagePrev, circles, cv::HOUGH_GRADIENT, 1, imagePrev.rows / 8, 100, 40, 30, 45);
std::vector<EyemOcsDXY> taPoints;
for (auto&contour : contours) {
for (int n = 0; n < contour.size(); n++) {
EyemOcsDXY taPoint;
taPoint.dX = (double)contour[n].x;
taPoint.dY = (double)contour[n].y;
taPoints.push_back(taPoint);
}
// Draw the circles detected
for (size_t i = 0; i < circles.size(); i++)
{
cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// circle center
cv::circle(showMat, center, 3, cv::Scalar(0, 255, 0), -1, 8, 0);
// circle outline
circle(showMat, center, radius, cv::Scalar(0, 0, 255), 3, 8, 0);
}
double min_err;
EyemOcsDXYR _tpCircle;
eyemFitCircle((int)taPoints.size(), &taPoints[0], iNumToIgnore, min_err, _tpCircle);
//画图
cv::Mat showMat;
cv::cvtColor(image, showMat, cv::COLOR_GRAY2RGB);
cv::circle(showMat, cv::Point(cvRound(_tpCircle.dX), cvRound(_tpCircle.dY)), cvRound(_tpCircle.dR), cv::Scalar(0, 255, 0), 2);
//输出
tpCircle->fX = (float)_tpCircle.dX + (float)tpRoi.iXs;
tpCircle->fY = (float)_tpCircle.dY + (float)tpRoi.iYs;
tpCircle->fR = (float)_tpCircle.dR;
tpCircle->fX = /*(float)_tpCircle.dX +*/ (float)tpRoi.iXs;
tpCircle->fY = /*(float)_tpCircle.dY +*/ (float)tpRoi.iYs;
tpCircle->fR = /*(float)_tpCircle.dR*/0;
//输出结果图像
{
if (NULL != tpDstImg->vpImage) {
tpDstImg->iWidth = tpDstImg->iHeight = tpDstImg->iDepth = tpDstImg->iChannels = 0;
//释放
free(tpDstImg->vpImage);
tpDstImg->vpImage = NULL;
}
if (NULL != tpDstImg->vpImage) {
tpDstImg->iWidth = tpDstImg->iHeight = tpDstImg->iDepth = tpDstImg->iChannels = 0;
//释放
free(tpDstImg->vpImage);
tpDstImg->vpImage = NULL;
}
tpDstImg->iWidth = mask.cols; tpDstImg->iHeight = mask.rows; tpDstImg->iDepth = mask.depth(); tpDstImg->iChannels = mask.channels();
tpDstImg->iWidth = showMat.cols; tpDstImg->iHeight = showMat.rows; tpDstImg->iDepth = showMat.depth(); tpDstImg->iChannels = showMat.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);
if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size);
//分配初始化内存
tpDstImg->vpImage = (uint8_t *)malloc(_Size);
if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据
memcpy(tpDstImg->vpImage, mask.data, _Size);
}
//拷贝数据
memcpy(tpDstImg->vpImage, showMat.data, _Size);
}
else if (strcmp(funcName, "__func2") == 0) {
else if (strcmp(funcName, "__func2__") == 0) {
}
else {
......@@ -7923,8 +8000,58 @@ int eyemMulFuncTool(EyemImage tpImage, EyemRect tpRoi, const char *funcName, dou
return FUNC_OK;
}
int eyemBuildTrainFile(const char *filePath, const char *fileName)
{
//cv::Mat img = cv::imread(filePath, cv::IMREAD_COLOR);
//if (!img.empty())
//{
// cv::imwrite(fileName, img);
//}
std::vector<std::string> fileNames;
cv::glob(filePath, fileNames);
//打乱顺序
std::random_shuffle(fileNames.begin(), fileNames.end());
//写入文件
std::ofstream sw(fileName, std::ios::trunc);
for (auto&item : fileNames) {
std::vector<std::string> items;
split(item, "\\", items);
//
std::vector<std::string> items2(2);
split(items[items.size() - 1], ".", items2);
if (strcmp(items2[3].c_str(), "png") == 0)
{
std::string line = "data/val_images/" + items[items.size() - 1] + "\n";
sw.write(line.c_str(), line.length());
sw.flush();
}
}
sw.close();
return FUNC_OK;
}
cv::Mat load_image_cv(const std::string& fileName, cv::Scalar mean, cv::Scalar std)
{
cv::Mat img = cv::imread(fileName, cv::IMREAD_ANYCOLOR);
if (img.empty()) {
return cv::Mat();
}
int incn = img.channels();
if (incn < 3) {
cv::cvtColor(img, img, cv::COLOR_GRAY2RGB);
}
else if (incn >= 3) {
cv::cvtColor(img, img, cv::COLOR_BGR2RGB);
}
img.convertTo(img, CV_32F, 1 / 255.);
cv::subtract(img, mean, img);
cv::divide(img, std, img);
return img;
}
#include "eyemStopwatch.h"
#include "yoloWrapper.h"
int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
{
CV_Assert(NULL != tpImage.vpImage);
......@@ -7936,10 +8063,20 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
if (image.channels() > 3) {
cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
}
cv::Mat img = load_image_cv("D://Cifar//airplane_01.png", cv::Scalar(0.4914, 0.4822, 0.4465), cv::Scalar(0.2023, 0.1994, 0.2010));
cv::dnn::Net net = cv::dnn::readNetFromONNX("Cifar.onnx");
net.setPreferableBackend(cv::dnn::Backend::DNN_BACKEND_OPENCV);
net.setPreferableTarget(cv::dnn::Target::DNN_TARGET_CPU);
cv::Mat input = cv::dnn::blobFromImage(img);
net.setInput(input);
cv::Mat predicted = net.forward();
cv::imwrite("pred.png", predicted);
return FUNC_OK;
cv::Mat output = image.clone();
#pragma region darknet.lib
//int topk = 5;
//DarkNet net;
//net.setPreferableParams(0.2, topk);
......@@ -7954,31 +8091,186 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
//net.getResult(predicts, confidence, &bbox);
#pragma endregion
#pragma region test new preprocess
////转单通道
//if (image.channels() != 1)
// cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
////图像裁剪
//cv::Mat src = image(cv::Rect(200, 200, image.cols - 400, image.rows - 400)).clone();
////image size
//int X = src.cols, Y = src.rows;
////用于去除黑色坏点干扰
//cv::Mat medBlur;
//cv::medianBlur(src, 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);
//src.convertTo(src, CV_64FC1);
//src -= min;
//src /= (max - min);
//src *= 65535;
//src.convertTo(src, CV_16UC1);
//src.convertTo(output, CV_8UC1, 1 / 255.);
//转单通道
if (image.channels() != 1)
cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
//图像裁剪
cv::Mat src = image(cv::Rect(200, 200, image.cols - 400, image.rows - 400)).clone();
//image size
int X = src.cols, Y = src.rows;
//用于去除黑色坏点干扰
cv::Mat medBlur;
cv::medianBlur(src, 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);
src.convertTo(src, CV_64FC1);
src -= min;
src /= (max - min);
src *= 65535;
src.convertTo(src, CV_16UC1);
cv::Mat src8U;
src.convertTo(src8U, CV_8UC1, 1 / 255.);
cv::Mat output = src8U.clone();
//显示结果图像
cv::Mat cc;
cv::cvtColor(src8U, cc, cv::COLOR_GRAY2BGRA);
//设置bins
const int histSize = 17;
//range of values
float range[] = { 0,255 };
const float* histRange = { range };
//计算直方图
cv::Mat hist;
cv::calcHist(&src8U, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange);
//计算背景
int maxIdx[2] = { 255,255 };
cv::minMaxIdx(hist, NULL, NULL, NULL, maxIdx);
//背景阈值
int backThresh = 15 * cvRound(((double)maxIdx[0] - 2));//正常-2
//移除背景
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 (src8U.ptr<uint8_t>(y)[x] >= backThresh) {
src8U.ptr<uint8_t>(y)[x] = backThresh;
}
}
}
});
//方便显示
cc += cv::Scalar((162 - backThresh), (162 - backThresh), (162 - backThresh));
//inv
cv::bitwise_not(src8U, src8U);
cv::Mat binary;
cv::threshold(src8U, binary, (255 - backThresh), 255, cv::THRESH_BINARY);
//连接在一起
cv::morphologyEx(binary, binary, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(45, 45)));
//find the pallet
std::vector<std::vector<cv::Point>> contoursFilter;
cv::findContours(binary, contoursFilter, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
//填充内部确定料盘
cv::Mat image2 = cv::Mat::zeros(src8U.size(), CV_8UC1);
for (int i = 0; i < contoursFilter.size(); i++)
{
if (cv::contourArea(contoursFilter[i]) > 100000)
{
cv::drawContours(image2, contoursFilter, i, cv::Scalar(255), -1);
}
}
cv::bitwise_not(src8U, src8U);
//剩下即料盘区域(面积大于100000均认为是料盘)
cv::findContours(image2, 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;
TrayPos() {};
TrayPos(cv::Point2f center, cv::Mat tray, bool bSorted, double dBackThresh) :Center(center), Tray(tray), 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, backThresh);
src8U.copyTo(tray, trayMask);
trays.push_back(TrayPos(reelCenter, tray, false, backThresh));
}
cv::Mat srcPrev, srcPrevB;
cv::bitwise_not(trays[0].Tray, srcPrev);
//备份
srcPrevB = srcPrev.clone();
//二值化可以分别放在两个算法里
cv::Mat sinParts;
cv::threshold(srcPrev, sinParts, (255 - trays[0].dBackThresh), 255, cv::THRESH_BINARY);
//判断元件尺寸
int sinPartSize;
bool useTrackMethod = checkSize(srcPrev, sinParts, sinPartSize);
//连在一起
cv::morphologyEx(sinParts, sinParts, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(45, 45)));
//间隔采样,避免采样数量过大
cv::Mat linesample(image2.rows, image2.cols, CV_8UC1, cv::Scalar(0));
cv::Point start = cv::Point((int)trays[0].Center.x, (int)trays[0].Center.y), end = cv::Point((int)trays[0].Center.x, 0);
//偏移两侧取更多样本
cv::Point Offset(90, 90);
start += Offset; end += Offset;
cv::line(linesample, start, end, cv::Scalar(255), 1);
cv::line(cc, start, end, cv::Scalar(0, 255, 0, 255));
cv::LineIterator it(image2, start, end);
for (int r = 0; r < linesample.rows; r += 2)
{
cv::line(linesample, cv::Point(0, r), cv::Point(linesample.cols, r), cv::Scalar(0), 1);
}
cv::bitwise_and(linesample, sinParts, sinParts);
std::vector<cv::Point> idx;
cv::findNonZero(sinParts, idx);
int step = (idx.size() / 25);
if (step < 1)
{
step = 1;
}
std::vector<cv::Mat> mats;
for (int i = 0; i < idx.size() - 1; i += step)
{
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();
if (mat.cols == mat.rows)
{
mats.push_back(mat);
}
}
for (int i = 0; i < idx.size(); i += step)
{
cv::Point p = idx[i];
cc.at<cv::Vec4b>(p) = cv::Vec4b(0, 255, 0, 255);
//cv::rectangle(cc, cv::Rect(cv::Point(p.x - 64, p.y - 64), cv::Point(p.x + 64, p.y + 64)), cv::Scalar(0, 255, 255, 255), 1);
}
//保存到训练图像
for (int i = 0; i < mats.size(); i++)
{
std::string filePath = "";
filePath += "D:\\ResOut";
//格式化文件名
char file[64 * 4] = { 0 };
sprintf_s(file, "%s\\%d_PID010.png", filePath.c_str(), i + 58);
cv::imwrite(file, mats[i]);
}
#pragma endregion
......@@ -8143,19 +8435,19 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
#pragma endregion
if (!output.empty()) {
//<输出结果图像
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);
//分配初始化内存
tpDstImg->vpImage = (uint8_t *)malloc(_Size);
if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据
memcpy(tpDstImg->vpImage, output.data, _Size);
}
//if (!output.empty()) {
// //<输出结果图像
// 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);
// //分配初始化内存
// tpDstImg->vpImage = (uint8_t *)malloc(_Size);
// if (NULL == tpDstImg->vpImage)
// return FUNC_NOT_ENOUGH_MEM;
// memset(tpDstImg->vpImage, 0, _Size);
// //拷贝数据
// memcpy(tpDstImg->vpImage, output.data, _Size);
//}
return FUNC_OK;
}
......
......@@ -13,5 +13,7 @@ constexpr double c = PI / 180.;
extern Logger logger;
extern int killProcessID;
extern double processLevel;
extern std::map<std::string, EyemImage> imageMap;
#endif/* __EYEM_MISC_H */
......@@ -4,10 +4,13 @@ class NNDetector::Impl {
public:
Impl() {}
~Impl() {}
//目标检测
std::vector<cv::Rect> detect(const cv::Mat& img);
//目标检测器
std::shared_ptr<YoloWrapper> detector_;
//目标检测参数
float _fConfidence = 0.01f, _fNMSThreshold = 0.05f;
};
NNDetector::NNDetector(const std::string & detector_config_path,
......@@ -23,6 +26,11 @@ NNDetector::NNDetector(const std::string & detector_config_path,
}
}
void NNDetector::setInputParams(float fConfidence, float fNMSThreshold)
{
p->_fConfidence = fConfidence; p->_fNMSThreshold = fNMSThreshold;
}
std::vector<cv::Rect> NNDetector::detect(cv::InputArray img)
{
CV_Assert(!img.empty());
......@@ -41,6 +49,7 @@ std::vector<cv::Rect> NNDetector::detect(cv::InputArray img)
}
std::vector<cv::Rect> NNDetector::Impl::detect(const cv::Mat& img) {
detector_->setPreferableParams(_fConfidence, _fNMSThreshold);
return detector_->forward(img);
}
......@@ -56,6 +65,12 @@ int eyemInitNNDetector(const char *detectorConfigPath, const char *detectorModel
return FUNC_OK;
}
int eyemNNDetectorParams(float fConfidence, float fNMSThreshold)
{
pNNDetector->setInputParams(fConfidence, fNMSThreshold);
return FUNC_OK;
}
int eyemNNDetector(EyemImage tpImage, int *ipNum, BboxContainer &container, EyemImage *tpDstImg)
{
cv::Mat src = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
......@@ -106,6 +121,7 @@ int eyemNNDetector(EyemImage tpImage, int *ipNum, BboxContainer &container, Eyem
return FUNC_OK;
}
#ifdef _DEBUG
int eyemInitClassifier(const char *classifierConfigPath, const char *classifierModelPath, int ntype)
{
try {
......@@ -142,3 +158,4 @@ int eyemClassifier(EyemImage tpImage)
return FUNC_OK;
}
#endif
\ No newline at end of file
......@@ -13,7 +13,8 @@ public:
NNDetector(const std::string& detector_config_path,
const std::string& detector_model_path, const cv::Size& input_size);
NNDetector() {};
//ü
void setInputParams(float fConfidence, float fNMSThreshold);
std::vector<cv::Rect> detect(cv::InputArray img);
protected:
......@@ -23,6 +24,8 @@ protected:
cv::Ptr<NNDetector> pNNDetector;
#ifdef _DEBUG
cv::Ptr<YoloDarknet> pClassifier;
#endif
#endif/* __EYEMNNDETECTOR_H */
\ No newline at end of file
......@@ -13,6 +13,12 @@ int YoloWrapper::init(const std::string& detector_config_path,
return 0;
}
int YoloWrapper::setPreferableParams(float fConfidence, float fNMSThreshold)
{
this->confidence = fConfidence; this->NMSThreshold = fNMSThreshold;
return 0;
}
std::vector<cv::Rect> YoloWrapper::forward(cv::Mat img) {
//获取输出层名称
auto layerNames = net_.getLayerNames();
......@@ -42,13 +48,11 @@ std::vector<cv::Rect> YoloWrapper::forward(cv::Mat img) {
//置信度
cv::Mat prob = outputBlobs[n](cv::Range(row, row + 1), cv::Range(5, outputBlobs[n].cols));
double confidence;
cv::Point classIdPoint;
//取得最大分数值与索引
cv::minMaxLoc(prob, 0, &confidence, 0, &classIdPoint);
double score = .0; cv::Point classIdPoint;
cv::minMaxLoc(prob, 0, &score, 0, &classIdPoint);
//把可能的区域都算作进去
if (confidence > 0.01) {
if (score > confidence) {
cv::Mat dt = outputBlobs[n](cv::Range(row, row + 1), cv::Range(0, 5));
int cx = cvRound(dt.ptr<float>(0)[0] * (float)img.cols);
......@@ -59,14 +63,14 @@ std::vector<cv::Rect> YoloWrapper::forward(cv::Mat img) {
int left = cx - w / 2;
int top = cy - h / 2;
confidences.push_back((float)confidence);
confidences.push_back((float)score);
bboxes.push_back(cv::Rect(left, top, w, h));
}
}
}
std::vector<int> indices;
//非极大值抑制
cv::dnn::NMSBoxes(bboxes, confidences, 0.01f, 0.05f, indices);
cv::dnn::NMSBoxes(bboxes, confidences, confidence, NMSThreshold, indices);
//裁剪区域
auto points = std::vector<cv::Rect>();
for (int i = 0; i < indices.size(); i++) {
......@@ -77,6 +81,8 @@ std::vector<cv::Rect> YoloWrapper::forward(cv::Mat img) {
return points;
}
#ifdef _DEBUG
class YoloDarknet::Impl {
public:
Impl() {}
......@@ -114,3 +120,4 @@ void YoloDarknet::forward(std::vector<int> &outputPredict, std::vector<float> &o
}
delete[] predicts; predicts = NULL; delete[] confidence; confidence = NULL;
}
#endif
......@@ -8,20 +8,25 @@
#include "opencv2/dnn.hpp"
#include "opencv2/imgproc.hpp"
#ifdef _DEBUG
#include <darknet.h>
#include <yolo_class.h>
#endif
class YoloWrapper
{
public:
YoloWrapper() {};
int init(const std::string& config_path, const std::string& model_path, const cv::Size& input_size);
int setPreferableParams(float fConfidence, float fNMSThreshold);//置信度,非极大值抑制阈值
std::vector<cv::Rect> forward(cv::Mat img);
private:
cv::Size Size_;
float confidence = 0.01f, NMSThreshold = 0.05f;
cv::dnn::Net net_;
};
#ifdef _DEBUG
class YoloDarknet
{
public:
......@@ -36,6 +41,6 @@ protected:
class Impl;
cv::Ptr<Impl> p;
};
#endif
#endif/* __YOLOWRAPPER_H */
\ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!