Commit 50f8f9d5 张士柳

1 个父辈 42d41a23
......@@ -924,7 +924,7 @@ namespace eyemLib_Sharp
//eyemCountObject(image, file.Replace(".png", ""), 35, 0, 100, 5, ref pNumObj, out tpDstImg);
//eyemCountObjectIrregularParts(image, file.Replace(".png", ""), 0.1, "IP_LARGE_PARTS", 100, 7, ref pNumObj, out tpDstImg);
//eyemCountObjectE(image, fileName, ref pNumObj, out tpDstImg);
eyemCountObjectIrregularPartsE(image, file.Replace(".png", ""), "D://批量测试图像模板文件//" + file.Replace(".png", "") + "_tpl.png", 0.7, ref pNumObj, out tpDstImg);
eyemCountObjectIrregularPartsE(image, file.Replace(".png", ""), "D://批量测试图像模板文件//" + file.Replace(".png", "") + "_tpl.png", 0.75, ref pNumObj, out tpDstImg);
Bitmap bmp = eyemCvtToBitmap(tpDstImg);
......
此文件类型无法预览
......@@ -108,9 +108,11 @@ static void findTrackModel(cv::Mat& image, cv::Mat &tplMat, double t, double tra
if (rr.width < yyu.cols || rr.height < yyu.rows)
return;
cv::Mat yuuc = image(rr&cv::Rect(0, 0, X, Y));
//计算中心位置
cv::Mat tplResult0;
cv::matchTemplate(image(rr&cv::Rect(0, 0, X, Y)), yyu, tplResult0, cv::TM_CCOEFF_NORMED);
cv::matchTemplate(yuuc, yyu, tplResult0, cv::TM_CCOEFF_NORMED);
//计算极值
cv::Point maxyyuloc;
......@@ -372,9 +374,9 @@ int eyemCountObject(EyemImage tpImage, const char *fileName, double dOffset, int
cv::Mat src8U;
//环鸿&佳世达
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();
//image size
int X = src.cols, Y = src.rows;
......@@ -1341,9 +1343,9 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, const char *fileName, doubl
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;
......@@ -2877,10 +2879,11 @@ int eyemCountObjectE(EyemImage tpImage, const char *fileName, LPSTR *lpszNumObj,
cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);
cv::Mat src8U;
//环鸿&佳世达
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();
//image size
int X = src.cols, Y = src.rows;
......@@ -2916,7 +2919,7 @@ int eyemCountObjectE(EyemImage tpImage, const char *fileName, LPSTR *lpszNumObj,
cv::minMaxIdx(hist, NULL, NULL, NULL, maxIdx);
//background thresh
int backThresh = 15 * (maxIdx[0] - 2);//正常-2
//remove the background
//remove the background
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range range)->void {
for (int y = range.start; y < range.end; y++)
{
......@@ -3821,18 +3824,24 @@ int eyemCountObjectE(EyemImage tpImage, const char *fileName, LPSTR *lpszNumObj,
{
strcpy(*lpszNumObj, cTrayNum);
}
//获取当前运行目录
char buf[128];
_getcwd(buf, sizeof(buf));
//创建文件夹
std::string filePath(buf);
filePath += "\\ResOut";
if (_access(filePath.c_str(), 0) == -1)
_mkdir(filePath.c_str());//不存在则创建
//格式化文件名
char file[64 * 4] = { 0 };
sprintf_s(file, "%s\\%s-Mark.png", filePath.c_str(), fileName);
cv::imwrite(file, cc);
///<输出计数结果标记图像
{
tpDstImg->iWidth = cc.cols; tpDstImg->iHeight = cc.rows; tpDstImg->iDepth = cc.depth(); tpDstImg->iChannels = cc.channels();
//内存尺寸
int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t);
//分配内存
tpDstImg->vpImage = (uint8_t *)malloc(_Size);
if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据
memcpy(tpDstImg->vpImage, cc.data, _Size);
}
return FUNC_OK;
}
......@@ -3918,6 +3927,9 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
cv::Mat binary, srcPrev;
cv::bitwise_not(src8U, srcPrev);
//创建模板图像
//计数图像
cv::Mat lbMat(Y, X, CV_8UC1, cv::Scalar(0));
......@@ -4057,7 +4069,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
*/
for (std::vector<cv::Point>::iterator itv = matchPts.begin(); itv != matchPts.end(); ++itv)
{
cv::drawMarker(cc, cv::Point((*itv).x, (*itv).y), cv::Scalar(0, 255, 0, 255));
//cv::drawMarker(cc, cv::Point((*itv).x, (*itv).y), cv::Scalar(0, 255, 0, 255));
}
#endif
......@@ -4089,7 +4101,6 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
///<初始化追踪参数
//追踪起点
cv::Point2f startCenter((float)(*itv).x, (float)(*itv).y);
//扫描步长
const double dMinorStep = 0.1;
//追踪长宽
......@@ -4140,7 +4151,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
dChordL = 2.0 * startRadius*sin(((2.0 * asin((cv::norm(startCenter - cv::Point2f((float)ecpectPos.x, \
(float)ecpectPos.y))) / (2.0 * startRadius))) * 180.0 / PI - dOffset)*PI / 180.0 / 2.0);
cv::drawMarker(cc, cv::Point(ecpectPos.x, ecpectPos.y), cv::Scalar(0, 0, 255, 255), 0, 10);
//cv::drawMarker(cc, cv::Point(ecpectPos.x, ecpectPos.y), cv::Scalar(0, 0, 255, 255), 0, 10);
}
else {
//用先前的方式重新计算间距,因为耗时操作不会在这里,加上可以减少耗时但可能不一定准
......@@ -4228,6 +4239,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
bool found = true;
std::vector<Track> vParts;
for (double t = trackAngle + (trackOffset / 2.0 + partDist + trackOffset / 3.0); t < trackAngle + \
(trackOffset / 2.0 + partDist + trackOffset / 3.0) + trackOffset / 3.0; t += dMinorStep)
{
......@@ -4241,20 +4253,23 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
double maxyyu; cv::Point2f maxyyuloc;
findTrackModel(srcPrev, tplMat, 90 - (t + 180), trackWidth, pts, maxyyu, maxyyuloc);
//存放结果
vParts.push_back(Track(0, 0, maxyyu, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), std::vector<cv::Point2f>()));
//测试标记
//cv::drawMarker(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), cv::Scalar(0, 0, 255, 255), cv::MARKER_CROSS, 5);
//最小匹配结果
if (maxyyu > 0.15)
{
//存放结果
vParts.push_back(Track(0, 0, maxyyu, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), std::vector<cv::Point2f>()));
}
}
//如果为0大概率是背景
if (vParts.size() <= 0)
break;
//极值处认为是元件
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新切线方向位置,由于这个方向是元件间隙不会有太大偏差
trackCenter = cv::Point2f((float)vParts[vParts.size() / 2].Pos.x, (float)vParts[vParts.size() / 2].Pos.y);
//更新切线方向位置
trackCenter = cv::Point2f((float)vParts[0].Pos.x, (float)vParts[0].Pos.y);
//理论元件位置
cv::Point2f trackCenterT(trackCenter.x, trackCenter.y);
//更新扫描角度
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI;
......@@ -4267,6 +4282,22 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
double maxyyu;
findTrackModel(srcPrev, tplMat, 90 - (trackAngle + 180), trackWidth, pts, maxyyu, trackCenter);
//如果匹配得到的分数过低
if (maxyyu < 0.45) {
vParts.clear();
//旋转模板角度[-2,2]范围内寻找最佳
for (double t = -3.0; t < 3.0; t += dMinorStep*5.)
{
findTrackModel(srcPrev, tplMat, 90 - (trackAngle + 180) + t, trackWidth, pts, maxyyu, trackCenter);
//存放结果
vParts.push_back(Track(0, 0, maxyyu, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), std::vector<cv::Point2f>()));
}
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//
trackCenter = cv::Point2f(vParts[0].Pos.x, vParts[0].Pos.y);
}
//更新扫描半径
trackRadius = cv::norm(trackCenter - reelCenter);
//更新扫描角度
......@@ -4276,18 +4307,39 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//更新元件间角度
partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//更新元件区域
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//计算理论元件区域
calcRotateRect(trackCenterT, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//画出元件区域
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, pts[j], pts[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
//}
//需要进行越界处理
//判断是否追踪终止
cv::RotatedRect rtt(pts[0], pts[1], pts[2]);
//判断是否结束
if (((trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255)) || \
((float)cv::countNonZero(binary((rtt.boundingRect()&cv::Rect(0, 0, X, Y)))) / rtt.size.area()) < 0.25)
{
if (((float)cv::countNonZero(binary((rtt.boundingRect()&cv::Rect(0, 0, X, Y)))) / rtt.size.area()) < 0.25) {
//不再判断,大概率已经终止
found = false;
//cv::drawMarker(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), cv::Scalar(0, 0, 255, 255), cv::MARKER_DIAMOND, 5);
}
else if (trackMat.ptr<uint8_t>(cvRound(trackCenterT.y))[cvRound(trackCenterT.x)] == 255) {
//不再判断,大概率已经终止
found = false;
}
else if (trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) {
//判断并未终止,重新确定精确元件位置
trackCenter = trackCenterT;
//标记为已追踪过
std::vector<cv::Point> ptPoly = { cv::Point(pts[0]),cv::Point(pts[1]) ,cv::Point(pts[2]) ,cv::Point(pts[3]) };
cv::fillConvexPoly(trackMat, ptPoly, cv::Scalar(255));
//标记计数
lbMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] = 255;
//标记当前位置
cv::drawMarker(cc, trackCenter, cv::Scalar(0, 255, 0, 255), cv::MARKER_DIAMOND, 5);
}
else
{
......@@ -4328,8 +4380,8 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
{
bool found = true;
std::vector<Track> vParts;
for (double t = trackAngle - (partDist + trackOffset / 2.0); t > trackAngle - (partDist + trackOffset / 2.0) - trackOffset; \
t -= dMinorStep)
for (double t = trackAngle - (trackOffset / 3.0 + partDist + trackOffset / 2.0); t > trackAngle - \
(trackOffset / 3.0 + partDist + trackOffset / 2.0) - trackOffset / 3.0; t -= dMinorStep)
{
trackCenter.x = float(reelCenter.x + trackRadius*cos(t*c));
trackCenter.y = float(reelCenter.y + trackRadius*sin(t*c));
......@@ -4341,21 +4393,28 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
double maxyyu; cv::Point2f maxyyuloc;
findTrackModel(srcPrev, tplMat, 90 - (t + 180), trackWidth, pts, maxyyu, maxyyuloc);
//存放结果
vParts.push_back(Track(0, 0, maxyyu, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), std::vector<cv::Point2f>()));
//最小匹配结果
if (maxyyu > 0.15) {
//存放结果
vParts.push_back(Track(0, 0, maxyyu, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), std::vector<cv::Point2f>()));
}
//测试标记
//cv::drawMarker(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), cv::Scalar(0, 165, 255, 255), 0, 5);
}
if (vParts.size() == 0) break;
if (vParts.size() == 0)
break;
//极值认为是元件
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新切线方向位置,由于这个方向是元件间隙不会有太大偏差
trackCenter = cv::Point2f((float)vParts[vParts.size() / 2].Pos.x, (float)vParts[vParts.size() / 2].Pos.y);
//更新位置
trackCenter = cv::Point2f((float)vParts[0].Pos.x, (float)vParts[0].Pos.y);
//理论元件区域
cv::Point2f trackCenterT(trackCenter.x, trackCenter.y);
//更新扫描角度
trackAngle = atan2((double)trackCenter.y - reelCenter.y, (double)trackCenter.x - reelCenter.x) * 180 / PI;
///<开始纵向扫描(横向由于存在间隔所以一般不会出现偏离的情况,除非料盘本身严重变形或者中心定位出问题)
///<开始离心/向心扫描(横向由于存在间隔所以一般不会出现偏离的情况,除非料盘本身严重变形或者中心定位出问题)
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
......@@ -4363,6 +4422,23 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
double maxyyu;
findTrackModel(srcPrev, tplMat, 90 - (trackAngle + 180), trackWidth, pts, maxyyu, trackCenter);
//如果匹配得到的分数过低
if (maxyyu < 0.45) {
vParts.clear();
//旋转模板角度[-2,2]范围内寻找最佳
for (double t = -3.0; t < 3.0; t += dMinorStep*5.)
{
findTrackModel(srcPrev, tplMat, 90 - (trackAngle + 180) + t, trackWidth, pts, maxyyu, trackCenter);
//存放结果
vParts.push_back(Track(0, 0, maxyyu, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), std::vector<cv::Point2f>()));
}
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新最接近的
trackCenter = cv::Point2f(vParts[0].Pos.x, vParts[0].Pos.y);
}
//更新扫描半径
trackRadius = cv::norm(trackCenter - reelCenter);
//更新扫描角度
......@@ -4372,18 +4448,40 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//更新元件间角度
partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//更新元件区域
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//计算理论元件位置
calcRotateRect(trackCenterT, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//画出元件区域
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, pts[j], pts[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
//}
//需要进行越界处理
//判断是否追踪终止
cv::RotatedRect rtt(pts[0], pts[1], pts[2]);
//判断是否结束
if (((trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255)) || \
(((float)cv::countNonZero(binary((rtt.boundingRect()&cv::Rect(0, 0, X, Y)))) / rtt.size.area()) < 0.25))
if (((float)cv::countNonZero(binary((rtt.boundingRect()&cv::Rect(0, 0, X, Y)))) / rtt.size.area()) < 0.25)
{
//如果匹配点被标记,或者偏离既定路径太大不排除标记点出错可能性
//不再判断,大概率已经终止
found = false;
//cv::drawMarker(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), cv::Scalar(0, 0, 255, 255), cv::MARKER_DIAMOND, 5);
}
else if (trackMat.ptr<uint8_t>(cvRound(trackCenterT.y))[cvRound(trackCenterT.x)] == 255) {
//不再判断,大概率已经终止
found = false;
}
else if (trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) {
//判断并未终止,重新确定精确元件位置
trackCenter = trackCenterT;
//标记为已追踪过
std::vector<cv::Point> ptPoly = { cv::Point(pts[0]),cv::Point(pts[1]) ,cv::Point(pts[2]) ,cv::Point(pts[3]) };
cv::fillConvexPoly(trackMat, ptPoly, cv::Scalar(255));
//标记计数
lbMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] = 255;
//标记当前位置
cv::drawMarker(cc, trackCenter, cv::Scalar(0, 255, 0, 255), cv::MARKER_DIAMOND, 5);
}
else
{
......@@ -4394,12 +4492,6 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//标记计数
lbMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] = 255;
//画出元件区域
//for (int j = 0; j < 4; j++)
//{
// cv::line(cc, pts[j], pts[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1);
//}
//标记当前位置
cv::drawMarker(cc, trackCenter, cv::Scalar(0, 255, 0, 255), cv::MARKER_DIAMOND, 5);
}
......@@ -4410,7 +4502,6 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
}
}
//计数
int numObj = cv::countNonZero(lbMat);
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!