Commit 92353bf2 张士柳

解决内圈多计数的问题;解决偶然间会计数出错的bug。

1 个父辈 d268845f
...@@ -304,23 +304,25 @@ namespace eyemLib_Sharp ...@@ -304,23 +304,25 @@ namespace eyemLib_Sharp
#endregion #endregion
#region 项目 #region 项目
//圆形/矩形(红色)mark点定位 /// <summary>
/// 圆形/矩形(红色)mark点定位
/// </summary>
/// <param name="tpImage">输入图像</param>
/// <param name="dThreshold">二值化阈值</param>
/// <param name="tpCircle">结果</param>
/// <param name="bHighAccuracy">是否是高精度定位</param>
/// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)] [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemMarkerTracing(EyemImage tpImage, double dThreshold, ref EyemOcsFXYR tpCircle, bool bHighAccuracy = false); private static extern int eyemMarkerTracing(EyemImage tpImage, double dThreshold, ref EyemOcsFXYR tpCircle, bool bHighAccuracy = false);
#endregion #endregion
#region 通用 #region 通用
// Win32 memory copy function
[DllImport("ntdll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern byte* memcpy(byte* dst, byte* src, int count);
//读取图像,支持彩色与多深度 //读取图像,支持彩色与多深度
[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);
//释放图像资源 //释放图像资源
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)] [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern void eyemImageFree(ref EyemImage tpImage); private static extern void eyemImageFree(ref EyemImage tpImage);
#endregion #endregion
//例程 //例程
...@@ -342,7 +344,7 @@ namespace eyemLib_Sharp ...@@ -342,7 +344,7 @@ namespace eyemLib_Sharp
//eyemImageFree(ref image); //eyemImageFree(ref image);
#endregion #endregion
#region //从网络读图 #region //从内存读图
//image = eyemCvtToEyemImage(bitmap); //image = eyemCvtToEyemImage(bitmap);
......
...@@ -1721,8 +1721,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -1721,8 +1721,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range range)->void { cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range range)->void {
for (int y = range.start; y < range.end; y++) { for (int y = range.start; y < range.end; y++) {
for (int x = 0; x < X; x++) { for (int x = 0; x < X; x++) {
if ((src8U.data)[(x)+(y)*X] >= backThresh) if ((src8U.data)[(x)+(y)*X] >= backThresh) {
{
(src8U.data)[(x)+(y)*X] = backThresh; (src8U.data)[(x)+(y)*X] = backThresh;
} }
} }
...@@ -2134,7 +2133,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2134,7 +2133,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
reelCenter.x = reelCenter.x > 0 && reelCenter.x < X ? reelCenter.x : 0; reelCenter.x = reelCenter.x > 0 && reelCenter.x < X ? reelCenter.x : 0;
reelCenter.y = reelCenter.y > 0 && reelCenter.y < Y ? reelCenter.y : 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); cv::drawMarker(cc, reelCenter, cv::Scalar(0, 0, 238, 255), 1, 35, 2);
//包含未粘连器件 //包含未粘连器件
image = cv::Scalar(0); image = cv::Scalar(0);
std::vector<uchar> colors(nccomps + 1, 0); std::vector<uchar> colors(nccomps + 1, 0);
...@@ -2209,10 +2207,10 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2209,10 +2207,10 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
return dMatchDeg < te.dMatchDeg; return dMatchDeg < te.dMatchDeg;
} }
}; };
////测试用 //测试用
//if (strcmp(fileName, "6H107-R50892202006136I075-20200805100224") == 0) { if (strcmp(fileName, "Img20210318120338") == 0) {
// std::cout << "_" << std::endl; std::cout << "_" << std::endl;
//} }
//缩放比例 //缩放比例
float coeff = 1.0f; float coeff = 1.0f;
//填充值 //填充值
...@@ -2220,7 +2218,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2220,7 +2218,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//元件尺寸 //元件尺寸
const double taLength = tracingAnchors[tracingAnchors.size() / 2].Length; const double taHeight = tracingAnchors[tracingAnchors.size() / 2].Height; const double taLength = tracingAnchors[tracingAnchors.size() / 2].Length; const double taHeight = tracingAnchors[tracingAnchors.size() / 2].Height;
//元件灰度值 //元件灰度值
float taMinGray; double taMaxGray = 0.0;
//标签图 //标签图
unsigned char *ucpTrackLabel = new unsigned char[Y*X](); unsigned char *ucpTrackLabel = new unsigned char[Y*X]();
cv::Mat trackMat(Y, X, CV_8UC1, ucpTrackLabel); cv::Mat trackMat(Y, X, CV_8UC1, ucpTrackLabel);
...@@ -2232,14 +2230,14 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2232,14 +2230,14 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//随机打乱顺序(降低计算错误dChordL的可能性,也为了测试在起点信息不同时的稳定性) //随机打乱顺序(降低计算错误dChordL的可能性,也为了测试在起点信息不同时的稳定性)
std::random_shuffle(tracingAnchors.begin(), tracingAnchors.end()); std::random_shuffle(tracingAnchors.begin(), tracingAnchors.end());
//开始确定起点(现在是用圆轨迹来追踪,不排除用螺旋线轨迹来追踪) //开始确定起点(现在是用圆轨迹来追踪,不排除用螺旋线轨迹来追踪)
for (std::vector<TracingAnchor>::iterator itv = tracingAnchors.begin(); itv != tracingAnchors.end(); ++itv) { for (std::vector<TracingAnchor>::iterator itvx = tracingAnchors.begin(); itvx != tracingAnchors.end(); ++itvx) {
//跳过执行 //跳过执行
if (killProcessID == 0) { if (killProcessID == 0) {
logger.t("eyemCountObjectIrregularParts 点料阶段被跳过执行..."); logger.t("eyemCountObjectIrregularParts 点料阶段被跳过执行...");
break; break;
} }
//起始位置信息 //起始位置信息
TracingAnchor ta = (*itv); TracingAnchor ta = (*itvx);
//起始位置坐标 //起始位置坐标
cv::Point2f startCenter(ta.Anchor.x, ta.Anchor.y); cv::Point2f startCenter(ta.Anchor.x, ta.Anchor.y);
//最小外包矩形 //最小外包矩形
...@@ -2255,15 +2253,18 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2255,15 +2253,18 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
__mmpts[j].x = _matx[0] * (_pts[j].x - (float)ta.RBox.boundingRect().x) + _matx[1] * (_pts[j].y - (float)ta.RBox.boundingRect().y) + _matx[2]; __mmpts[j].x = _matx[0] * (_pts[j].x - (float)ta.RBox.boundingRect().x) + _matx[1] * (_pts[j].y - (float)ta.RBox.boundingRect().y) + _matx[2];
__mmpts[j].y = _matx[3] * (_pts[j].x - (float)ta.RBox.boundingRect().x) + _matx[4] * (_pts[j].y - (float)ta.RBox.boundingRect().y) + _matx[5]; __mmpts[j].y = _matx[3] * (_pts[j].x - (float)ta.RBox.boundingRect().x) + _matx[4] * (_pts[j].y - (float)ta.RBox.boundingRect().y) + _matx[5];
} }
cv::Rect _r(cvFloor(std::min(std::min(std::min(__mmpts[0].x, __mmpts[1].x), __mmpts[2].x), __mmpts[3].x)), cv::Rect _r(cvFloor(std::min(std::min(std::min(__mmpts[0].x, __mmpts[1].x), __mmpts[2].x), __mmpts[3].x)) + 1,
cvFloor(std::min(std::min(std::min(__mmpts[0].y, __mmpts[1].y), __mmpts[2].y), __mmpts[3].y)), cvFloor(std::min(std::min(std::min(__mmpts[0].y, __mmpts[1].y), __mmpts[2].y), __mmpts[3].y)) + 1,
cvCeil(std::max(std::max(std::max(__mmpts[0].x, __mmpts[1].x), __mmpts[2].x), __mmpts[3].x)), cvCeil(std::max(std::max(std::max(__mmpts[0].x, __mmpts[1].x), __mmpts[2].x), __mmpts[3].x)),
cvCeil(std::max(std::max(std::max(__mmpts[0].y, __mmpts[1].y), __mmpts[2].y), __mmpts[3].y))); _r.width -= _r.x - 1; _r.height -= _r.y - 1; cvCeil(std::max(std::max(std::max(__mmpts[0].y, __mmpts[1].y), __mmpts[2].y), __mmpts[3].y))); _r.width -= _r.x - 1; _r.height -= _r.y - 1;
//已作标记 //已作标记
if (cv::countNonZero(ty(_r&cv::Rect(0, 0, ty.cols, ty.rows))) > 0) if (cv::countNonZero((ty(_r&cv::Rect(0, 0, ty.cols, ty.rows)) > 250)) > 0)
continue; continue;
////已做标记
//if (trackMat.ptr<uint8_t>(cvRound(startCenter.y))[cvRound(startCenter.x)] == 255) {
// continue;
//}
//获取模板图像(是否每次起点都计算模板,如果元件变形过大是否还会有用?) //获取模板图像(是否每次起点都计算模板,如果元件变形过大是否还会有用?)
if (tplMat.empty()) if (tplMat.empty())
{ {
...@@ -2278,7 +2279,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2278,7 +2279,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
double t = atan2((double)startCenter.y - reelCenter.y, (double)startCenter.x - reelCenter.x) * 180.0 / PI; double t = atan2((double)startCenter.y - reelCenter.y, (double)startCenter.x - reelCenter.x) * 180.0 / PI;
//计算旋转角度 //计算旋转角度
cv::Mat traceMat = srcPrev(_rLimits); cv::Mat traceMat = srcPrev(_rLimits);
//这里计算得出的模板不是很对 //这里计算得出的模板不是很对
float matx[6]; float matx[6];
tplMat = getTrackMat(traceMat, t + 90.0, 0, matx); tplMat = getTrackMat(traceMat, t + 90.0, 0, matx);
...@@ -2355,8 +2355,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2355,8 +2355,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
if (MIN(tplMat.size().width, tplMat.size().height) < 12.0) { if (MIN(tplMat.size().width, tplMat.size().height) < 12.0) {
coeff = 2.0f; coeff = 2.0f;
} }
// //最大
taMinGray = (float)cv::mean(tplMat)[0]; 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]) }; std::vector<cv::Point> vT = { cv::Point(_pts[0]),cv::Point(_pts[1]) ,cv::Point(_pts[2]) ,cv::Point(_pts[3]) };
...@@ -2383,7 +2383,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2383,7 +2383,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
{ {
float x = float(reelCenter.x + startRadius*cos(t*c)); float x = float(reelCenter.x + startRadius*cos(t*c));
float y = float(reelCenter.y + startRadius*sin(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)) { if (cvRound(x) < 0 || (cvRound(x) > X - 1) || cvRound(y) < 0 || (cvRound(y) > Y - 1)) {
break; break;
...@@ -2418,7 +2417,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2418,7 +2417,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
} }
//没确定出元件间距一般为结尾处,继续从下一个起点计算弦长并开始追踪 //没确定出元件间距一般为结尾处,继续从下一个起点计算弦长并开始追踪
if (dChordL <= 0.1) { if (dChordL <= 0.1) {
break; continue;
} }
//顺时针(是否并行取决于在windows下运行还是树莓派上) //顺时针(是否并行取决于在windows下运行还是树莓派上)
{ {
...@@ -2441,7 +2440,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2441,7 +2440,7 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv::Point2f predicPos; cv::Point2f predicPos;
predicPos.x = reelCenter.x + (float)trackRadius*(float)cos((trackAngle + (trackOffset + partDist))*c); predicPos.x = reelCenter.x + (float)trackRadius*(float)cos((trackAngle + (trackOffset + partDist))*c);
predicPos.y = reelCenter.y + (float)trackRadius*(float)sin((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)) { if (cvRound(predicPos.x) < 0 || (cvRound(predicPos.x) > X - 1) || cvRound(predicPos.y) < 0 || (cvRound(predicPos.y) > Y - 1)) {
trayEnd = true; trayEnd = true;
break; break;
...@@ -2509,12 +2508,13 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2509,12 +2508,13 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv::Mat mmRescaling; cv::Mat mmRescaling;
cv::normalize(dst, mmRescaling, 1.0, 0.0, cv::NORM_MINMAX); cv::normalize(dst, mmRescaling, 1.0, 0.0, cv::NORM_MINMAX);
//测试用:模板匹配,为了尽量避免定位出错 //模板匹配,为了尽量避免定位出错
cv::Mat _tplMat; cv::Mat _tplMat;
tplMat.convertTo(_tplMat, CV_32FC1); tplMat.convertTo(_tplMat, CV_32FC1);
if (coeff > 1.0f) { if (coeff > 1.0f) {
cv::resize(_tplMat, _tplMat, cv::Size(), coeff, coeff); cv::resize(_tplMat, _tplMat, cv::Size(), coeff, coeff);
} }
//考虑并行计算两个模板结果
cv::Mat tplResult0; cv::Mat tplResult0;
cv::matchTemplate(_traceMat, _tplMat, tplResult0, cv::TM_SQDIFF_NORMED); cv::matchTemplate(_traceMat, _tplMat, tplResult0, cv::TM_SQDIFF_NORMED);
...@@ -2554,19 +2554,21 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2554,19 +2554,21 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
} }
} }
//目标元件在小图中的位置
cv::Point2f maxLox;
//元件位置判断 //元件位置判断
if (_vParts.size() <= 0) { if (_vParts.size() <= 0) {
//大概率终止 //大概率终止
trayEnd = true; trayEnd = true;
} }
else if (_vParts.size() == 1) { else if (_vParts.size() == 1) {
//大概率不会出错 //有可能会出错
cv::Point2f maxLoc = cv::Point2f(_vParts[0].Pos.x, _vParts[0].Pos.y); maxLox = cv::Point2f(_vParts[0].Pos.x / coeff, _vParts[0].Pos.y / coeff);
if (tRecF.contains(cv::Point2f(maxLoc.x / coeff, maxLoc.y / coeff))) { if (tRecF.contains(maxLox)) {
//计算旋转前的坐标(即匹配的最终坐标) //计算旋转前的坐标(即匹配的最终坐标)
float realX = 0.0f, realY = 0.0f; float realX = 0.0f, realY = 0.0f;
realX = (float)rLimits.tl().x + ((maxLoc.x / coeff - matx[2])*matx[4] - (maxLoc.y / coeff - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]); 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 + ((maxLoc.x / coeff - matx[2])*matx[3] - (maxLoc.y / coeff - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]); 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]; cv::Point2f pts[4];
...@@ -2602,7 +2604,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2602,7 +2604,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//排序 //排序
std::sort(__vParts.begin(), __vParts.end(), std::less<Track>()); std::sort(__vParts.begin(), __vParts.end(), std::less<Track>());
cv::Point2f maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff); //在小图中的位置
maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff);
//计算旋转前的坐标(即匹配的最终坐标) //计算旋转前的坐标(即匹配的最终坐标)
float realX = 0.0f, realY = 0.0f; float realX = 0.0f, realY = 0.0f;
...@@ -2627,12 +2630,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2627,12 +2630,12 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//存在多个峰值,先判断分数最高是否位于理论位置 //存在多个峰值,先判断分数最高是否位于理论位置
std::sort(_vParts.begin(), _vParts.end(), std::greater<Track>()); std::sort(_vParts.begin(), _vParts.end(), std::greater<Track>());
for (auto&_vPart : _vParts) { for (auto&_vPart : _vParts) {
cv::Point2f maxLoc = cv::Point2f(_vPart.Pos.x, _vPart.Pos.y); maxLox = cv::Point2f(_vPart.Pos.x / coeff, _vPart.Pos.y / coeff);
if (tRecF.contains(cv::Point2f(maxLoc.x / coeff, maxLoc.y / coeff))) { if (tRecF.contains(maxLox)) {
//计算旋转前的坐标(即匹配的最终坐标) //计算旋转前的坐标(即匹配的最终坐标)
float realX = 0.0f, realY = 0.0f; float realX = 0.0f, realY = 0.0f;
realX = (float)rLimits.tl().x + ((maxLoc.x / coeff - matx[2])*matx[4] - (maxLoc.y / coeff - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]); 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 + ((maxLoc.x / coeff - matx[2])*matx[3] - (maxLoc.y / coeff - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]); 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]; cv::Point2f pts[4];
...@@ -2671,7 +2674,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2671,7 +2674,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//排序 //排序
std::sort(__vParts.begin(), __vParts.end(), std::less<Track>()); std::sort(__vParts.begin(), __vParts.end(), std::less<Track>());
cv::Point2f maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff); //在小图中的位置
maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff);
//计算旋转前的坐标(即匹配的最终坐标) //计算旋转前的坐标(即匹配的最终坐标)
float realX = 0.0f, realY = 0.0f; float realX = 0.0f, realY = 0.0f;
...@@ -2692,9 +2696,26 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2692,9 +2696,26 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
} }
} }
} }
#ifdef _DEBUG
cc.ptr<cv::Vec4b>(cvRound(predicPos.y))[cvRound(predicPos.x)] = cv::Vec4b(100, 100, 238, 255); if (!vParts.empty()) {
#endif //显示用
//cv::Mat traceMat4, traceMat5;
//_traceMat.convertTo(traceMat4, CV_8U);
//traceMat.convertTo(traceMat5, CV_8U);
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);
//cv::rectangle(traceMat5, tRec_, cv::Scalar(0));
//cv::rectangle(traceMat4, _rr, cv::Scalar(0));
//当作一种辅助手段,无需设置太严格
double dmax;
cv::minMaxLoc(traceMat(tRec_).clone(), NULL, &dmax);
if (dmax < 0.75*taMaxGray) {
trayEnd = true;
}
}
break; break;
} }
//追踪终止,选取下一个起点 //追踪终止,选取下一个起点
...@@ -2831,12 +2852,13 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2831,12 +2852,13 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
cv::Mat mmRescaling; cv::Mat mmRescaling;
cv::normalize(dst, mmRescaling, 1.0, 0.0, cv::NORM_MINMAX); cv::normalize(dst, mmRescaling, 1.0, 0.0, cv::NORM_MINMAX);
//测试用:模板匹配,为了尽量避免定位出错 //模板匹配,为了尽量避免定位出错
cv::Mat _tplMat; cv::Mat _tplMat;
tplMat.convertTo(_tplMat, CV_32FC1); tplMat.convertTo(_tplMat, CV_32FC1);
if (coeff > 1.0f) { if (coeff > 1.0f) {
cv::resize(_tplMat, _tplMat, cv::Size(), coeff, coeff); cv::resize(_tplMat, _tplMat, cv::Size(), coeff, coeff);
} }
//考虑并行计算两个模板结果
cv::Mat tplResult0; cv::Mat tplResult0;
cv::matchTemplate(_traceMat, _tplMat, tplResult0, cv::TM_SQDIFF_NORMED); cv::matchTemplate(_traceMat, _tplMat, tplResult0, cv::TM_SQDIFF_NORMED);
...@@ -2874,20 +2896,21 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2874,20 +2896,21 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
_vParts.push_back(Track(0, 0, confidence, cv::Point2f((float)pt.x, (float)pt.y), std::vector<cv::Point2f>())); _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) { if (_vParts.size() <= 0) {
//大概率终止 //大概率终止
trayEnd = true; trayEnd = true;
} }
else if (_vParts.size() == 1) { else if (_vParts.size() == 1) {
maxLox = cv::Point2f(_vParts[0].Pos.x / coeff, _vParts[0].Pos.y / coeff);
//有可能会出错,当靠的太近可能只存在一个峰值 //有可能会出错,当靠的太近可能只存在一个峰值
cv::Point2f maxLoc = cv::Point2f(_vParts[0].Pos.x, _vParts[0].Pos.y); if (tRecF.contains(maxLox)) {
if (tRecF.contains(cv::Point2f(maxLoc.x / coeff, maxLoc.y / coeff))) {
//计算旋转前的坐标(即匹配的最终坐标) //计算旋转前的坐标(即匹配的最终坐标)
float realX = 0.0f, realY = 0.0f; float realX = 0.0f, realY = 0.0f;
realX = (float)rLimits.tl().x + ((maxLoc.x / coeff - matx[2])*matx[4] - (maxLoc.y / coeff - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]); 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 + ((maxLoc.x / coeff - matx[2])*matx[3] - (maxLoc.y / coeff - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]); 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]; cv::Point2f pts[4];
...@@ -2922,8 +2945,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2922,8 +2945,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//排序 //排序
std::sort(__vParts.begin(), __vParts.end(), std::less<Track>()); std::sort(__vParts.begin(), __vParts.end(), std::less<Track>());
cv::Point2f maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff); //小图中的定位坐标
maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff);
//计算旋转前的坐标(即匹配的最终坐标) //计算旋转前的坐标(即匹配的最终坐标)
float realX = 0.0f, realY = 0.0f; 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]); 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]);
...@@ -2941,24 +2964,18 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2941,24 +2964,18 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
{ {
cv::line(cc, predicBox[j], predicBox[(j + 1) % 4], cv::Scalar(0, 0, 238, 255), 1); cv::line(cc, predicBox[j], predicBox[(j + 1) % 4], cv::Scalar(0, 0, 238, 255), 1);
} }
////显示用
//cv::Mat traceMat4, traceMat5;
//_traceMat.convertTo(traceMat4, CV_8U);
//traceMat.convertTo(traceMat5, CV_8U);
//cv::rectangle(traceMat5, rr, cv::Scalar(0));
//cv::rectangle(traceMat4, _rr, cv::Scalar(0));
} }
} }
else { else {
//存在定位出错的可能性,先判断分数最高是否位于理论位置 //存在定位出错的可能性,先判断分数最高是否位于理论位置
std::sort(_vParts.begin(), _vParts.end(), std::greater<Track>()); std::sort(_vParts.begin(), _vParts.end(), std::greater<Track>());
for (auto&_vPart : _vParts) { for (auto&_vPart : _vParts) {
cv::Point2f maxLoc = cv::Point2f(_vPart.Pos.x, _vPart.Pos.y); maxLox = cv::Point2f(_vPart.Pos.x / coeff, _vPart.Pos.y / coeff);
if (tRecF.contains(cv::Point2f(maxLoc.x / coeff, maxLoc.y / coeff))) { if (tRecF.contains(maxLox)) {
//计算旋转前的坐标(即匹配的最终坐标) //计算旋转前的坐标(即匹配的最终坐标)
float realX = 0.0f, realY = 0.0f; float realX = 0.0f, realY = 0.0f;
realX = (float)rLimits.tl().x + ((maxLoc.x / coeff - matx[2])*matx[4] - (maxLoc.y / coeff - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]); 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 + ((maxLoc.x / coeff - matx[2])*matx[3] - (maxLoc.y / coeff - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]); 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]; cv::Point2f pts[4];
...@@ -2996,8 +3013,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -2996,8 +3013,8 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
//排序 //排序
std::sort(__vParts.begin(), __vParts.end(), std::less<Track>()); std::sort(__vParts.begin(), __vParts.end(), std::less<Track>());
cv::Point2f maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff); //小图中的位置
maxLox = cv::Point2f(__vParts[0].Pos.x / coeff, __vParts[0].Pos.y / coeff);
//计算旋转前的坐标(即匹配的最终坐标) //计算旋转前的坐标(即匹配的最终坐标)
float realX = 0.0f, realY = 0.0f; 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]); 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]);
...@@ -3017,13 +3034,25 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -3017,13 +3034,25 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
} }
} }
} }
#ifdef _DEBUG if (!vParts.empty()) {
cc.ptr<cv::Vec4b>(cvRound(predicPos.y))[cvRound(predicPos.x)] = cv::Vec4b(100, 100, 238, 255); ////显示用
//for (int j = 0; j < 4; j++) //cv::Mat traceMat4, traceMat5;
//{ //_traceMat.convertTo(traceMat4, CV_8U);
// cv::line(cc, predicBox[j], predicBox[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1); //traceMat.convertTo(traceMat5, CV_8U);
//} //cv::rectangle(traceMat5, rr, cv::Scalar(0));
#endif //cv::rectangle(traceMat4, _rr, cv::Scalar(0));
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.75*taMaxGray) {
trayEnd = true;
}
}
break; break;
} }
//接着下一个起点 //接着下一个起点
...@@ -3998,7 +4027,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char ...@@ -3998,7 +4027,6 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
} }
} }
} }
//计数 //计数
std::vector<cv::Point> idx; std::vector<cv::Point> idx;
cv::findNonZero(binary, idx); cv::findNonZero(binary, idx);
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!