Commit f42cdbad 张士柳

1 个父辈 8a5b3248
......@@ -924,11 +924,14 @@ 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", ""), "IP_LARGE_PARTS", "D://批量测试图像模板文件//" + file.Replace(".png", "") + "_tpl.png", 0.65, ref pNumObj, out tpDstImg);
eyemCountObjectIrregularPartsE(image, file.Replace(".png", ""), "IP_LARGE_PARTS", "D://批量测试图像模板文件//" + file.Replace(".png", "") + "_tpl.png", 0.7, ref pNumObj, out tpDstImg);
Bitmap bmp = eyemCvtToBitmap(tpDstImg);
bmp.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
if (bmp != null)
{
bmp.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
}
////<解码测试
//int ipNum; EyemBarCode* tpResults;
......
......@@ -55,6 +55,7 @@ static void calcRotateRect(cv::Point2f pt, float t, float length, float width, c
{
float b = (float)cos(t*PI / 180.)*0.5f;
float a = (float)sin(t*PI / 180.)*0.5f;
pts[0].x = (float)(pt.x - a*length * 2 - b*width * 4);
pts[0].y = (float)(pt.y + b*length * 2 - a*width * 4);
pts[1].x = (float)(pt.x + a*length * 2 - b*width * 4);
......@@ -3818,12 +3819,8 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//苏州公司&成都纬创
//src = src(cv::Range(10, src.cols - 10), cv::Range(10, src.rows - 10)).clone();
//图像金字塔
if (true)
{
//cv::pyrDown(src, src, );
//cv::resize(src, src, cv::Size(src.cols / 4, src.rows / 4));
}
//加载模板
cv::Mat tplMat = cv::imread(tplName, -1);
//图像尺寸
int X = src.cols, Y = src.rows;
......@@ -3994,6 +3991,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//使用大料算法(模板匹配方式)
else if (strcmp(ccSubType, "IP_LARGE_PARTS") == 0)
{
double begin0 = (double)cv::getTickCount();
//二值化
cv::threshold(srcPrev, binary, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
......@@ -4065,14 +4063,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
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(tplName, -1);
if (true) {
//cv::pyrDown(tplMat, tplMat, cv::Size(tplMat.cols / 4, tplMat.rows / 4));
//cv::resize(tplMat, tplMat, cv::Size(tplMat.cols / 4, tplMat.rows / 4));
}
//模板信息
int tplWidth, tplHeight;
tplWidth = tplMat.cols, tplHeight = tplMat.rows;
......@@ -4086,8 +4077,6 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//用于计数
cv::Mat matchParts(Y, X, CV_8UC1, cv::Scalar(0));
//double begin0 = (double)cv::getTickCount();
cv::parallel_for_(cv::Range(0, 4), [&](const cv::Range& range)->void {
for (int tpl = range.start; tpl < range.end; tpl++)
{
......@@ -4126,8 +4115,6 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
}
});
//std::cout << "剩余耗时:" << 1000 * (static_cast<double>(cv::getTickCount()) - begin0) / cv::getTickFrequency() << std::endl;
///<追踪元件算法
//标记初始区域
std::vector<cv::Point> matchPts;
......@@ -4146,63 +4133,43 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
}
#endif
//考虑留在外面,元件间距只需要计算一次(用二者结合的方式确定元件)
std::cout << "追踪前计算耗时:" << 1000 * (static_cast<double>(cv::getTickCount()) - begin0) / cv::getTickFrequency() << std::endl;
//标签图
cv::Mat trackMat(Y, X, CV_8UC1, cv::Scalar(0));
//开始追踪
for (std::vector<cv::Point>::iterator itv = matchPts.begin(); itv != matchPts.end(); ++itv)
{
//已作标记
if (trackMat.ptr<uint8_t>((*itv).y)[(*itv).x] == 255)
continue;
//追踪信息
struct Track {
int iLimit, iPartSize;
double dMatchDeg;
cv::Point Pos;
std::vector<cv::Point2f> Rect;
//追踪起点
cv::Point2f startCenter((float)(*itv).x, (float)(*itv).y);
//计算元件区域
cv::Point2f points[4];
{
double t = atan2((double)(*itv).y - reelCenter.y, (double)(*itv).x - reelCenter.x) * 180 / PI;
Track() {};
const float trackLength = (float)tplWidth / 2.0f, trackWidth = (float)tplHeight / 4.0f;
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) {};
calcRotateRect(cv::Point2f((float)(*itv).x, (float)(*itv).y), (float)t, trackLength, trackWidth, points);
bool operator >(const Track &te)const
{
return dMatchDeg > te.dMatchDeg;
}
};
//标记为已追踪过
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));
//标记计数
lbMat.ptr<uint8_t>(cvRound(startCenter.y))[cvRound(startCenter.x)] = 255;
//标记当前位置
cv::drawMarker(cc, cv::Point((*itv).x, (*itv).y), cv::Scalar(0, 165, 255, 255), cv::MARKER_DIAMOND, 5);
struct Track {
int iLimit, iPartSize;
double dMatchDeg;
cv::Point Pos;
std::vector<cv::Point2f> Rect;
Track() {};
//计算元件间距
double dChordL = .0;
for (std::vector<cv::Point>::iterator itv = matchPts.begin(); itv != matchPts.end(); ++itv)
{
///<初始化追踪参数
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) {};
//追踪起点
cv::Point2f startCenter((float)(*itv).x, (float)(*itv).y);
bool operator >(const Track &te)const
{
return dMatchDeg > te.dMatchDeg;
}
};
//扫描步长
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 startAngle = atan2((double)startCenter.y - (double)reelCenter.y, (double)startCenter.x - (double)reelCenter.x) * 180 / PI;
//起始扫描半径
const double startRadius = cv::norm(startCenter - reelCenter);
//偏移角度(元件尺寸)
......@@ -4210,8 +4177,9 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//初始搜索角度,用以确定元件间距(默认15度范围内存在元件)
const double dScanRange = 15;
//追踪元件间距(弦长,可以尽量避免因个别器件偏离导致的追踪中断)
double dChordL = .0; std::vector<Track> trackScore; bool expect = false;
std::vector<Track> trackScore; bool expect = false;
for (double t = startAngle + dOffset; t < startAngle + dOffset + dScanRange; t += dMinorStep)
{
float x = float(reelCenter.x + startRadius*cos(t*c));
......@@ -4229,9 +4197,6 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
cv::Point2i(cv::min(r.boundingRect().x + r.boundingRect().width + cvRound(trackWidth), X), \
cv::min(r.boundingRect().y + r.boundingRect().height + cvRound(trackWidth), Y)));
//测试
cv::Mat df = srcPrev(rr);
//不同方向模板图像(考虑实时更新模板图像或多角度模板,这样可能速度会下降)
cv::Mat yyu = getTplMat(tplMat, 90 - (t + 180));
......@@ -4272,17 +4237,70 @@ 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, 255, 0, 255), 0, 5);
cv::drawMarker(cc, cv::Point(ecpectPos.x, ecpectPos.y), cv::Scalar(0, 0, 255, 255), 0, 10);
}
else {
//用先前的方式
//用先前的方式重新计算间距,因为耗时操作不会在这里,加上可以减少耗时但可能不一定准
}
//无法计算元件间距
if (dChordL <= 0) {
//计算元件间距
if (dChordL > 0) {
break;
}
}
//开始两个方向追踪
for (std::vector<cv::Point>::iterator itv = matchPts.begin(); itv != matchPts.end(); ++itv)
{
//追踪起点
cv::Point2f startCenter((float)(*itv).x, (float)(*itv).y);
//已作标记
if (trackMat.ptr<uint8_t>((int)startCenter.y)[(int)startCenter.x] == 255)
continue;
//计算元件区域
cv::Point2f points[4];
{
double t = atan2((double)(*itv).y - reelCenter.y, (double)(*itv).x - reelCenter.x) * 180 / PI;
const float trackLength = (float)tplWidth / 2.0f, trackWidth = (float)tplHeight / 4.0f;
calcRotateRect(startCenter, (float)t, trackLength, trackWidth, points);
}
//增加判断,在模板匹配失效时候判断,可能匹配的不是元件
cv::RotatedRect rt(points[0], points[1], points[2]);
cv::Rect brt = rt.boundingRect()&cv::Rect(0, 0, X, Y);
if (((float)cv::countNonZero(binary(brt)) / rt.size.area()) < 0.25) {
continue;
}
//标记为已追踪过
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));
//标记计数
lbMat.ptr<uint8_t>(cvRound(startCenter.y))[cvRound(startCenter.x)] = 255;
//标记当前位置
cv::drawMarker(cc, cv::Point((*itv).x, (*itv).y), cv::Scalar(0, 165, 255, 255), cv::MARKER_DIAMOND, 5);
///<初始化追踪参数
//扫描步长
const double dMinorStep = 0.1;
//追踪长宽
const double trackLength = (double)tplWidth / 2., trackWidth = (double)tplHeight / 4.;
//起始扫描角度
const double startAngle = atan2((double)startCenter.y - (double)reelCenter.y, (double)startCenter.x - (double)reelCenter.x) * 180 / PI;
//起始扫描半径
const double startRadius = cv::norm(startCenter - reelCenter);
//偏移角度(元件尺寸)
const double dOffset = (2 * asin(2 * trackLength / (2 * startRadius))) * 180. / PI;
//并行处理
//#pragma omp parallel sections
{
......@@ -4355,8 +4373,6 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//不同方向模板图像(考虑实时更新模板图像或多角度模板,活动模板,用定位到的区域选取当前位置的模板,这样可能速度会下降)
cv::Mat yyu = getTplMat(tplMat, 90 - (trackAngle + 180));
//测试用
//cv::rectangle(cc, rr, cv::Scalar(0, 0, 255, 255));
//判断待匹配图像是否小于模板图像
if (rr.width < yyu.cols || rr.height < yyu.rows)
continue;
......@@ -4370,6 +4386,9 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
cv::minMaxLoc(tplResult0, NULL, &maxyyu, NULL, &maxyyuloc);
//旧标记点
cv::Point2f trackOldCenter = cv::Point2f(trackCenter.x, trackCenter.y);
//更新元件精确位置
trackCenter = cv::Point2f(float(maxyyuloc.x + rr.x + cvRound((float)yyu.cols / 2.0f)), \
float(maxyyuloc.y + rr.y + cvRound((float)yyu.rows / 2.0f)));
......@@ -4388,12 +4407,13 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//更新元件区域
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//需要进行越界处理
cv::RotatedRect rtt(pts[0], pts[1], pts[2]);
//判断是否结束
if ((trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) || (maxyyu < dMinScore*0.7))
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)
{
found = false;
//当分数过低采用其他方式确定是否真的终止
cv::drawMarker(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), cv::Scalar(0, 0, 255, 255), 0, 5);
}
else
{
......@@ -4419,7 +4439,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
}
//#pragma omp section
//逆时针追踪
//逆时针追踪
{
//追踪起点
cv::Point2f trackCenter(startCenter.x, startCenter.y);
......@@ -4499,6 +4519,9 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
cv::minMaxLoc(tplResult0, NULL, &maxyyu, NULL, &maxyyuloc);
//旧标记点
cv::Point2f trackOldCenter = cv::Point2f(trackCenter.x, trackCenter.y);
//更新元件精确位置
trackCenter = cv::Point2f(float(maxyyuloc.x + rr.x + cvRound((float)yyu.cols / 2.0f)), \
float(maxyyuloc.y + rr.y + cvRound((float)yyu.rows / 2.0f)));
......@@ -4517,12 +4540,14 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//更新元件区域
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//需要进行越界处理
cv::RotatedRect rtt(pts[0], pts[1], pts[2]);
//判断是否结束
if ((trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) || (maxyyu < dMinScore*0.7))
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))
{
//如果匹配点被标记,或者偏离既定路径太大不排除标记点出错可能性
found = false;
//当分数过低采用其他方式确定是否真的终止
cv::drawMarker(cc, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), cv::Scalar(0, 0, 255, 255), 0, 5);
}
else
{
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!