Commit 2a4714d9 张士柳

1 个父辈 6e657cd2
......@@ -926,17 +926,17 @@ namespace eyemLib_Sharp
//eyemCountObjectE(image, fileName, 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);
Bitmap bmp = eyemCvtToBitmap(tpDstImg);
//if (bmp != null)
//{
// 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;
//DataCodeHandle hObject;
//int iRes = eyemDetectAndDecode(image, tpRoi, file.Replace(".png", ""), "QR_CODE|DATA_MATRIX|CODE_39|CODE_128|CODE_93", out hObject, out tpResults, out ipNum, false, 5, 5, 128, 256, 1d);
//int iRes = eyemDetectAndDecode(image, tpRoi, file.Replace(".png", ""), "QR_CODE|DATA_MATRIX", out hObject, out tpResults, out ipNum, false, 11, 5, 128, 256);
//for (int i = 0; i < ipNum; i++)
//{
// Console.WriteLine("类型:" + Marshal.PtrToStringAnsi(tpResults[i].hType) + ";坐标" + "[" + tpResults[i].iCenterX.ToString() + "," + tpResults[i].iCenterY.ToString() + "]" + ";角度:" + tpResults[i].dAngle.ToString("F4") + "," + ";内容:" + Marshal.PtrToStringAnsi(tpResults[i].hText) + "");
......
......@@ -88,7 +88,34 @@ static cv::Mat getTplMat(cv::Mat &tplMat, double t, int val)
return tplMatD;
}
static void findTrackModel(cv::Mat& image, cv::Mat &tplMat, double t, double trackWidth, cv::Point2f *pts, int val, double &maxVal, cv::Point2f &maxLoc)
static cv::Mat getTrackMat(cv::Mat &trackMat, double t, int val, float *matx)
{
const int tckH = trackMat.rows, tckW = trackMat.cols;
int tckdW = cvRound((double)tckH * abs(sin(t * CV_PI / 180.)) + (double)tckW * abs(cos(t * CV_PI / 180.)));
int tckdH = cvRound(ceil((double)tckW * abs(sin(t * CV_PI / 180.)) + (double)tckH * abs(cos(t * CV_PI / 180.))));
//创建矩阵
cv::Mat matx23f(2, 3, CV_64F);
matx23f = cv::getRotationMatrix2D(cv::Point2f((float)tckW / 2.0f - 0.5f, (float)tckH / 2.0f - 0.5f), t, 1.0);
//由于旋转产生的偏移
matx23f.ptr<double>(0)[2] += (float)(tckdW - tckW) / 2.0;
matx23f.ptr<double>(1)[2] += (float)(tckdH - tckH) / 2.0;
//输出矩阵
matx[0] = (float)matx23f.ptr<double>(0)[0]; matx[1] = (float)matx23f.ptr<double>(0)[1]; matx[2] = (float)matx23f.ptr<double>(0)[2];
matx[3] = (float)matx23f.ptr<double>(1)[0]; matx[4] = (float)matx23f.ptr<double>(1)[1]; matx[5] = (float)matx23f.ptr<double>(1)[2];
//仿射变换
cv::Mat tplMatD;
cv::warpAffine(trackMat, tplMatD, matx23f, cv::Size(tckdW, tckdH), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(val));
return tplMatD;
}
static bool findTrackModel(cv::Mat& image, cv::Mat &tplMat, double t, double trackWidth, cv::Point2f *pts, int val, bool bFinal, double &maxVal, cv::Point2f &maxLoc, cv::InputArray mask = cv::noArray())
{
//图像尺寸
int X = image.cols, Y = image.rows;
......@@ -102,25 +129,64 @@ static void findTrackModel(cv::Mat& image, cv::Mat &tplMat, double t, double tra
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 yyu = getTplMat(tplMat, t, val);
//判断待匹配图像是否小于模板图像
if (rr.width < yyu.cols || rr.height < yyu.rows)
return;
cv::Mat yuuc = image(rr&cv::Rect(0, 0, X, Y));
//计算中心位置
float matx[6];
cv::Mat tty = getTrackMat(yuuc, -t, val, matx);
//计算匹配位置
cv::Mat tplResult0;
cv::matchTemplate(yuuc, yyu, tplResult0, cv::TM_CCOEFF_NORMED);
cv::matchTemplate(tty, tplMat, tplResult0, cv::TM_CCOEFF_NORMED);
//计算极值
//计算极值坐标
cv::Point maxyyuloc;
cv::minMaxLoc(tplResult0, NULL, &maxVal, NULL, &maxyyuloc);
//计算匹配坐标
maxLoc = cv::Point2f(float(maxyyuloc.x + rr.x + cvRound((float)yyu.cols / 2.0f)), \
float(maxyyuloc.y + rr.y + cvRound((float)yyu.rows / 2.0f)));
//偏移到中心
maxyyuloc += cv::Point(tplMat.cols / 2, tplMat.rows / 2);
//测试用,限制在理论范围内
if (bFinal)
{
//重新确定位置
cv::Rect rLimit(cv::Point((tty.cols - tplMat.cols) / 2, (tty.rows - tplMat.rows) / 2), tplMat.size());
cv::Mat showMat;
cv::cvtColor(tty, showMat, cv::COLOR_GRAY2BGR);
cv::rectangle(showMat, rLimit, cv::Scalar(0, 255, 0, 255));
cv::Mat test = getTplMat(mask.getMat()(rr&cv::Rect(0, 0, X, Y)), -t, 0);
//判断区域内有效面积所占比例
if ((float)cv::countNonZero(test(rLimit)) / (float)rLimit.area() < 0.15) {
//料盘结束
return true;
}
if (!rLimit.contains(maxyyuloc))
{
//可能偏离位置,重新确定位置
do
{
maxyyuloc -= cv::Point(tplMat.cols / 2, tplMat.rows / 2);
tplResult0.ptr<float>(maxyyuloc.y)[maxyyuloc.x] = -1.0;
cv::minMaxLoc(tplResult0, NULL, &maxVal, NULL, &maxyyuloc);
maxyyuloc += cv::Point(tplMat.cols / 2, tplMat.rows / 2);
} while (!rLimit.contains(maxyyuloc));
}
}
//计算旋转前的坐标(即匹配的最终坐标)
maxLoc.x = (float)rr.x + (((float)maxyyuloc.x - matx[2])*matx[4] - ((float)maxyyuloc.y - matx[5])*matx[1]) / (matx[0] * matx[4] - matx[3] * matx[1]);
maxLoc.y = (float)rr.y + (((float)maxyyuloc.x - matx[2])*matx[3] - ((float)maxyyuloc.y - matx[5])*matx[0]) / (matx[1] * matx[3] - matx[4] * matx[0]);
return false;
}
static int Otsu(int hist[])
......@@ -4129,7 +4195,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//计算极值
double maxyyu; cv::Point2f trackCentert;
findTrackModel(srcPrev, tplMat, 90.0 - (t + 180.0), trackWidth, pts, (255 - backThresh), maxyyu, trackCentert);
findTrackModel(srcPrev, tplMat, 90.0 - (t + 180.0), trackWidth, pts, (255 - backThresh), false, maxyyu, trackCentert, cv::noArray());
//匹配阈值
if (maxyyu > dMinScore)
......@@ -4253,7 +4319,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//模板匹配
double maxyyu; cv::Point2f maxyyuloc;
findTrackModel(srcPrev, tplMat, 90.0 - (t + 180.0), trackWidth, pts, (255 - backThresh), maxyyu, maxyyuloc);
findTrackModel(srcPrev, tplMat, 90.0 - (t + 180.0), trackWidth, pts, (255 - backThresh), false, maxyyu, maxyyuloc, cv::noArray());
//最小匹配结果
if (maxyyu > 0.15)
......@@ -4289,24 +4355,19 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//模板匹配/更新元件精确位置
double maxyyu;
findTrackModel(srcPrev, tplMat, 90.0 - (trackAngle + 180.0), trackWidth, pts, (255 - backThresh), maxyyu, trackCenter);
findTrackModel(srcPrev, tplMat, 90.0 - (trackAngle + 180.0), trackWidth, pts, (255 - backThresh), false, maxyyu, trackCenter, cv::noArray());
//如果匹配得到的分数过低
if (maxyyu < 0.45) {
vParts.clear();
//旋转模板角度[-3,3]范围内寻找最佳
for (double t = -3.0; t < 3.0; t += dMinorStep*5.)
{
findTrackModel(srcPrev, tplMat, 90.0 - (trackAngle + 180.0) + t, trackWidth, pts, (255 - backThresh), 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>());
//进一步确认元件位置
bool trayEnd = false;
if (true) {
//
trackCenter = cv::Point2f(vParts[0].Pos.x, vParts[0].Pos.y);
//再确认一下
trayEnd = findTrackModel(srcPrev, tplMat, 90.0 - (trackAngle + 180.0), trackWidth, pts, (255 - backThresh), true, maxyyu, trackCenter, binary);
}
//if (cvRound(trackCenter.x) == 597 && cvRound(trackCenter.y) == 1504)
// std::cout << "" << std::endl;
//更新扫描半径
trackRadius = cv::norm(trackCenter - reelCenter);
//更新扫描角度
......@@ -4316,24 +4377,26 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//更新元件间角度
partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//计算理论元件区域
calcRotateRect(trackCenterT, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//计算实际元件区域
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
#ifdef _DEBUG
cv::Point2f ptsT[4];
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, ptsT);
//画出元件区域
for (int j = 0; j < 4; j++)
if (!trayEnd)
{
cv::line(cc, ptsT[j], ptsT[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
//画出元件区域
for (int j = 0; j < 4; j++)
{
cv::line(cc, ptsT[j], ptsT[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
}
}
#endif
//判断是否追踪终止
cv::RotatedRect rtt(pts[0], pts[1], pts[2]);
if (((float)cv::countNonZero(binary((rtt.boundingRect()&cv::Rect(0, 0, X, Y)))) / rtt.size.area()) < 0.25) {
if (trayEnd) {
//不再判断,大概率已经终止
found = false;
}
......@@ -4342,9 +4405,23 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
found = false;
}
else if (trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) {
//判断可能并未终止,采用理论位置作为下一个元件位置
//判断可能并未终止,遂采用理论位置作为下一个元件位置
trackCenter = trackCenterT;
///<更新追踪信息
//更新扫描半径
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;
//计算理论元件区域
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//标记为已追踪过
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));
......@@ -4405,7 +4482,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//模板匹配
double maxyyu; cv::Point2f maxyyuloc;
findTrackModel(srcPrev, tplMat, 90.0 - (t + 180.0), trackWidth, pts, (255 - backThresh), maxyyu, maxyyuloc);
findTrackModel(srcPrev, tplMat, 90.0 - (t + 180.0), trackWidth, pts, (255 - backThresh), false, maxyyu, maxyyuloc, cv::noArray());
//最小匹配结果
if (maxyyu > 0.15) {
......@@ -4436,27 +4513,19 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//模板匹配/更新元件精确位置
//模板匹配/更新元件精确位置+判断
double maxyyu;
findTrackModel(srcPrev, tplMat, 90.0 - (trackAngle + 180.0), trackWidth, pts, (255 - backThresh), maxyyu, trackCenter);
findTrackModel(srcPrev, tplMat, 90.0 - (trackAngle + 180.0), trackWidth, pts, (255 - backThresh), false, maxyyu, trackCenter, cv::noArray());
//如果匹配得到的分数过低
if (maxyyu < 0.45) {
vParts.clear();
//旋转模板角度[-3,3]范围内寻找最佳
for (double t = -3.0; t < 3.0; t += dMinorStep*5.)
{
findTrackModel(srcPrev, tplMat, 90.0 - (trackAngle + 180.0) + t, trackWidth, pts, (255 - backThresh), 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);
bool trayEnd = false;
if (true) {
//再确认一下
trayEnd = findTrackModel(srcPrev, tplMat, 90.0 - (trackAngle + 180.0), trackWidth, pts, (255 - backThresh), true, maxyyu, trackCenter, binary);
}
if (trackCenter.x == 1358 && trackCenter.y == 1568)
std::cout << "" << std::endl;
//if (cvRound(trackCenter.x) == 1230 && cvRound(trackCenter.y) == 497)
// std::cout << "" << std::endl;
//更新扫描半径
trackRadius = cv::norm(trackCenter - reelCenter);
......@@ -4467,24 +4536,26 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//更新元件间角度
partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//计算理论元件位置
calcRotateRect(trackCenterT, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//计算实际元件位置
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
#ifdef _DEBUG
cv::Point2f ptsT[4];
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, ptsT);
//画出元件区域
for (int j = 0; j < 4; j++)
if (!trayEnd)
{
cv::line(cc, ptsT[j], ptsT[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
//画出元件区域
for (int j = 0; j < 4; j++)
{
cv::line(cc, ptsT[j], ptsT[(j + 1) % 4], cv::Scalar(0, 0, 255, 255), 1);
}
}
#endif
//判断是否追踪终止
cv::RotatedRect rtt(pts[0], pts[1], pts[2]);
if (((float)cv::countNonZero(binary((rtt.boundingRect()&cv::Rect(0, 0, X, Y)))) / rtt.size.area()) < 0.25)
if (trayEnd)
{
//不再判断,大概率已经终止
found = false;
......@@ -4494,9 +4565,23 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
found = false;
}
else if (trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) {
//判断可能并未终止,采用理论位置作为下一个元件位置
//判断可能并未终止,遂采用理论位置作为下一个元件位置
trackCenter = trackCenterT;
///<更新追踪信息
//更新扫描半径
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;
//计算理论元件位置
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//标记为已追踪过
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));
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!