Commit 592aab70 张士柳

1 个父辈 de2afb31
...@@ -23,11 +23,13 @@ namespace eyemLib_Sharp ...@@ -23,11 +23,13 @@ namespace eyemLib_Sharp
//} //}
//EyemLib.eyemTest2(fileNames); //EyemLib.eyemTest2(fileNames);
foreach (var item in fileNames) foreach (var item in fileNames)
{ {
EyemLib.eyemReadImageTool(item); EyemLib.eyemReadImageTool(item);
} }
//for (int i = 0; i < 1; i++) //for (int i = 0; i < 1; i++)
//{ //{
// EyemLib.eyemTestVideoCapture("D:\\插件完成检测\\视频\\cap5.mp4"); // EyemLib.eyemTestVideoCapture("D:\\插件完成检测\\视频\\cap5.mp4");
......
...@@ -3776,10 +3776,11 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons ...@@ -3776,10 +3776,11 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
if (src.channels() != 1) if (src.channels() != 1)
cv::cvtColor(src, src, cv::COLOR_BGR2GRAY); cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);
//环鸿&佳世达图像裁剪 //图像裁剪
//src = src(cv::Range(200, src.cols - 70), cv::Range(200, src.rows - 10)).clone(); //环鸿&佳世达
src = src(cv::Range(200, src.cols - 70), cv::Range(200, src.rows - 10)).clone();
//苏州公司&成都纬创 //苏州公司&成都纬创
src = src(cv::Range(10, src.cols - 10), cv::Range(10, src.rows - 10)).clone(); //src = src(cv::Range(10, src.cols - 10), cv::Range(10, src.rows - 10)).clone();
//图像尺寸 //图像尺寸
int X = src.cols, Y = src.rows; int X = src.cols, Y = src.rows;
...@@ -3990,7 +3991,8 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons ...@@ -3990,7 +3991,8 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
cv::Rect rec = cv::boundingRect(contourMax); cv::Rect rec = cv::boundingRect(contourMax);
cv::Point tl, br, tr, bl; cv::Point tl, br, tr, bl;
tl = rec.tl(); br = rec.br(); tr = cv::Point(tl.x + rec.width, tl.y); bl = cv::Point(tl.x, tl.y + rec.height); tl = cv::Point(cv::max(rec.tl().x - 35, 0), cv::max(rec.tl().y - 35, 0)); br = cv::Point(cv::min(rec.br().x + 35, Y), cv::min(rec.br().y + 35, Y));
tr = cv::Point(br.x, tl.y); bl = cv::Point(tl.x, br.y);
//加载模板 //加载模板
cv::Mat tplMat = cv::imread("D://批量测试图像2//template.png", -1); cv::Mat tplMat = cv::imread("D://批量测试图像2//template.png", -1);
...@@ -4002,7 +4004,11 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons ...@@ -4002,7 +4004,11 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
const float icvDirections[4] = { 0 , 90 , 180 , -90 }; const float icvDirections[4] = { 0 , 90 , 180 , -90 };
//用以计算元件中心 //用以计算元件中心
const int icvDirectionDeltas[4][2] = { { tplWidth / 2,tplHeight / 2 },{ tplHeight / 2,tplWidth / 2 },{ tplWidth / 2,tplHeight / 2 },{ tplHeight / 2,tplWidth / 2 } }; const int icvDirectionDeltas[4][2] = { { tplWidth / 2,tplHeight / 2 },{ tplHeight / 2,tplWidth / 2 },{ tplWidth / 2,tplHeight / 2 },\
{ tplHeight / 2,tplWidth / 2 } };
//用于计数
cv::Mat matchParts(Y, X, CV_8UC1, cv::Scalar(0));
cv::parallel_for_(cv::Range(0, 4), [&](const cv::Range& range)->void { cv::parallel_for_(cv::Range(0, 4), [&](const cv::Range& range)->void {
for (int tpl = range.start; tpl < range.end; tpl++) for (int tpl = range.start; tpl < range.end; tpl++)
...@@ -4024,559 +4030,483 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons ...@@ -4024,559 +4030,483 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
cv::Mat tplMatD; cv::Mat tplMatD;
cv::warpAffine(tplMat, tplMatD, matx23f, cv::Size((int)width, (int)height), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0)); cv::warpAffine(tplMat, tplMatD, matx23f, cv::Size((int)width, (int)height), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0));
//模板匹配(TODO:仅处理料盘区域以提高速度) //模板匹配(仅处理料盘区域以提高速度)
cv::Mat tplResult0; cv::Mat tplResult0;
cv::matchTemplate(srcPrev, tplMatD, tplResult0, cv::TM_CCOEFF_NORMED); cv::matchTemplate(srcPrev(cv::Rect(tl, br)), tplMatD, tplResult0, cv::TM_CCOEFF_NORMED);
//为什么尺寸会发生变化
int bottom, right;
bottom = (Y - tplResult0.rows), right = (X - tplResult0.cols);
cv::copyMakeBorder(tplResult0, tplResult0, 0, bottom, 0, right, cv::BORDER_CONSTANT, cv::Scalar(0));
//分数大于0.7才当作元件处理 //分数大于0.7才当作元件处理
cv::Mat bin = cv::Mat(tplResult0 > dMinScore); tplResult0 = cv::Mat(tplResult0 > dMinScore);
cv::Point quard[4]{ tr,tl,bl,br }; cv::Point quard[4]{ cv::Point(tplResult0.cols,0),cv::Point(0,0),cv::Point(0,tplResult0.rows),cv::Point(tplResult0.cols,tplResult0.rows) };
std::vector<cv::Point> pt = { cv::Point(reelCenter),quard[tpl], quard[(tpl + 1) % 4] }; std::vector<cv::Point> pt = { cv::Point(tplResult0.cols / 2,tplResult0.rows / 2),quard[tpl], quard[(tpl + 1) % 4] };
std::vector<std::vector<cv::Point>> pts; std::vector<std::vector<cv::Point>> pts;
pts.push_back(pt); pts.push_back(pt);
cv::Mat dirMask(Y, X, CV_8UC1, cv::Scalar(0)); cv::Mat dirMask(tplResult0.size(), CV_8UC1, cv::Scalar(0));
cv::drawContours(dirMask, pts, 0, cv::Scalar(255), -1); cv::drawContours(dirMask, pts, 0, cv::Scalar(255), -1);
//除去非必要部分 //除去非必要部分
cv::bitwise_and(bin, dirMask, bin); cv::bitwise_and(tplResult0, dirMask, tplResult0);
//连通域分析 //连通域分析
cv::Mat labels, stats, centroids; cv::Mat labels, stats, centroids;
int nccomps2 = cv::connectedComponentsWithStats(bin, labels, stats, centroids); int nccomps = cv::connectedComponentsWithStats(tplResult0, labels, stats, centroids);
for (int i = 1; i < nccomps2; i++) { for (int i = 1; i < nccomps; i++) {
cv::drawMarker(cc, cv::Point(cvRound(centroids.ptr<double>(i)[0]) + icvDirectionDeltas[tpl][0], cvRound(centroids.ptr<double>(i)[1]) + icvDirectionDeltas[tpl][1]), cv::Scalar(0, 255, 0, 255)); cv::Point matchPt(cvRound(centroids.ptr<double>(i)[0]) + icvDirectionDeltas[tpl][0] + tl.x, \
cvRound(centroids.ptr<double>(i)[1]) + icvDirectionDeltas[tpl][1] + tl.y);
matchParts.ptr<uint8_t>(matchPt.y)[matchPt.x] = 255;
} }
} }
}); });
if (false) ///<追踪元件算法
//标记初始区域
std::vector<cv::Point> matchPts;
cv::findNonZero(matchParts, matchPts);
//单个元件尺寸
double sinPartSize = (double)tplWidth*(double)tplHeight;
//标签图
unsigned char *ucpTrackLabel = new unsigned char[Y*X]();
cv::Mat trackMat(Y, X, CV_8UC1, ucpTrackLabel);
clock_t begin = clock();
//开始追踪
for (std::vector<cv::Point>::iterator itv = matchPts.begin(); itv != matchPts.end(); ++itv)
{ {
double sinPartSize = 0.5; //已标记
if (trackMat.ptr<uint8_t>((*itv).y)[(*itv).x] == 255)
////包含未粘连器件 continue;
//image = cv::Scalar(0);
//std::vector<uchar> colors(nccomps + 1, 0); //追踪起点
//for (int i = 1; i < nccomps; i++) { cv::Point2f startCenter((float)(*itv).x, (float)(*itv).y);
// colors[i] = 255;
// if ((((int *)m2.data)[(cv::CC_STAT_AREA) + (i)*m2.cols] >= 1.4*sinPartSize) || (((int *)m2.data)[(cv::CC_STAT_AREA) + (i)*m2.cols] < 0.4*sinPartSize))//经验值 //计算元件区域
// { cv::Point2f points[4];
// 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);
//追踪直至没有单个元件存在
bool bExistSingle = true;
//用于计数
cv::Mat lb4Count(Y, X, CV_8UC1, cv::Scalar(0));
//标签图
unsigned char *ucpTrackLabel = new unsigned char[Y*X]();
cv::Mat trackMat(Y, X, CV_8UC1, ucpTrackLabel);
do
{ {
//不随机挑选起点(考虑换成面积最小的那个) double t = atan2((double)(*itv).y - reelCenter.y, (double)(*itv).x - reelCenter.x) * 180 / PI;
std::vector<cv::Point> contourMin;
cv::findContours(image, contoursFilter, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
//终止追踪
if (contoursFilter.size() <= 0) break;
//大于等于1个随机挑选
if (contoursFilter.size() > 1)
{
//随机数生成
srand((unsigned)time(NULL));
contourMin = contoursFilter[rand() % (contoursFilter.size() - 1)];
for (int fc = 0; fc < contoursFilter.size(); fc++)
{
if (cv::contourArea(contoursFilter[fc]) > 0.4*sinPartSize)
{
if (cv::contourArea(contoursFilter[fc]) < cv::contourArea(contourMin))
{
contourMin = contoursFilter[fc];
}
}
}
}
else if (contoursFilter.size() == 1)
{
contourMin = contoursFilter[0];
}
//去掉起始位置
std::vector<std::vector<cv::Point>> vTempRect;
vTempRect.push_back(contourMin);
cv::drawContours(image, vTempRect, 0, cv::Scalar(0), -1);
//最小外包矩形
cv::RotatedRect rect = cv::minAreaRect(contourMin);
cv::Point2f points[4];
rect.points(points);
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, points[j], points[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1);
//}
//追踪起点
cv::Point2f startCenter((points[0].x + points[1].x + points[2].x + points[3].x) / 4.f, (points[0].y + points[1].y + points[2].y + points[3].y) / 4.f);
//打标签
cv::Mat labels;
int nccomps = cv::connectedComponents(image, labels);
//去掉已处理的分离器件
std::vector<uchar> labeled(nccomps + 1, 0);
//标记为已追踪过
std::vector<cv::Point> vT = { cv::Point(points[0]),cv::Point(points[1]) ,cv::Point(points[2]) ,cv::Point(points[3]) };
cv::fillConvexPoly(trackMat, vT, cv::Scalar(255));
//起点加入计数
cv::circle(lb4Count, cv::Point(startCenter), 0, cv::Scalar(255), 1);
cv::circle(cc, cv::Point(startCenter), 2, cv::Scalar(0, 255, 0, 255), 1);
///<追踪元件算法
struct Track {
int iLimit, iPartSize;
double dMatchDeg;
cv::Point Pos;
std::vector<cv::Point2f> Rect;
Track() {}; const double trackLength = tplWidth / 2, trackWidth = tplHeight / 4;
Track(int iLimit, int iPartSize, double dMatchDeg, cv::Point Pos, std::vector<cv::Point2f> Rect) :iLimit(iLimit), iPartSize(iPartSize), dMatchDeg(dMatchDeg), Pos(Pos), Rect(Rect) {}; float b = (float)cos(t*c)*0.5f;
float a = (float)sin(t*c)*0.5f;
bool operator >(const Track &te)const points[0].x = float((*itv).x - a*trackLength * 2 - b*trackWidth * 4);
{ points[0].y = float((*itv).y + b*trackLength * 2 - a*trackWidth * 4);
return dMatchDeg > te.dMatchDeg; points[1].x = float((*itv).x + a*trackLength * 2 - b*trackWidth * 4);
} points[1].y = float((*itv).y - b*trackLength * 2 - a*trackWidth * 4);
}; points[2].x = float(2 * (*itv).x - points[0].x);
//扫描步长 points[2].y = float(2 * (*itv).y - points[0].y);
const double dMinorStep = 0.1; points[3].x = float(2 * (*itv).x - points[1].x);
//追踪长宽 points[3].y = float(2 * (*itv).y - points[1].y);
const double trackLength = std::max(rect.size.width / 2, rect.size.height / 2), trackWidth = std::min(rect.size.width / 4, rect.size.height / 4); }
//起始扫描角度
const double startAngle = atan2((double)startCenter.y - reelCenter.y, (double)startCenter.x - reelCenter.x) * 180 / PI; //标记为已追踪过
//起始扫描半径 std::vector<cv::Point> vT = { cv::Point(points[0]),cv::Point(points[1]) ,cv::Point(points[2]) ,cv::Point(points[3]) };
const double startRadius = cv::norm(startCenter - reelCenter); cv::fillConvexPoly(trackMat, vT, cv::Scalar(255));
//偏移角度(元件尺寸)
const double dOffset = (2 * asin(2 * trackLength / (2 * startRadius))) * 180 / PI; struct Track {
//偏移角度(元件间距) int iLimit, iPartSize;
const double dScanRange = 15; double dMatchDeg;
//追踪元件间距(弦长,可以尽量避免因个别器件偏离导致的追踪中断) cv::Point Pos;
double dChordL = .0; std::vector<cv::Point2f> Rect;
for (double t = startAngle + dOffset / 1.5; t < startAngle + dOffset / 1.5 + dScanRange; t += dMinorStep)
Track() {};
Track(int iLimit, int iPartSize, double dMatchDeg, cv::Point Pos, std::vector<cv::Point2f> Rect) :iLimit(iLimit), \
iPartSize(iPartSize), dMatchDeg(dMatchDeg), Pos(Pos), Rect(Rect) {};
bool operator >(const Track &te)const
{ {
float x = float(reelCenter.x + startRadius*cos(t*c)); return dMatchDeg > te.dMatchDeg;
float y = float(reelCenter.y + startRadius*sin(t*c)); }
//初次确定元件间距 };
const double angle = atan2((double)reelCenter.y - y, (double)reelCenter.x - x); //扫描步长
const double dMinorStep = 0.1;
//追踪长宽
const double trackLength = (double)tplWidth / 2., trackWidth = (double)tplHeight / 4.;
//起始扫描角度
const double startAngle = atan2((double)startCenter.y - reelCenter.y, (double)startCenter.x - reelCenter.x) * 180 / PI;
//起始扫描半径
const double startRadius = cv::norm(startCenter - reelCenter);
//偏移角度(元件尺寸)
const double dOffset = (2 * asin(2 * trackLength / (2 * startRadius))) * 180 / PI;
//偏移角度(元件间距)
const double dScanRange = 15;
//追踪元件间距(弦长,可以尽量避免因个别器件偏离导致的追踪中断)
double dChordL = .0;
for (double t = startAngle + (dOffset / 1.5); t < startAngle + (dOffset / 1.5) + dScanRange; t += dMinorStep)
{
float x = float(reelCenter.x + startRadius*cos(t*c));
float y = float(reelCenter.y + startRadius*sin(t*c));
//初次确定元件间距
const double angle = atan2((double)reelCenter.y - y, (double)reelCenter.x - x);
cv::Point p1 = cv::Point(cvRound(x + trackWidth * cos(angle)), cv::Point p1 = cv::Point(cvRound(x + trackWidth * cos(angle)),
cvRound(y + trackWidth * sin(angle))); cvRound(y + trackWidth * sin(angle)));
cv::Point p2 = cv::Point(cvRound(x + trackWidth * cos(angle + CV_PI)), cv::Point p2 = cv::Point(cvRound(x + trackWidth * cos(angle + CV_PI)),
cvRound(y + trackWidth * sin(angle + CV_PI))); cvRound(y + trackWidth * sin(angle + CV_PI)));
cv::LineIterator it(binary, p1, p2, 4); cv::LineIterator it(binary, p1, p2, 4);
for (int n = 0; n < it.count; n++, ++it) for (int n = 0; n < it.count; n++, ++it)
{
if ((binary.data)[(it.pos().x) + (it.pos().y)*X] == 255)
{ {
if ((binary.data)[(it.pos().x) + (it.pos().y)*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);
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 > 0)
break; break;
}
} }
//并行处理 if (dChordL > 0)
//#pragma omp parallel sections break;
}
//标记当前位置
cv::circle(cc, cv::Point(startCenter), 2, cv::Scalar(0, 255, 0, 255), 1);
for (int j = 0; j < 4; j++)
{
cv::line(cc, points[j], points[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1);
}
//无法计算元件间距
if (dChordL <= 0) {
continue;
}
//并行处理
//#pragma omp parallel sections
{
//(顺时针)
//#pragma omp section
{ {
//(顺时针) //追踪中心
//#pragma omp section cv::Point2f trackCenter = cv::Point2f(startCenter.x, startCenter.y);
//追踪角度、半径
double trackAngle = startAngle, trackRadius = startRadius;
//元件本身角度
double trackOffset = dOffset;
//元件间间距
double partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//外包矩形顶点
cv::Point2f pts[4];
//结束位置
Track trackEndPos;
//开始追踪
bool trackEnd = true;
do
{ {
//追踪中心 bool found = true;
cv::Point2f trackCenter = cv::Point2f(startCenter.x, startCenter.y); std::vector<Track> vParts;
//追踪角度、半径 for (double t = trackAngle + (trackOffset / 2.0 + partDist); t < trackAngle + (trackOffset / 2.0 + partDist) + trackOffset; \
double trackAngle = startAngle, trackRadius = startRadius; t += dMinorStep)
//元件本身角度
double trackOffset = dOffset;
//元件间间距
double partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//外包矩形顶点
cv::Point2f pts[4];
//结束位置
Track trackEndPos;
//开始追踪
bool trackEnd = true;
do
{ {
bool found = true; trackCenter.x = reelCenter.x + (float)trackRadius*(float)cos(t*c);
std::vector<Track> vParts; trackCenter.y = reelCenter.y + (float)trackRadius*(float)sin(t*c);
for (double t = trackAngle + (trackOffset / 2.0 + partDist); t < trackAngle + (trackOffset / 2.0 + partDist) + trackOffset; t += dMinorStep)
{
trackCenter.x = reelCenter.x + (float)trackRadius*(float)cos(t*c);
trackCenter.y = reelCenter.y + (float)trackRadius*(float)sin(t*c);
float b = (float)cos(t*c)*0.5f; float b = (float)cos(t*c)*0.5f;
float a = (float)sin(t*c)*0.5f; float a = (float)sin(t*c)*0.5f;
pts[0].x = float(trackCenter.x - a*trackLength * 2 - b*trackWidth * 4); pts[0].x = float(trackCenter.x - a*trackLength * 2 - b*trackWidth * 4);
pts[0].y = float(trackCenter.y + b*trackLength * 2 - a*trackWidth * 4); pts[0].y = float(trackCenter.y + b*trackLength * 2 - a*trackWidth * 4);
pts[1].x = float(trackCenter.x + a*trackLength * 2 - b*trackWidth * 4); pts[1].x = float(trackCenter.x + a*trackLength * 2 - b*trackWidth * 4);
pts[1].y = float(trackCenter.y - b*trackLength * 2 - a*trackWidth * 4); pts[1].y = float(trackCenter.y - b*trackLength * 2 - a*trackWidth * 4);
pts[2].x = float(2 * trackCenter.x - pts[0].x); pts[2].x = float(2 * trackCenter.x - pts[0].x);
pts[2].y = float(2 * trackCenter.y - pts[0].y); pts[2].y = float(2 * trackCenter.y - pts[0].y);
pts[3].x = float(2 * trackCenter.x - pts[1].x); pts[3].x = float(2 * trackCenter.x - pts[1].x);
pts[3].y = float(2 * trackCenter.y - pts[1].y); pts[3].y = float(2 * trackCenter.y - pts[1].y);
std::vector<cv::Point> vPoints; std::vector<cv::Point> vPoints;
std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f)); std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
//获取内部坐标 //获取内部坐标
calcRotateRect(vRect, vPoints); calcRotateRect(vRect, vPoints);
//计算灰度值 //计算灰度值
double dMatch = 0; double dMatch = 0;
for (int v = 0; v < vPoints.size(); v++) for (int v = 0; v < vPoints.size(); v++)
{
if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y)
{
dMatch += (srcPrev.data)[(vPoints[v].x) + (vPoints[v].y)*X];
}
}
dMatch /= (double)vPoints.size();
//仅扫描一个元件的角度
vParts.push_back(Track(0, 0, dMatch, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), vRect));
//cv::circle(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), 0, cv::Scalar(0, 255, 255, 255), 1);
}
if (vParts.size() == 0) continue;
//
trackEndPos = vParts[vParts.size() / 2];
//灰度极值认为是元件
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新位置
trackCenter = cv::Point(vParts[0].Pos.x, vParts[0].Pos.y);
//更新扫描角度
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI;
//纵向扫描
vParts.clear();
std::vector<cv::Point> trackLine;
drawLine(cc, reelCenter, trackCenter, cv::Scalar(0, 255, 255, 255), 1, trackLength, trackWidth * 2, trackLine);
//更改纵向扫描方向,分两个方向?
cv::LineIterator it(binary, trackLine[0], trackLine[1], 4);
for (int n = 0; n < it.count; n++, ++it)
{ {
float b = (float)cos(trackAngle*PI / 180.)*0.5f; if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y)
float a = (float)sin(trackAngle*PI / 180.)*0.5f;
pts[0].x = (float)(it.pos().x - a*trackLength * 2 - b*trackWidth * 4);
pts[0].y = (float)(it.pos().y + b*trackLength * 2 - a*trackWidth * 4);
pts[1].x = (float)(it.pos().x + a*trackLength * 2 - b*trackWidth * 4);
pts[1].y = (float)(it.pos().y - b*trackLength * 2 - a*trackWidth * 4);
pts[2].x = (float)(2 * it.pos().x - pts[0].x);
pts[2].y = (float)(2 * it.pos().y - pts[0].y);
pts[3].x = (float)(2 * it.pos().x - pts[1].x);
pts[3].y = (float)(2 * it.pos().y - pts[1].y);
std::vector<cv::Point> vPoints;
std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
//获取内部坐标
calcRotateRect(vRect, vPoints);
//计算灰度值
int iLimit = 0, iPartSize = 0;
double dMatch = 0;
for (int v = 0; v < vPoints.size(); v++)
{ {
if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y) dMatch += (srcPrev.data)[(vPoints[v].x) + (vPoints[v].y)*X];
{
iLimit += ucpTrackLabel[(vPoints[v].x) + (vPoints[v].y)*X];
dMatch += (srcPrev.data)[(vPoints[v].x) + (vPoints[v].y)*X];
if ((binary.data)[(vPoints[v].x) + (vPoints[v].y)*X] == 255)
iPartSize++;
}
} }
vParts.push_back(Track(iLimit, iPartSize, dMatch, it.pos(), vRect));
//cv::circle(cc, it.pos(), 0, cv::Scalar(255, 0, 0, 255), 1);
} }
if (vParts.size() == 0) continue; dMatch /= (double)vPoints.size();
//方案二每个点以当前半径画圆,看下个点偏离圆多少 //仅扫描一个元件的角度
//灰度极值认为是元件(最多问题出现在这里,加个条件判断矩形内是否存在已标记像素) vParts.push_back(Track(0, 0, dMatch, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), vRect));
std::sort(vParts.begin(), vParts.end(), std::greater<Track>()); }
//更新当前元件位置(必须不与已有元件重合) if (vParts.size() == 0) continue;
Track mac = vParts[0]; //
if (mac.iLimit != 0) trackEndPos = vParts[vParts.size() / 2];
//灰度极值认为是元件
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新位置
trackCenter = cv::Point(vParts[0].Pos.x, vParts[0].Pos.y);
//更新扫描角度
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI;
//纵向扫描
vParts.clear();
std::vector<cv::Point> trackLine;
drawLine(cc, reelCenter, trackCenter, cv::Scalar(0, 255, 255, 255), 1, trackLength, trackWidth * 2, trackLine);
//更改纵向扫描方向,分两个方向?
cv::LineIterator it(binary, trackLine[0], trackLine[1], 4);
for (int n = 0; n < it.count; n++, ++it)
{
float b = (float)cos(trackAngle*PI / 180.)*0.5f;
float a = (float)sin(trackAngle*PI / 180.)*0.5f;
pts[0].x = (float)(it.pos().x - a*trackLength * 2 - b*trackWidth * 4);
pts[0].y = (float)(it.pos().y + b*trackLength * 2 - a*trackWidth * 4);
pts[1].x = (float)(it.pos().x + a*trackLength * 2 - b*trackWidth * 4);
pts[1].y = (float)(it.pos().y - b*trackLength * 2 - a*trackWidth * 4);
pts[2].x = (float)(2 * it.pos().x - pts[0].x);
pts[2].y = (float)(2 * it.pos().y - pts[0].y);
pts[3].x = (float)(2 * it.pos().x - pts[1].x);
pts[3].y = (float)(2 * it.pos().y - pts[1].y);
std::vector<cv::Point> vPoints;
std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
//获取内部坐标
calcRotateRect(vRect, vPoints);
//计算灰度值
int iLimit = 0, iPartSize = 0;
double dMatch = 0;
for (int v = 0; v < vPoints.size(); v++)
{ {
for (int cc = 1; cc < vParts.size(); cc++) if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y)
{ {
if (vParts[cc].iLimit < mac.iLimit) iLimit += ucpTrackLabel[(vPoints[v].x) + (vPoints[v].y)*X];
mac = vParts[cc]; dMatch += (srcPrev.data)[(vPoints[v].x) + (vPoints[v].y)*X];
if (mac.iLimit == 0) if ((binary.data)[(vPoints[v].x) + (vPoints[v].y)*X] == 255)
break; iPartSize++;
} }
} }
trackCenter = mac.Pos; vParts.push_back(Track(iLimit, iPartSize, dMatch, it.pos(), vRect));
//更新扫描半径 }
trackRadius = cv::norm(trackCenter - reelCenter); if (vParts.size() == 0) continue;
//更新扫描角度 //灰度极值认为是元件(最多问题出现在这里,加个条件判断矩形内是否存在已标记像素)
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI; std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新偏移量(元件大小) //更新当前元件位置(必须不与已有元件重合)
trackOffset = (2 * asin(2 * trackLength / (2 * trackRadius))) * 180 / PI; Track mac = vParts[0];
//更新元件间角度 if (mac.iLimit != 0)
partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI; {
//判断是否结束 for (int cc = 1; cc < vParts.size(); cc++)
if ((mac.iPartSize < sinPartSize / 4) || (trackMat.at<uchar>((cvRound(trackCenter.y)), (cvRound(trackCenter.x))) == 255) || (mac.iLimit / 255) > (rect.size.area() / 4) || (binary.at<uchar>((cvRound(trackCenter.y)), (cvRound(trackCenter.x))) == 0))
{ {
found = false; if (vParts[cc].iLimit < mac.iLimit)
//for (int j = 0; j < 4; j++) mac = vParts[cc];
//{ if (mac.iLimit == 0)
// cv::line(cc, trackEndPos.Rect[j], trackEndPos.Rect[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1); break;
//}
//cv::circle(cc, trackCenter, 1, cv::Scalar(0, 255, 0, 255), 1);
} }
else }
trackCenter = mac.Pos;
//更新扫描半径
trackRadius = cv::norm(trackCenter - reelCenter);
//更新扫描角度
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI;
//更新偏移量(元件大小)
trackOffset = (2 * asin(2 * trackLength / (2 * trackRadius))) * 180 / PI;
//更新元件间角度
partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//判断是否结束
if ((mac.iPartSize < sinPartSize / 4) || (trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) || \
(mac.iLimit / 255) > (sinPartSize / 4) /*|| (binary.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 0)*/)
{
found = false;
}
else
{
//画出最终位置
std::vector<cv::Point> ptPoly;
for (int j = 0; j < 4; j++)
{ {
//画出最终位置 ptPoly.push_back(cv::Point(cvRound(mac.Rect[j].x), cvRound(mac.Rect[j].y)));
std::vector<cv::Point> ptPoly;
for (int j = 0; j < 4; j++)
{
ptPoly.push_back(cv::Point(cvRound(mac.Rect[j].x), cvRound(mac.Rect[j].y)));
//cv::line(cc, mac.Rect[j], mac.Rect[(j + 1) % 4], cv::Scalar(0, 255, 0, 255), 1);
}
cv::circle(cc, trackCenter, 2, cv::Scalar(0, 255, 0, 255), 1);
cv::circle(lb4Count, trackCenter, 0, cv::Scalar(255), 1);
//标记Label
cv::fillConvexPoly(trackMat, ptPoly, cv::Scalar(255));
//获得已处理标签
std::vector<cv::Point> vTemp;
calcRotateRect(mac.Rect, vTemp);
for (int p = 0; p < vTemp.size(); p++)
{
if (vTemp[p].x >= 0 && vTemp[p].x <= X&&vTemp[p].y >= 0 && vTemp[p].y <= Y)
{
int label = labels.at<int>(vTemp[p]);
if (label != 0)
{
labeled[label] = 255;
break;
}
}
}
} }
trackEnd = (!found); //画图显示
} while (!trackEnd); cv::circle(cc, trackCenter, 2, cv::Scalar(0, 255, 0, 255), 1);
}
//#pragma omp section //for (int j = 0; j < 4; j++)
//逆时针追踪 //{
// cv::line(cc, pts[j], pts[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1);
//}
//标记已追踪
cv::fillConvexPoly(trackMat, ptPoly, cv::Scalar(255));
//标记计数
//cv::circle(matchParts, trackCenter, 0, cv::Scalar(255), 1);
}
trackEnd = (!found);
} while (!trackEnd);
}
//#pragma omp section
//逆时针追踪
{
//追踪起点
cv::Point2f trackCenter(startCenter.x, startCenter.y);
//起始扫描角度、半径
double trackAngle = startAngle, trackRadius = startRadius;
//元件本身角度
double trackOffset = dOffset;
//元件间间距
double partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//当扫描一圈后修正中心位置(待测试)
cv::Point2f pts[4];
//结束位置
Track trackEndPos;
//开始追踪
bool trackEnd = true;
//
do
{ {
//追踪起点 bool found = true;
cv::Point2f trackCenter(startCenter.x, startCenter.y); std::vector<Track> vParts;
//起始扫描角度、半径 for (double t = trackAngle - (partDist + trackOffset / 2.0); t > trackAngle - (partDist + trackOffset / 2.0) - trackOffset; \
double trackAngle = startAngle, trackRadius = startRadius; t -= dMinorStep)
//元件本身角度
double trackOffset = dOffset;
//元件间间距
double partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//当扫描一圈后修正中心位置(待测试)
cv::Point2f pts[4];
//结束位置
Track trackEndPos;
//开始追踪
bool trackEnd = true;
//
do
{ {
bool found = true; trackCenter.x = float(reelCenter.x + trackRadius*cos(t*c));
std::vector<Track> vParts; trackCenter.y = float(reelCenter.y + trackRadius*sin(t*c));
for (double t = trackAngle - (partDist + trackOffset / 2.0); t > trackAngle - (partDist + trackOffset / 2.0) - trackOffset; t -= dMinorStep)
{
trackCenter.x = float(reelCenter.x + trackRadius*cos(t*c));
trackCenter.y = float(reelCenter.y + trackRadius*sin(t*c));
float b = (float)cos(t*c)*0.5f; float b = (float)cos(t*c)*0.5f;
float a = (float)sin(t*c)*0.5f; float a = (float)sin(t*c)*0.5f;
pts[0].x = (float)(trackCenter.x - a*trackLength * 2 - b*trackWidth * 4); pts[0].x = (float)(trackCenter.x - a*trackLength * 2 - b*trackWidth * 4);
pts[0].y = (float)(trackCenter.y + b*trackLength * 2 - a*trackWidth * 4); pts[0].y = (float)(trackCenter.y + b*trackLength * 2 - a*trackWidth * 4);
pts[1].x = (float)(trackCenter.x + a*trackLength * 2 - b*trackWidth * 4); pts[1].x = (float)(trackCenter.x + a*trackLength * 2 - b*trackWidth * 4);
pts[1].y = (float)(trackCenter.y - b*trackLength * 2 - a*trackWidth * 4); pts[1].y = (float)(trackCenter.y - b*trackLength * 2 - a*trackWidth * 4);
pts[2].x = (float)(2 * trackCenter.x - pts[0].x); pts[2].x = (float)(2 * trackCenter.x - pts[0].x);
pts[2].y = (float)(2 * trackCenter.y - pts[0].y); pts[2].y = (float)(2 * trackCenter.y - pts[0].y);
pts[3].x = (float)(2 * trackCenter.x - pts[1].x); pts[3].x = (float)(2 * trackCenter.x - pts[1].x);
pts[3].y = (float)(2 * trackCenter.y - pts[1].y); pts[3].y = (float)(2 * trackCenter.y - pts[1].y);
std::vector<cv::Point> vPoints; std::vector<cv::Point> vPoints;
std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f)); std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
//获取内部坐标 //获取内部坐标
calcRotateRect(vRect, vPoints); calcRotateRect(vRect, vPoints);
//计算灰度值 //计算灰度值
double dMatch = 0; double dMatch = 0;
for (int v = 0; v < vPoints.size(); v++) for (int v = 0; v < vPoints.size(); v++)
{
if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y)
{
dMatch += (srcPrev.data)[(vPoints[v].x) + (vPoints[v].y)*X];
}
}
dMatch /= (double)vPoints.size();
//仅扫描一个元件的角度
vParts.push_back(Track(0, 0, dMatch, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), vRect));
//cv::circle(cc, trackCenter, 0, cv::Scalar(0, 255, 255, 255), 1);
}
if (vParts.size() == 0) continue;
//
trackEndPos = vParts[vParts.size() / 2];
//灰度极值认为是元件
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新位置
trackCenter = cv::Point(vParts[0].Pos.x, vParts[0].Pos.y);
//更新扫描角度
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI;
//纵向扫描
vParts.clear();
std::vector<cv::Point> trackLine;
drawLine(cc, reelCenter, trackCenter, cv::Scalar(0, 255, 255, 255), 1, trackLength, trackWidth * 2, trackLine);
//更改纵向扫描方向,分两个方向
cv::LineIterator it(binary, trackLine[0], trackLine[1], 4);
for (int n = 0; n < it.count; n++, ++it)
{ {
float b = (float)cos(trackAngle*PI / 180.)*0.5f; if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y)
float a = (float)sin(trackAngle*PI / 180.)*0.5f;
pts[0].x = (float)(it.pos().x - a*trackLength * 2 - b*trackWidth * 4);
pts[0].y = (float)(it.pos().y + b*trackLength * 2 - a*trackWidth * 4);
pts[1].x = (float)(it.pos().x + a*trackLength * 2 - b*trackWidth * 4);
pts[1].y = (float)(it.pos().y - b*trackLength * 2 - a*trackWidth * 4);
pts[2].x = (float)(2 * it.pos().x - pts[0].x);
pts[2].y = (float)(2 * it.pos().y - pts[0].y);
pts[3].x = (float)(2 * it.pos().x - pts[1].x);
pts[3].y = (float)(2 * it.pos().y - pts[1].y);
std::vector<cv::Point> vPoints;
std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
//获取内部坐标
calcRotateRect(vRect, vPoints);
//计算灰度值
int iLimit = 0, iPartSize = 0;
double dMatch = 0;
for (int v = 0; v < vPoints.size(); v++)
{ {
if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y) dMatch += (srcPrev.data)[(vPoints[v].x) + (vPoints[v].y)*X];
{
iLimit += ucpTrackLabel[(vPoints[v].x) + (vPoints[v].y)*X];
dMatch += (srcPrev.data)[(vPoints[v].x) + (vPoints[v].y)*X];
if ((binary.data)[(vPoints[v].x) + (vPoints[v].y)*X] == 255)
iPartSize++;
}
} }
vParts.push_back(Track(iLimit, iPartSize, dMatch, it.pos(), vRect));
//cv::circle(cc, it.pos(), 0, cv::Scalar(255, 0, 0, 255), 1);
} }
if (vParts.size() == 0) continue; dMatch /= (double)vPoints.size();
//灰度极值认为是元件 //仅扫描一个元件的角度
std::sort(vParts.begin(), vParts.end(), std::greater<Track>()); vParts.push_back(Track(0, 0, dMatch, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), vRect));
//更新当前元件位置 }
Track mac = vParts[0]; if (vParts.size() == 0) continue;
if (mac.iLimit != 0) //
trackEndPos = vParts[vParts.size() / 2];
//灰度极值认为是元件
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新位置
trackCenter = cv::Point(vParts[0].Pos.x, vParts[0].Pos.y);
//更新扫描角度
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI;
//纵向扫描
vParts.clear();
std::vector<cv::Point> trackLine;
drawLine(cc, reelCenter, trackCenter, cv::Scalar(0, 255, 255, 255), 1, trackLength, trackWidth * 2, trackLine);
//更改纵向扫描方向,分两个方向
cv::LineIterator it(binary, trackLine[0], trackLine[1], 4);
for (int n = 0; n < it.count; n++, ++it)
{
float b = (float)cos(trackAngle*PI / 180.)*0.5f;
float a = (float)sin(trackAngle*PI / 180.)*0.5f;
pts[0].x = (float)(it.pos().x - a*trackLength * 2 - b*trackWidth * 4);
pts[0].y = (float)(it.pos().y + b*trackLength * 2 - a*trackWidth * 4);
pts[1].x = (float)(it.pos().x + a*trackLength * 2 - b*trackWidth * 4);
pts[1].y = (float)(it.pos().y - b*trackLength * 2 - a*trackWidth * 4);
pts[2].x = (float)(2 * it.pos().x - pts[0].x);
pts[2].y = (float)(2 * it.pos().y - pts[0].y);
pts[3].x = (float)(2 * it.pos().x - pts[1].x);
pts[3].y = (float)(2 * it.pos().y - pts[1].y);
std::vector<cv::Point> vPoints;
std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
//获取内部坐标
calcRotateRect(vRect, vPoints);
//计算灰度值
int iLimit = 0, iPartSize = 0;
double dMatch = 0;
for (int v = 0; v < vPoints.size(); v++)
{ {
for (int cc = 1; cc < vParts.size(); cc++) if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y)
{ {
if (vParts[cc].iLimit < mac.iLimit) iLimit += ucpTrackLabel[(vPoints[v].x) + (vPoints[v].y)*X];
mac = vParts[cc]; dMatch += (srcPrev.data)[(vPoints[v].x) + (vPoints[v].y)*X];
if (mac.iLimit == 0) if ((binary.data)[(vPoints[v].x) + (vPoints[v].y)*X] == 255)
break; iPartSize++;
} }
} }
trackCenter = mac.Pos; vParts.push_back(Track(iLimit, iPartSize, dMatch, it.pos(), vRect));
//更新扫描半径 }
trackRadius = cv::norm(trackCenter - reelCenter); if (vParts.size() == 0) continue;
//更新扫描角度 //灰度极值认为是元件
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI; std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新偏移量 //更新当前元件位置
trackOffset = (2 * asin(2 * trackLength / (2 * trackRadius))) * 180 / PI; Track mac = vParts[0];
//更新追踪角度 if (mac.iLimit != 0)
partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI; {
//绕完一周后更新料盘中心试试? for (int cc = 1; cc < vParts.size(); cc++)
//判断是否结束
if (mac.iPartSize < sinPartSize / 4 || (trackMat.at<uchar>((cvRound(trackCenter.y)), (cvRound(trackCenter.x))) == 255) || (mac.iLimit / 255) >(rect.size.area() / 4) || (binary.at<uchar>((cvRound(trackCenter.y)), (cvRound(trackCenter.x))) == 0))
{
found = false;
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, trackEndPos.Rect[j], trackEndPos.Rect[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
//}
//cv::circle(cc, trackCenter, 1, cv::Scalar(0, 255, 0, 255), 1);
}
else
{ {
//画出最终位置 if (vParts[cc].iLimit < mac.iLimit)
std::vector<cv::Point> ptPoly; mac = vParts[cc];
for (int j = 0; j < 4; j++) if (mac.iLimit == 0)
{ break;
ptPoly.push_back(cv::Point(cvRound(mac.Rect[j].x), cvRound(mac.Rect[j].y)));
//cv::line(cc, mac.Rect[j], mac.Rect[(j + 1) % 4], cv::Scalar(0, 255, 0, 255), 1);
}
//
cv::circle(cc, trackCenter, 2, cv::Scalar(0, 255, 0, 255), 1);
cv::circle(lb4Count, trackCenter, 0, cv::Scalar(255), 1);
//标记Label
cv::fillConvexPoly(trackMat, ptPoly, cv::Scalar(255));
//获得已处理标签
std::vector<cv::Point> vTemp;
calcRotateRect(mac.Rect, vTemp);
for (int p = 0; p < vTemp.size(); p++)
{
if (vTemp[p].x >= 0 && vTemp[p].x <= X&&vTemp[p].y >= 0 && vTemp[p].y <= Y)
{
int label = labels.at<int>(vTemp[p]);
if (label != 0)
{
labeled[label] = 255;
break;
}
}
}
} }
trackEnd = (!found); }
} while (!trackEnd); trackCenter = mac.Pos;
} //更新扫描半径
} trackRadius = cv::norm(trackCenter - reelCenter);
//去掉已标记处理的 //更新扫描角度
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range& range)->void { trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI;
for (int y = range.start; y < range.end; y++) //更新偏移量
{ trackOffset = (2 * asin(2 * trackLength / (2 * trackRadius))) * 180 / PI;
for (int x = 0; x < X; x++) //更新追踪角度
partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//绕完一周后更新料盘中心试试?
//判断是否结束
if (mac.iPartSize < sinPartSize / 4 || (trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) || \
(mac.iLimit / 255) >(sinPartSize / 4) /*|| (binary.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 0)*/)
{ {
int label = ((int *)labels.data)[(x)+(y)*labels.cols]; found = false;
CV_Assert(0 <= label && label <= nccomps); }
if (labeled[label]) else
{
//画出最终位置
std::vector<cv::Point> ptPoly;
for (int j = 0; j < 4; j++)
{ {
((int *)(labels.data))[(x)+(y)*X] = 0; ptPoly.push_back(cv::Point(cvRound(mac.Rect[j].x), cvRound(mac.Rect[j].y)));
} }
//画图显示
cv::circle(cc, trackCenter, 2, cv::Scalar(0, 255, 0, 255), 1);
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, pts[j], pts[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1);
//}
//标记Label
cv::fillConvexPoly(trackMat, ptPoly, cv::Scalar(255));
//标记计数
//cv::circle(matchParts, trackCenter, 0, cv::Scalar(255), 1);
} }
} trackEnd = (!found);
}); } while (!trackEnd);
image = labels > 0; }
//判断是否存在未追踪单个料 }
bExistSingle = (cv::countNonZero(image) == 0); //测试用
} while (!bExistSingle); //cv::circle(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), 0, cv::Scalar(0, 255, 0, 255), -1);
//拷贝计数
binary = lb4Count.clone();
//释放资源
delete[] ucpTrackLabel;
ucpTrackLabel = NULL;
} }
std::cout << "模板匹配耗时:" << clock() - begin << std::endl;
//释放资源
delete[] ucpTrackLabel;
ucpTrackLabel = NULL;
} }
//对单个器件间存在断裂使用,及料盘内圈颜色过深 //对单个器件间存在断裂使用,及料盘内圈颜色过深
else if (strcmp(ccSubType, "IP_LONG_PARTS") == 0) else if (strcmp(ccSubType, "IP_LONG_PARTS") == 0)
...@@ -5269,14 +5199,12 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons ...@@ -5269,14 +5199,12 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
} }
} }
//计数 //计数
std::vector<cv::Point> vLocations; std::vector<cv::Point> vLocations;
cv::findNonZero(binary, vLocations); cv::findNonZero(binary, vLocations);
for (int c = 0; c < vLocations.size(); c++) for (int c = 0; c < vLocations.size(); c++)
{ {
cv::circle(cc, vLocations[c], 1, cv::Scalar(0, 255, 0, 255), 1); //cv::circle(cc, vLocations[c], 1, cv::Scalar(0, 255, 0, 255), 1);
} }
std::string trayNum = std::to_string(vLocations.size()); std::string trayNum = std::to_string(vLocations.size());
//输出结果 //输出结果
...@@ -5288,7 +5216,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons ...@@ -5288,7 +5216,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//获取当前运行目录 //获取当前运行目录
char buf[128]; char buf[128];
_getcwd(buf, sizeof(buf)); _getcwd(buf, sizeof(buf));
// //创建路径
std::string filePath(buf); std::string filePath(buf);
filePath += "\\ResOut"; filePath += "\\ResOut";
if (_access(filePath.c_str(), 0) == -1) if (_access(filePath.c_str(), 0) == -1)
...@@ -5301,8 +5229,11 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons ...@@ -5301,8 +5229,11 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
return FUNC_OK; return FUNC_OK;
} }
int eyemCreateTemplateImage(EyemImage tpImage, EyemImage *tpDstImg) int eyemCreateTemplateImage(EyemImage tpImage, EyemRect tpRoi, const char *ccTplName)
{ {
cv::Mat src = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage);
cv::Mat tplMat = src(cv::Rect(tpRoi.iXs, tpRoi.iYs, tpRoi.iWidth, tpRoi.iHeight));
return FUNC_OK; return FUNC_OK;
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <io.h> #include <io.h>
#include <direct.h> #include <direct.h>
#include <fstream>
#include "eyemLib.h" #include "eyemLib.h"
constexpr double c = PI / 180.; constexpr double c = PI / 180.;
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!