Commit 5361861d 张士柳

1 个父辈 37fb9c9a
......@@ -720,6 +720,9 @@ namespace eyemLib_Sharp
//异型器件(新版本)
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemCountObjectIrregularPartsE(EyemImage tpImage, string fileName, string ccSubType, string ccTplName, double dMinScore, ref string pNumObj, out EyemImage tpDstImg);
//创建模板匹配模型
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemCreateTemplateModel(EyemImage tpImage, EyemRect tpRoi, string ccTplName);
//读码程序
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, string fileName, string strCodeType, out DataCodeHandle hObject, out EyemBarCode* tpResults, out int ipNum, bool bUseNiBlack, int iBlockSize, int iRangeC, int iSymbolMin, int iSymbolMax, double dScaleUpAndDown = 0.5, double dToleErr = 0.5, double dMinorStep = 1.0);
......@@ -901,10 +904,19 @@ namespace eyemLib_Sharp
//eyemEdgesPixel(ucpImage, 15);
#endregion
////EyemRect tpRoi = new EyemRect();
////tpRoi.iXs = 1231; tpRoi.iYs = 433;
////tpRoi.iWidth = 41;
////tpRoi.iHeight = 14;
EyemRect tpRoi = new EyemRect();
tpRoi.iXs = tpRoi.iYs = 0;
tpRoi.iXs = 0; tpRoi.iYs = 0;
tpRoi.iWidth = image.iWidth;
tpRoi.iHeight = image.iHeight;
//创建模板匹配模型
//flag = eyemCreateTemplateModel(image, tpRoi, "D://批量测试图像2//template.tpl");
//
string pNumObj = "";
string file = fileName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries)[2];
......@@ -912,16 +924,25 @@ 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://批量测试图像2//template.png", 0.7, ref pNumObj, out tpDstImg);
//int ipNum; EyemBarCode* tpResults;
//DataCodeHandle hObject;
//int iRes = eyemDetectAndDecode(image, tpRoi, file.Replace(".png", ""), "QR_CODE|DATA_MATRIX|CODE_39|CODE_128", out hObject, out tpResults, out ipNum, false, 11, 5, 128, 256, 0.5);
//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) + "");
// Marshal.FreeCoTaskMem(tpResults[i].hText); Marshal.FreeCoTaskMem(tpResults[i].hType);
//}
//hObject.Dispose();
//eyemCountObjectIrregularPartsE(image, file.Replace(".png", ""), "IP_LARGE_PARTS", "D://批量测试图像2//template.png", 0.7, ref pNumObj, out tpDstImg);
//Bitmap bmp = eyemCvtToBitmap(tpDstImg);
//bmp.Save("D://ResOut//" + file);
//<解码测试
int ipNum; EyemBarCode* tpResults;
DataCodeHandle hObject;
int iRes = eyemDetectAndDecode(image, tpRoi, file.Replace(".png", ""), "QR_CODE|DATA_MATRIX|CODE_39|CODE_128", out hObject, out tpResults, out ipNum, false, 7, 5, 128, 256, 1d);
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) + "");
Marshal.FreeCoTaskMem(tpResults[i].hText); Marshal.FreeCoTaskMem(tpResults[i].hType);
}
hObject.Dispose();
sw.Stop();
Console.WriteLine("耗时:" + sw.ElapsedMilliseconds.ToString() + ",结果:" + pNumObj);
//free image
......
......@@ -649,6 +649,9 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
if (src.empty()) {
return FUNC_IMAGE_NOT_EXIST;
}
//转单通道图像
if (src.channels() != 1)
cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);
//提取ROI
src = src(cv::Rect(tpRoi.iXs, tpRoi.iYs, tpRoi.iWidth, tpRoi.iHeight));
//图像原图备份
......
......@@ -6,7 +6,6 @@
#define __EYEM_EDGE_H
#include "eyemLib.h"
#include "eyemGeneric.h"
......
......@@ -836,6 +836,7 @@ extern "C" {
EXPORTS int eyemCountObjectE(EyemImage tpImage, const char *fileName, LPSTR *lpszNumObj, EyemImage *tpDstImg);
EXPORTS int eyemCountObjectIrregularParts(EyemImage tpImage, const char *fileName, double dOffset, const char * ccSubType, int iMaxArea, int iWinSize, LPSTR *lpszNumObj, EyemImage *tpDstImg);
EXPORTS int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, const char * ccSubType, const char *ccTplName, double dMinScore, LPSTR *lpszNumObj, EyemImage *tpDstImg);
EXPORTS int eyemCreateTemplateModel(EyemImage tpImage, EyemRect tpRoi, const char *ccTplName);
EXPORTS int eyemTrackFeature(EyemImage tpPrevImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum, int *ipResults);
EXPORTS int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum);
......
......@@ -51,6 +51,20 @@ static void calcRotateRect(std::vector<cv::Point2f> &vRect, std::vector<cv::Poin
}
}
static void calcRotateRect(cv::Point2f pt, float t, float length, float width, cv::Point2f *pts)
{
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);
pts[1].y = (float)(pt.y - b*length * 2 - a*width * 4);
pts[2].x = (float)(2 * pt.x - pts[0].x);
pts[2].y = (float)(2 * pt.y - pts[0].y);
pts[3].x = (float)(2 * pt.x - pts[1].x);
pts[3].y = (float)(2 * pt.y - pts[1].y);
}
static cv::Mat getTplMat(cv::Mat &tplMat, double t)
{
const int tplH = tplMat.rows, tplW = tplMat.cols;
......@@ -3824,9 +3838,11 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//转8位灰度图
cv::Mat src8U;
src.convertTo(src8U, CV_8UC1, 1 / 255.);
//用于显示
cv::Mat cc;
cv::cvtColor(src8U, cc, cv::COLOR_GRAY2BGRA);
//设定bin数目
const int histSize = 17;
//设定取值范围
......@@ -3853,11 +3869,14 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
}
}
});
//增强到目标亮度
cc += cv::Scalar((162 - backThresh), (162 - backThresh), (162 - backThresh));
//去掉干扰
cv::Mat binary, srcPrev;
cv::bitwise_not(src8U, srcPrev);
//使用小料算法
if (strcmp(ccSubType, "IP_SMALL_PARTS") == 0)
{
......@@ -3963,7 +3982,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//释放资源
free((void *)pLabelImg);
}
//使用大料算法
//使用大料算法(模板匹配方式)
else if (strcmp(ccSubType, "IP_LARGE_PARTS") == 0)
{
//二值化
......@@ -4113,13 +4132,12 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
double sinPartSize = (double)tplWidth*(double)tplHeight;
//标签图
unsigned char *ucpTrackLabel = new unsigned char[Y*X]();
cv::Mat trackMat(Y, X, CV_8UC1, ucpTrackLabel);
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;
......@@ -4131,19 +4149,9 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
{
double t = atan2((double)(*itv).y - reelCenter.y, (double)(*itv).x - reelCenter.x) * 180 / PI;
const double trackLength = tplWidth / 2, trackWidth = tplHeight / 4;
const float trackLength = (float)tplWidth / 2.0f, trackWidth = (float)tplHeight / 4.0f;
float b = (float)cos(t*c)*0.5f;
float a = (float)sin(t*c)*0.5f;
points[0].x = float((*itv).x - a*trackLength * 2 - b*trackWidth * 4);
points[0].y = float((*itv).y + b*trackLength * 2 - a*trackWidth * 4);
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);
points[3].x = float(2 * (*itv).x - points[1].x);
points[3].y = float(2 * (*itv).y - points[1].y);
calcRotateRect(cv::Point2f((float)(*itv).x, (float)(*itv).y), (float)t, trackLength, trackWidth, points);
}
//标记为已追踪过
......@@ -4229,10 +4237,8 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
double trackOffset = dOffset;
//元件间间距
double partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//外矩形顶点
//外矩形顶点
cv::Point2f pts[4];
//结束位置
Track trackEndPos;
//开始追踪
bool trackEnd = true;
do
......@@ -4245,16 +4251,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
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 a = (float)sin(t*c)*0.5f;
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[1].x = float(trackCenter.x + a*trackLength * 2 - b*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].y = float(2 * trackCenter.y - pts[0].y);
pts[3].x = float(2 * trackCenter.x - pts[1].x);
pts[3].y = float(2 * trackCenter.y - pts[1].y);
calcRotateRect(trackCenter, (float)t, (float)trackLength, (float)trackWidth, pts);
std::vector<cv::Point> vPoints;
std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
......@@ -4273,105 +4270,47 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
//仅扫描一个元件的角度
vParts.push_back(Track(0, 0, dMatch, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), vRect));
}
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;
//测试用
//cv::rectangle(cc, vParts[0].Rect, cv::Scalar(0, 0, 255, 255));
//纵向扫描
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++)
{
if (vPoints[v].x >= 0 && vPoints[v].x <= X&&vPoints[v].y >= 0 && vPoints[v].y <= Y)
{
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));
}
//测试用
{
float b = (float)cos(trackAngle*PI / 180.)*0.5f;
float a = (float)sin(trackAngle*PI / 180.)*0.5f;
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[1].x = (float)(trackCenter.x + a*trackLength * 2 - b*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].y = (float)(2 * trackCenter.y - pts[0].y);
pts[3].x = (float)(2 * trackCenter.x - pts[1].x);
pts[3].y = (float)(2 * trackCenter.y - pts[1].y);
//
cv::RotatedRect r(pts[0], pts[1], pts[2]);
///<开始纵向扫描(横向由于存在间隔所以一般不会出现偏离的情况,除非料盘本身严重变形或者中心定位出问题)
cv::rectangle(cc, r.boundingRect(), cv::Scalar(0, 255, 0, 255));
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//
cv::Mat yyuc = srcPrev(cv::Rect(r.boundingRect().x - 27, r.boundingRect().y - 27, r.boundingRect().width + 54, r.boundingRect().height + 54));
//旋转矩形
cv::RotatedRect r(pts[0], pts[1], pts[2]);
//不同方向模板图像
cv::Mat yyu = getTplMat(tplMat, 90 - (trackAngle + 180));
//待匹配图像
cv::Rect rr(cv::Point2i(cv::max(r.boundingRect().x - cvRound(trackWidth), 0), \
cv::max(r.boundingRect().y - cvRound(trackWidth), 0)), \
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 tplResult0;
cv::matchTemplate(yyuc, yyu, tplResult0, cv::TM_CCOEFF_NORMED);
//
double minyyu, maxyyu; cv::Point minyyuloc, maxyyuloc;
cv::Mat yyuc = srcPrev(rr);
cv::minMaxLoc(tplResult0, &minyyu, &maxyyu, &minyyuloc, &maxyyuloc);
//不同方向模板图像
cv::Mat yyu = getTplMat(tplMat, 90 - (trackAngle + 180));
cv::circle(cc, cv::Point(maxyyuloc.x + r.boundingRect().x + cvRound(yyu.cols / 2) - 27, maxyyuloc.y + r.boundingRect().y + cvRound(yyu.rows / 2) - 27), 1, cv::Scalar(0, 0, 255, 255), -1);
}
//计算中心位置
cv::Mat tplResult0;
cv::matchTemplate(yyuc, yyu, tplResult0, cv::TM_CCOEFF_NORMED);
//
double maxyyu; cv::Point maxyyuloc;
cv::minMaxLoc(tplResult0, NULL, &maxyyu, NULL, &maxyyuloc);
//更新元件精确位置
trackCenter = cv::Point2f(maxyyuloc.x + rr.x + cvRound((float)yyu.cols / 2.0f), \
maxyyuloc.y + rr.y + cvRound((float)yyu.rows / 2.0f));
//cv::drawMarker(cc, trackCenter, cv::Scalar(0, 0, 255, 255));
if (vParts.size() == 0) continue;
//灰度极值认为是元件(最多问题出现在这里,加个条件判断矩形内是否存在已标记像素)
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新当前元件位置(必须不与已有元件重合)
Track mac = vParts[0];
if (mac.iLimit != 0)
{
for (int cc = 1; cc < vParts.size(); cc++)
{
if (vParts[cc].iLimit < mac.iLimit)
mac = vParts[cc];
if (mac.iLimit == 0)
break;
}
}
trackCenter = mac.Pos;
//更新扫描半径
trackRadius = cv::norm(trackCenter - reelCenter);
//更新扫描角度
......@@ -4380,30 +4319,31 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
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)*/)
//更新元件区域
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//判断是否结束(重新考虑终止条件)
if ((trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) || (maxyyu < dMinScore*0.7))
{
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)));
}
//标记当前位置
cv::drawMarker(cc, trackCenter, cv::Scalar(0, 255, 0, 255), cv::MARKER_DIAMOND, 5);
//标记为已追踪过
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));
//画出元件区域
//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::drawMarker(cc, trackCenter, cv::Scalar(0, 255, 0, 255), cv::MARKER_DIAMOND, 5);
}
trackEnd = (!found);
} while (!trackEnd);
}
......@@ -4419,10 +4359,8 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
double trackOffset = dOffset;
//元件间间距
double partDist = (2 * asin(dChordL / (2 * trackRadius))) * 180 / PI;
//当扫描一圈后修正中心位置(待测试)
//外接矩形
cv::Point2f pts[4];
//结束位置
Track trackEndPos;
//开始追踪
bool trackEnd = true;
//
......@@ -4436,16 +4374,7 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
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 a = (float)sin(t*c)*0.5f;
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[1].x = (float)(trackCenter.x + a*trackLength * 2 - b*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].y = (float)(2 * trackCenter.y - pts[0].y);
pts[3].x = (float)(2 * trackCenter.x - pts[1].x);
pts[3].y = (float)(2 * trackCenter.y - pts[1].y);
calcRotateRect(trackCenter, (float)t, (float)trackLength, (float)trackWidth, pts);
std::vector<cv::Point> vPoints;
std::vector<cv::Point2f> vRect(pts, pts + sizeof(pts) / sizeof(cv::Point2f));
......@@ -4465,140 +4394,83 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
vParts.push_back(Track(0, 0, dMatch, cv::Point(cvRound(trackCenter.x), cvRound(trackCenter.y)), vRect));
}
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;
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)
{
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));
}
//测试用
{
float b = (float)cos(trackAngle*PI / 180.)*0.5f;
float a = (float)sin(trackAngle*PI / 180.)*0.5f;
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[1].x = (float)(trackCenter.x + a*trackLength * 2 - b*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].y = (float)(2 * trackCenter.y - pts[0].y);
pts[3].x = (float)(2 * trackCenter.x - pts[1].x);
pts[3].y = (float)(2 * trackCenter.y - pts[1].y);
//
cv::RotatedRect r(pts[0], pts[1], pts[2]);
///<开始纵向扫描(横向由于存在间隔所以一般不会出现偏离的情况,除非料盘本身严重变形或者中心定位出问题)
cv::rectangle(cc, r.boundingRect(), cv::Scalar(0, 255, 0, 255));
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//
cv::Mat yyuc = srcPrev(cv::Rect(r.boundingRect().x - 27, r.boundingRect().y - 27, r.boundingRect().width + 54, r.boundingRect().height + 54));
//旋转矩形
cv::RotatedRect r(pts[0], pts[1], pts[2]);
//不同方向模板图像
cv::Mat yyu = getTplMat(tplMat, 90 - (trackAngle + 180));
//待匹配图像
cv::Rect rr(cv::Point2i(cv::max(r.boundingRect().x - cvRound(trackWidth), 0), \
cv::max(r.boundingRect().y - cvRound(trackWidth), 0)), \
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 tplResult0;
cv::matchTemplate(yyuc, yyu, tplResult0, cv::TM_CCOEFF_NORMED);
//
double minyyu, maxyyu; cv::Point minyyuloc, maxyyuloc;
cv::Mat yyuc = srcPrev(rr);
cv::minMaxLoc(tplResult0, &minyyu, &maxyyu, &minyyuloc, &maxyyuloc);
//不同方向模板图像
cv::Mat yyu = getTplMat(tplMat, 90 - (trackAngle + 180));
cv::circle(cc, cv::Point(maxyyuloc.x + r.boundingRect().x + cvRound(yyu.cols / 2) - 27, maxyyuloc.y + r.boundingRect().y + cvRound(yyu.rows / 2) - 27), 1, cv::Scalar(0, 0, 255, 255), -1);
}
//计算中心位置
cv::Mat tplResult0;
cv::matchTemplate(yyuc, yyu, tplResult0, cv::TM_CCOEFF_NORMED);
//
double maxyyu; cv::Point maxyyuloc;
cv::minMaxLoc(tplResult0, NULL, &maxyyu, NULL, &maxyyuloc);
//更新元件精确位置
trackCenter = cv::Point2f(maxyyuloc.x + rr.x + cvRound((float)yyu.cols / 2.0f), \
maxyyuloc.y + rr.y + cvRound((float)yyu.rows / 2.0f));
//cv::drawMarker(cc, trackCenter, cv::Scalar(0, 0, 255, 255));
if (vParts.size() == 0) continue;
//灰度极值认为是元件
std::sort(vParts.begin(), vParts.end(), std::greater<Track>());
//更新当前元件位置
Track mac = vParts[0];
if (mac.iLimit != 0)
{
for (int cc = 1; cc < vParts.size(); cc++)
{
if (vParts[cc].iLimit < mac.iLimit)
mac = vParts[cc];
if (mac.iLimit == 0)
break;
}
}
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;
//绕完一周后更新料盘中心试试?
//更新元件区域
calcRotateRect(trackCenter, (float)trackAngle, (float)trackLength, (float)trackWidth, pts);
//判断是否结束
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)*/)
if ((trackMat.ptr<uint8_t>(cvRound(trackCenter.y))[cvRound(trackCenter.x)] == 255) || (maxyyu < dMinScore*0.7))
{
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)));
}
//画图显示
cv::circle(cc, trackCenter, 2, cv::Scalar(0, 255, 0, 255), 1);
//标记Label
//标记为已追踪过
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));
//画出元件区域
//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);
}
trackEnd = (!found);
} while (!trackEnd);
}
}
}
//释放资源
delete[] ucpTrackLabel;
ucpTrackLabel = NULL;
}
//对单个器件间存在断裂使用,及料盘内圈颜色过深
else if (strcmp(ccSubType, "IP_LONG_PARTS") == 0)
......@@ -5291,43 +5163,72 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, const char *fileName, cons
}
}
//输出图像
//计数
std::vector<cv::Point> vLocations;
cv::findNonZero(binary, vLocations);
for (int c = 0; c < vLocations.size(); c++)
{
//cv::circle(cc, vLocations[c], 1, cv::Scalar(0, 255, 0, 255), 1);
}
std::string trayNum = std::to_string(vLocations.size());
int numObj = cv::countNonZero(binary);
std::string text = "Reel Number = :" + std::to_string(numObj);
cv::putText(cc, text, cv::Point(35, 35), 0, 1.0, cv::Scalar(0, 140, 255, 255), 2);
std::string trayNum = std::to_string(numObj);
//输出结果
*lpszNumObj = (char *)CoTaskMemAlloc(trayNum.size());
if (NULL != lpszNumObj)
{
strcpy(*lpszNumObj, trayNum.c_str());
}
//获取当前运行目录
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[256];
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;
}
int eyemCreateTemplateImage(EyemImage tpImage, EyemRect tpRoi, const char *ccTplName)
int eyemCreateTemplateModel(EyemImage tpImage, EyemRect tpRoi, const char *ccTplName)
{
cv::Mat src = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage)\
(cv::Rect(tpRoi.iXs, tpRoi.iYs, tpRoi.iWidth, tpRoi.iHeight));
cv::Mat tplMat = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage)\
(cv::Rect(tpRoi.iXs, tpRoi.iYs, tpRoi.iWidth, tpRoi.iHeight)).clone();
//模板信息
std::string hint = " " + std::to_string(tpRoi.iXs) + "," + std::to_string(tpRoi.iYs) + "," \
+ std::to_string(tpRoi.iWidth) + "," + std::to_string(tpRoi.iHeight);
//内存尺寸(将信息添加到图像后面)
int _Size = tplMat.cols*tplMat.rows*tplMat.channels() * sizeof(uint8_t);
unsigned char *_Dst = new unsigned char[_Size + (int)hint.size()];
//拷贝图像
memcpy(_Dst, tplMat.data, _Size);
//拷贝信息
memcpy(_Dst + _Size, hint.c_str(), (int)hint.size());
//写入本地
std::ofstream fileStream(ccTplName, std::ios::binary);
fileStream.write(reinterpret_cast<const char *>(_Dst), _Size + (int)hint.size());
fileStream.close();
//测试用
//释放资源
delete _Dst;
_Dst = NULL;
return FUNC_OK;
}
......
......@@ -6,6 +6,7 @@
#define __EYEM_MISC_H
#include <io.h>
#include <fstream>
#include <direct.h>
#include "eyemLib.h"
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!