Commit 4ac30f0e 张士柳

1 个父辈 5d868695
......@@ -849,7 +849,7 @@ namespace eyemLib_Sharp
private static extern int eyemSkeleton(EyemImage tpImage);
//边缘
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemEdgesPixel(EyemImage tpImage, double dThresh);
private static extern int eyemEdgesPixel(EyemImage tpImage, double dThreshold, out IntPtr hObject, out int ipNum, out EyemOcsDXY* hResults);
//释放工具所使用句柄
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern bool eyemEdge1dGenMeasureFree(IntPtr hObject);
......@@ -878,6 +878,17 @@ namespace eyemLib_Sharp
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemFitLine(int iPtnNum, IntPtr taPoint, int numToIgnore, ref EyemOcsDABC tpLine);
/// <summary>
/// 鲁棒圆拟合
/// </summary>
/// <param name="iPtnNum">点数量</param>
/// <param name="taPoint">点</param>
/// <param name="iCalcMode">计算方式</param>
/// <param name="dRobustCoef">鲁棒系数,如果采用预设定的值则设置为0</param>
/// <param name="tpCircle">圆</param>
/// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemRobustFitCircle(int iPtnNum, IntPtr taPoint, int iCalcMode, double dRobustCoef, ref EyemOcsDXYR tpCircle);
/// <summary>
/// 圆拟合
/// </summary>
/// <param name="iPtnNum">点数量</param>
......@@ -888,8 +899,7 @@ namespace eyemLib_Sharp
/// <param name="tpCircle">圆</param>
/// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemFitCircle(int iPtnNum, IntPtr taPoint, int iCalcMode, int numToIgnore, ref double RMS, ref EyemOcsDXYR tpCircle);
private static extern int eyemFitCircle(int iPtnNum, IntPtr taPoint, int numToIgnore, ref double dRMS, ref EyemOcsDXYR tpCircle);
#endregion
#region 二维几何计算
......@@ -1270,73 +1280,386 @@ namespace eyemLib_Sharp
#endregion
#region Test Edge
//int iCount; IntPtr hHandle; EyemOcsDXY* hResults;
//eyemEdgesPixel(image, 45, out hHandle, out iCount, out hResults);
#endregion
#region Test RobustFitLine
//EyemOcsDXY taPoint = new EyemOcsDXY();
//List<EyemOcsDXY> taPoints = new List<EyemOcsDXY>();
//double k = 2.0, b = 1.0;//y=2x+1
//for (int i = 0; i < 100; i += 5)
//{
// taPoint.dX = i;
// taPoint.dY = k * taPoint.dX + b;
// taPoints.Add(taPoint);
//}
//taPoint.dX = 61;
//taPoint.dY = 41;
//taPoints.Add(taPoint);
//taPoint.dX = 62;
//taPoint.dY = 41;
//taPoints.Add(taPoint);
//taPoint.dX = 63;
//taPoint.dY = 41;
//taPoints.Add(taPoint);
//taPoint.dX = 56;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 57;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 58;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 59;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 60;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 64;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 65;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 66;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 67;
//taPoint.dY = 42;
//taPoints.Add(taPoint);
//taPoint.dX = 53;
//taPoint.dY = 43;
//taPoints.Add(taPoint);
//taPoint.dX = 54;
//taPoint.dY = 43;
//taPoints.Add(taPoint);
//taPoint.dX = 55;
//taPoint.dY = 43;
//taPoints.Add(taPoint);
//taPoint.dX = 68;
//taPoint.dY = 43;
//taPoints.Add(taPoint);
//taPoint.dX = 69;
//taPoint.dY = 43;
//taPoints.Add(taPoint);
//taPoint.dX = 70;
//taPoint.dY = 43;
//taPoints.Add(taPoint);
//taPoint.dX = 51;
//taPoint.dY = 44;
//taPoints.Add(taPoint);
//taPoint.dX = 52;
//taPoint.dY = 44;
//taPoints.Add(taPoint);
//taPoint.dX = 71;
//taPoint.dY = 44;
//taPoints.Add(taPoint);
//taPoint.dX = 72;
//taPoint.dY = 44;
//taPoints.Add(taPoint);
//taPoint.dX = 50;
//taPoint.dY = 45;
//taPoints.Add(taPoint);
//taPoint.dX = 60;
//taPoint.dY = 76;
//taPoint.dX = 73;
//taPoint.dY = 45;
//taPoints.Add(taPoint);
//taPoint.dX = 38;
//taPoint.dX = 49;
//taPoint.dY = 46;
//taPoints.Add(taPoint);
//taPoint.dX = 74;
//taPoint.dY = 46;
//taPoints.Add(taPoint);
//taPoint.dX = 48;
//taPoint.dY = 47;
//taPoints.Add(taPoint);
//taPoint.dX = 75;
//taPoint.dY = 47;
//taPoints.Add(taPoint);
//taPoint.dX = 47;
//taPoint.dY = 48;
//taPoints.Add(taPoint);
//taPoint.dX = 76;
//taPoint.dY = 48;
//taPoints.Add(taPoint);
//taPoint.dX = 46;
//taPoint.dY = 49;
//taPoints.Add(taPoint);
//taPoint.dX = 77;
//taPoint.dY = 49;
//taPoints.Add(taPoint);
//taPoint.dX = 45;
//taPoint.dY = 50;
//taPoints.Add(taPoint);
//taPoint.dX = 78;
//taPoint.dY = 50;
//taPoints.Add(taPoint);
//taPoint.dX = 44;
//taPoint.dY = 51;
//taPoints.Add(taPoint);
//taPoint.dX = 79;
//taPoint.dY = 51;
//taPoints.Add(taPoint);
//taPoint.dX = 44;
//taPoint.dY = 52;
//taPoints.Add(taPoint);
//taPoint.dX = 79;
//taPoint.dY = 52;
//taPoints.Add(taPoint);
//taPoint.dX = 43;
//taPoint.dY = 53;
//taPoints.Add(taPoint);
//taPoint.dX = 80;
//taPoint.dY = 53;
//taPoints.Add(taPoint);
//taPoint.dX = 43;
//taPoint.dY = 54;
//taPoints.Add(taPoint);
//taPoint.dX = 80;
//taPoint.dY = 54;
//taPoints.Add(taPoint);
//taPoint.dX = 43;
//taPoint.dY = 55;
//taPoints.Add(taPoint);
//taPoint.dX = 80;
//taPoint.dY = 55;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 56;
//taPoints.Add(taPoint);
//taPoint.dX = 81;
//taPoint.dY = 56;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 57;
//taPoints.Add(taPoint);
//taPoint.dX = 81;
//taPoint.dY = 57;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 58;
//taPoints.Add(taPoint);
//taPoint.dX = 81;
//taPoint.dY = 58;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 59;
//taPoints.Add(taPoint);
//taPoint.dX = 41;
//taPoint.dY = 60;
//taPoints.Add(taPoint);
//taPoint.dX = 82;
//taPoint.dY = 60;
//taPoints.Add(taPoint);
//taPoint.dX = 41;
//taPoint.dY = 61;
//taPoints.Add(taPoint);
//taPoint.dX = 82;
//taPoint.dY = 61;
//taPoints.Add(taPoint);
//taPoint.dX = 41;
//taPoint.dY = 62;
//taPoints.Add(taPoint);
//taPoint.dX = 82;
//taPoint.dY = 62;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 63;
//taPoints.Add(taPoint);
//taPoint.dX = 82;
//taPoint.dY = 63;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 64;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 65;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 66;
//taPoints.Add(taPoint);
//taPoint.dX = 81;
//taPoint.dY = 66;
//taPoints.Add(taPoint);
//taPoint.dX = 42;
//taPoint.dY = 67;
//taPoints.Add(taPoint);
//taPoint.dX = 81;
//taPoint.dY = 67;
//taPoints.Add(taPoint);
//taPoint.dX = 43;
//taPoint.dY = 68;
//taPoints.Add(taPoint);
//taPoint.dX = 81;
//taPoint.dY = 68;
//taPoints.Add(taPoint);
//taPoint.dX = 43;
//taPoint.dY = 69;
//taPoints.Add(taPoint);
//taPoint.dX = 80;
//taPoint.dY = 69;
//taPoints.Add(taPoint);
//taPoint.dX = 43;
//taPoint.dY = 70;
//taPoints.Add(taPoint);
//taPoint.dX = 80;
//taPoint.dY = 70;
//taPoints.Add(taPoint);
//taPoint.dX = 44;
//taPoint.dY = 71;
//taPoints.Add(taPoint);
//taPoint.dX = 79;
//taPoint.dY = 71;
//taPoints.Add(taPoint);
//taPoint.dX = 44;
//taPoint.dY = 72;
//taPoints.Add(taPoint);
//taPoint.dX = 79;
//taPoint.dY = 72;
//taPoints.Add(taPoint);
//taPoint.dX = 45;
//taPoint.dY = 73;
//taPoints.Add(taPoint);
//taPoint.dX = 78;
//taPoint.dY = 73;
//taPoints.Add(taPoint);
//taPoint.dX = 46;
//taPoint.dY = 74;
//taPoints.Add(taPoint);
//taPoint.dX = 77;
//taPoint.dY = 74;
//taPoints.Add(taPoint);
//taPoint.dX = 47;
//taPoint.dY = 75;
//taPoints.Add(taPoint);
//taPoint.dX = 76;
//taPoint.dY = 75;
//taPoints.Add(taPoint);
//taPoint.dX = 48;
//taPoint.dY = 76;
//taPoints.Add(taPoint);
//taPoint.dX = 75;
//taPoint.dY = 76;
//taPoints.Add(taPoint);
//taPoint.dX = 49;
//taPoint.dY = 77;
//taPoints.Add(taPoint);
//taPoint.dX = 74;
//taPoint.dY = 77;
//taPoints.Add(taPoint);
//taPoint.dX = 50;
//taPoint.dY = 78;
//taPoints.Add(taPoint);
//taPoint.dX = 73;
//taPoint.dY = 78;
//taPoints.Add(taPoint);
//taPoint.dX = 51;
//taPoint.dY = 79;
//taPoints.Add(taPoint);
//taPoint.dX = 52;
//taPoint.dY = 79;
//taPoints.Add(taPoint);
//taPoint.dX = 71;
//taPoint.dY = 37;
//taPoint.dY = 79;
//taPoints.Add(taPoint);
//taPoint.dX = 72;
//taPoint.dY = 79;
//taPoints.Add(taPoint);
//taPoint.dX = 53;
//taPoint.dY = 80;
//taPoints.Add(taPoint);
//taPoint.dX = 54;
//taPoint.dY = 80;
//taPoints.Add(taPoint);
//taPoint.dX = 69;
//taPoint.dY = 80;
//taPoints.Add(taPoint);
//taPoint.dX = 70;
//taPoint.dY = 80;
//taPoints.Add(taPoint);
//taPoint.dX = 55;
//taPoint.dY = 81;
//taPoints.Add(taPoint);
//taPoint.dX = 56;
//taPoint.dY = 81;
//taPoints.Add(taPoint);
//taPoint.dX = 57;
//taPoint.dY = 81;
//taPoints.Add(taPoint);
//taPoint.dX = 64;
//taPoint.dY = 81;
//taPoints.Add(taPoint);
//taPoint.dX = 65;
//taPoint.dY = 81;
//taPoints.Add(taPoint);
//taPoint.dX = 66;
//taPoint.dY = 81;
//taPoints.Add(taPoint);
//taPoint.dX = 67;
//taPoint.dY = 81;
//taPoints.Add(taPoint);
//taPoint.dX = 68;
//taPoint.dY = 81;
//taPoints.Add(taPoint);
//taPoint.dX = 60;
//taPoint.dY = 82;
//taPoints.Add(taPoint);
//taPoint.dX = 61;
//taPoint.dY = 82;
//taPoints.Add(taPoint);
//taPoint.dX = 62;
//taPoint.dY = 82;
//taPoints.Add(taPoint);
//taPoint.dX = 63;
//taPoint.dY = 82;
//taPoints.Add(taPoint);
//taPoint.dX = 15;
//taPoint.dY = 50;
//taPoint.dX = 41;
//taPoint.dY = 53;
//taPoints.Add(taPoint);
//taPoint.dX = 36;
//taPoint.dX = 40;
//taPoint.dY = 56;
//taPoints.Add(taPoint);
//taPoint.dX = 18;
//taPoint.dY = 8;
//taPoint.dX = 38;
//taPoint.dY = 57;
//taPoints.Add(taPoint);
//taPoint.dX = 100;
//taPoint.dY = 100;
//taPoint.dX = 39;
//taPoint.dY = 51;
//taPoints.Add(taPoint);
//taPoint.dX = 16;
//taPoint.dY = 16;
//taPoint.dX = 42;
//taPoint.dY = 49;
//taPoints.Add(taPoint);
//taPoint.dX = 18;
//taPoint.dY = 28;
////taPoint.dX = 62;
////taPoint.dY = 61;
////taPoints.Add(taPoint);
//taPoint.dX = 61;
//taPoint.dY = 19;
//taPoints.Add(taPoint);
//taPoint.dX = 56;
//taPoint.dY = 39;
//taPoints.Add(taPoint);
//taPoint.dX = 17;
//taPoint.dY = 37;
//taPoint.dX = 49;
//taPoint.dY = 20;
//taPoints.Add(taPoint);
//taPoint.dX = 28;
//taPoint.dY = 48;
//taPoint.dX = 49;
//taPoint.dY = 21;
//taPoints.Add(taPoint);
//EyemOcsDABC tpLine = new EyemOcsDABC();
//IntPtr tpPoint = eyemStructArray2IntPtr(taPoints.ToArray());
//eyemFitLine(taPoints.Count, tpPoint, 10, ref tpLine);
//eyemRobustFitLine(taPoints.Count, tpPoint, 6, 0, ref tpLine);
//eyemRobustFitLine(taPoints.Count, tpPoint, 2, 0, ref tpLine);
//EyemOcsDXYR tpCircle = new EyemOcsDXYR(); double dRMS = 0.0;
//eyemRobustFitCircle(taPoints.Count, tpPoint, 6, 0, ref tpCircle);
//eyemFitCircle(taPoints.Count, tpPoint, 15, ref dRMS, ref tpCircle);
//EyemOcsDABC tpLine2 = new EyemOcsDABC();
//EyemOcsDXY tpPoint1 = new EyemOcsDXY();
......@@ -1380,10 +1703,6 @@ namespace eyemLib_Sharp
//eyemImageWrite("D:\\Matlab测试图像\\xxx.bmp", tpDstImg);
#endregion
#region Test Edge
//eyemEdgesPixel(ucpImage, 15);
#endregion
#region Test NNDetector
//eyemInitNNDetector(".\\darknet\\detect-tiny-label.cfg", ".\\darknet\\detect-tiny-label.weights");
......@@ -1412,11 +1731,11 @@ namespace eyemLib_Sharp
// bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
//}
//创建模板匹配模型
EyemRect tpRoi2 = new EyemRect();
tpRoi2.iXs = 0; tpRoi2.iYs = 0;
tpRoi2.iWidth = image.iWidth;
tpRoi2.iHeight = image.iHeight;
////创建模板匹配模型
//EyemRect tpRoi2 = new EyemRect();
//tpRoi2.iXs = 0; tpRoi2.iYs = 0;
//tpRoi2.iWidth = image.iWidth;
//tpRoi2.iHeight = image.iHeight;
//double matchDeg = 0.75;
//flag = eyemCreateTemplateModel(image, tpRoi2, matchDeg, "D:\\模板文件\\" + file.Replace(".png", ".tpl"));
......@@ -1460,7 +1779,7 @@ namespace eyemLib_Sharp
//"IP_SMALL_PARTS","IP_LARGE_PARTS","IP_LONG_PARTS","IP_LOWCONTRAST_PARTS"
//eyemCountObject(image, tpRoi, file.Replace(".png", ""), ipReelNum, out tpDstImg);
eyemCountObjectIrregularParts(image, tpRoi, file.Replace(".png", ""), "IP_LARGE_PARTS", ipReelNum, out tpDstImg);
//eyemCountObjectIrregularParts(image, tpRoi, file.Replace(".png", ""), "IP_LARGE_PARTS", ipReelNum, out tpDstImg);
//eyemCountObjectE(image, tpRoi, fileName, ipReelNum, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), tpModels[0], hModelID, ipReelNum, out tpDstImg);
//eyemCountObjectIrregularPartsE(image, tpRoi, file.Replace(".png", ""), "D:\\模板文件\\" + /*file.Replace(".png", ".tpl")*/"74d571ed-9fd4-4959-85dd-3195261e4b48.tpl", ref pNumObj, out tpDstImg);
......@@ -1489,10 +1808,10 @@ namespace eyemLib_Sharp
//flag = eyemDetectAndDecodeBarcodeUseNN(image, tpRoi, out hObject, out tpResults, out ipNum, out tpDstImg);
string strReelNum = "";
for (int i = 0; i < 4; i++)
{
strReelNum += ipReelNum[i].ToString() + ",";
}
//for (int i = 0; i < 4; i++)
//{
// strReelNum += ipReelNum[i].ToString() + ",";
//}
sw.Stop();
Console.WriteLine(file + "--->" + "耗时:" + sw.ElapsedMilliseconds.ToString() + "ms" + ",结果:" + strReelNum);
......
#include"eyemEdge.h"
int eyemEdgesPixel(EyemImage tpImage, double dThreshold)
int eyemEdgesPixel(EyemImage tpImage, double dThreshold, IntPtr *hObject, int *ipNum, EyemOcsDXY **hResults)
{
cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
......@@ -45,24 +45,25 @@ int eyemEdgesPixel(EyemImage tpImage, double dThreshold)
}
}
});
//标记连通域,根据不同连通域显示不同颜色
cv::Mat labels;
int ilabel = cv::connectedComponents(label, labels);
//绘制连通域
std::vector<cv::Vec3b> labelColor(ilabel);
for (int i = 0; i < ilabel; i++) {
labelColor[i] = cv::Vec3b(rand() % 256, rand() % 256, rand() % 256);
}
cv::Mat labelImage;
cv::cvtColor(image, labelImage, cv::COLOR_GRAY2BGR);
for (int y = 1; y < Y - 1; y++) {
for (int x = 1; x < X - 1; x++) {
int lb = labels.at<int>(y, x);
if (lb != 0) {
labelImage.at<cv::Vec3b>(y, x) = labelColor[lb];
}
}
std::vector<EyemOcsDXY> *tpResults = new std::vector<EyemOcsDXY>();
//坐标点
std::vector<cv::Point> idx;
cv::findNonZero(label, idx);
for (auto&point : idx) {
EyemOcsDXY edgePoint;
edgePoint.dX = point.x; edgePoint.dY = point.y;
tpResults->push_back(edgePoint);
std::cout << "taPoint.dX =" << edgePoint.dX << ";" << std::endl;
std::cout << "taPoint.dY =" << edgePoint.dY << ";" << std::endl;
std::cout << "taPoints.Add(taPoint);" << std::endl;
}
//输出结果
*ipNum = static_cast<int>(tpResults->size());
*hResults = tpResults->data();
*hObject = reinterpret_cast<IntPtr>(tpResults);
//释放资源
free((void *)ucpLabel);
free((void *)dpFx);
......
......@@ -179,14 +179,10 @@ static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weigh
w += weights[i];
}
sa[2] = sa[1];
px = sa[1] / w, py = sb[0] / w;
//solve ax=b
bool solved = cv::solve(a, b, x, cv::DECOMP_SVD);
if (!solved)
return;
cv::solve(a, b, x, cv::DECOMP_SVD);
float t = (float)atan(sx[1]);
line[0] = (float)cos(t);
line[1] = (float)sin(t);
......@@ -198,14 +194,12 @@ static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weigh
int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double dRobustCoef, EyemOcsDABC &tpLine)
{
double min_err = DBL_MAX, err = 0;
void(*calc_weights_param) (float *, int, float *, float) = 0;
float linebuf[4] = { .0f };
memset(linebuf, 0, 4 * sizeof(float));
std::vector<float> weights(iPtnNum, 1.0);
switch (iCalcMode)
{
case EYEM_DIST_L1:
......@@ -244,19 +238,15 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d
default:
break;
}
for (int n = 0; n < 50; n++) {
//迭代计算
for (int n = 0; n < 100; n++) {
float sum_dist = .0, sum_w = .0;
/*calculate parameter*/
fitLine2D_wods(iPtnNum, taPoints, &weights[0], linebuf);
float px = linebuf[2], py = linebuf[3];
float nx = linebuf[1], ny = -linebuf[0];
cv::AutoBuffer<float> dist(iPtnNum);
/*calculate distance*/
for (int k = 0; k < iPtnNum; k++) {
dist[k] = fabs(nx*(float)taPoints[k].dX + ny*(float)taPoints[k].dY - (nx*px + ny*py)) / sqrt(nx*nx + ny*ny);
sum_dist += dist[k];
......@@ -264,16 +254,12 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d
err = sum_dist;
if (sum_dist < FLT_EPSILON)
break;
/*calculate weight*/
calc_weights_param(dist, iPtnNum, &weights[0], (float)dRobustCoef);
if (std::abs(err - min_err) < FLT_EPSILON)
break;
min_err = err;
}
double px = linebuf[2], py = linebuf[3];
double nx = linebuf[1], ny = -linebuf[0];
//直线一般式
......@@ -304,11 +290,10 @@ static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsDAB
int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &tpLine)
{
//初始化参数,或许可用RANSAC算法进一步提高鲁棒性,不过没必要
if (numToIgnore > iPtnNum - 2 || iPtnNum < 2) {
if (iPtnNum - numToIgnore < 2 || iPtnNum < 2) {
return FUNC_CANNOT_CALC;
}
//初始化参数,或许可用RANSAC算法进一步提高鲁棒性,不过没必要
auto taPoints = std::vector<EyemOcsDXY2D>(iPtnNum);
for (int i = 0; i < iPtnNum; i++) {
taPoints[i].bValid = true;
......@@ -318,17 +303,14 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &
}
double min_err = DBL_MAX, err = 0;
//Initialize the parameters with Robust method
fitLine2D_wods(iPtnNum, &taPoints[0], tpLine);
for (int n = 0; n < 50; n++) {
for (int n = 0; n < 100; n++) {
double sr = 0.0, r = 0.0;
/* calculate distances */
for (int i = 0; i < iPtnNum; i++) {
taPoints[i].bValid = true;
taPoints[i].dE = std::pow(calcDist2D(taPoints[i], tpLine.dA, tpLine.dB, tpLine.dC), 2);
}
//sort by dE
std::sort(taPoints.begin(), taPoints.end(), std::less<EyemOcsDXY2D>());
for (int i = (iPtnNum - numToIgnore); i < iPtnNum; i++) {
......@@ -346,7 +328,6 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &
err = std::sqrt(sr / (double)(iPtnNum - numToIgnore));
if (err < EPS)
break;
if (std::abs(err - min_err) < EPS)
break;
min_err = err;
......@@ -354,10 +335,8 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &
return FUNC_OK;
}
static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsDXYR &tpCircle) {
if (iPtnNum <= 0) {
return;
}
static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsDXYR &tpCircle)
{
std::vector<cv::Point2d> points;
for (int i = 0; i < iPtnNum; i++) {
if (taPoints[i].bValid) {
......@@ -392,12 +371,12 @@ static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsD
tpCircle.dR = sqrt(pow(x.ptr<double_t>(0)[0], 2) + pow(x.ptr<double_t>(1)[0], 2) - 4.0*(x.ptr<double_t>(2)[0])) / 2.0;
}
int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS, EyemOcsDXYR &tpCircle)
int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &dRMS, EyemOcsDXYR &tpCircle)
{
//初始化参数,或许可用RANSAC算法进一步提高鲁棒性,不过没必要
if (numToIgnore > iPtnNum - 3 || iPtnNum < 3) {
if (iPtnNum - numToIgnore < 3 || iPtnNum < 3) {
return FUNC_CANNOT_CALC;
}
//初始化参数,或许可用RANSAC算法进一步提高鲁棒性,不过没必要
std::vector<EyemOcsDXY2D> taPoints(iPtnNum);
for (int i = 0; i < iPtnNum; i++)
{
......@@ -409,7 +388,7 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS
double rms = .0;
fitCircle2D_wods(iPtnNum, &taPoints[0], tpCircle);
//迭代计算
for (int n = 0; n < 50; n++) {
for (int n = 0; n < 100; n++) {
double sr = 0.0, r = 0.0;
for (int i = 0; i < iPtnNum; i++) {
taPoints[i].bValid = true;
......@@ -424,32 +403,31 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS
fitCircle2D_wods(iPtnNum, &taPoints[0], tpCircle);
//计算RMS
for (int i = 0; i < iPtnNum; i++) {
if (taPoints[i].bValid)
{
if (taPoints[i].bValid) {
r = std::pow(calcDist(taPoints[i], tpCircle) - tpCircle.dR, 2);
sr += r;
}
}
rms = std::sqrt(sr / (double)(iPtnNum - numToIgnore));
if (rms < 0.03 || std::abs((RMS - rms)) < 1e-3) {
if (rms < 0.03 || std::abs((dRMS - rms)) < 1e-3) {
break;
}
RMS = rms;
dRMS = rms;
}
return FUNC_OK;
}
static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weights, float *circle)
static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weights, float *linebuf)
{
//计算系数
double sa[9], sb[3];
double sa[9], sb[3], sx[3];
cv::Mat a = cv::Mat(3, 3, CV_64F, sa), b = cv::Mat(3, 1, CV_64F, sb);
//系数矩阵A*X=B;
cv::Mat x = cv::Mat(3, 1, CV_64F);
cv::Mat x = cv::Mat(3, 1, CV_64F, sx);
memset(sa, 0, sizeof(sa));
memset(sb, 0, sizeof(sb));
for (int i = 0; i < iPtnNum; i++)
{
memset(sx, 0, sizeof(sx));
for (int i = 0; i < iPtnNum; i++) {
sa[0] += (double)weights[i] * taPoints[i].dX;
sa[1] += (double)weights[i] * taPoints[i].dY;
sa[2] += (double)weights[i];
......@@ -457,26 +435,94 @@ static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *wei
sa[4] += (double)weights[i] * taPoints[i].dX*taPoints[i].dY;
sa[7] += (double)weights[i] * taPoints[i].dY*taPoints[i].dY;
sb[1] += (double)weights[i] * taPoints[i].dX*(-taPoints[i].dX*taPoints[i].dX - taPoints[i].dY*taPoints[i].dY);
sb[2] += (double)weights[i] * taPoints[i].dY*(-taPoints[i].dX*taPoints[i].dX - taPoints[i].dY*taPoints[i].dY);
sb[1] += (double)weights[i] * taPoints[i].dX*(-(double)taPoints[i].dX*(double)taPoints[i].dX - (double)taPoints[i].dY*(double)taPoints[i].dY);
sb[2] += (double)weights[i] * taPoints[i].dY*(-(double)taPoints[i].dX*(double)taPoints[i].dX - (double)taPoints[i].dY*(double)taPoints[i].dY);
}
sa[5] = sa[0];
sa[6] = sa[4];
sa[8] = sa[1];
sb[0] = -(sa[3] + sa[7]);
cv::solve(a, b, x, cv::DECOMP_SVD);
//tpCircle.dX = -x.ptr<double_t>(0)[0] / 2.0;
//tpCircle.dY = -x.ptr<double_t>(1)[0] / 2.0;
//tpCircle.dR = sqrt(pow(x.ptr<double_t>(0)[0], 2) + pow(x.ptr<double_t>(1)[0], 2) - 4.0*(x.ptr<double_t>(2)[0])) / 2.0;
linebuf[0] = -0.5f*(float)sx[0];
linebuf[1] = -0.5f*(float)sx[1];
linebuf[2] = 0.5f*sqrtf(powf((float)sx[0], 2) + powf((float)sx[1], 2) - 4.0f*(float)sx[2]);
}
int eyemRobustFitCircle(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double dRobustCoef, EyemOcsDXYR &tpCircle)
{
double min_err = DBL_MAX, err = 0;
void(*calc_weights_param) (float *, int, float *, float) = 0;
float linebuf[3] = { .0f };
memset(linebuf, 0, 3 * sizeof(float));
std::vector<float> weights(iPtnNum, 1.0);
switch (iCalcMode)
{
case EYEM_DIST_L1:
calc_weights_param = weightL1;
break;
case EYEM_DIST_L12:
calc_weights_param = weightL12;
break;
case EYEM_DIST_FAIR:
calc_weights_param = weightFair;
break;
case EYEM_DIST_WELSCH:
calc_weights_param = weightWelsch;
break;
case EYEM_DIST_HUBER:
calc_weights_param = weightHuber;
break;
case EYEM_DIST_TUKEY:
calc_weights_param = weightTukey;
break;
case EYEM_DIST_CAUCHY:
calc_weights_param = weightCauchy;
break;
case EYEM_DIST_LOGISTIC:
calc_weights_param = weightLogistic;
break;
case EYEM_DIST_ANDREWS:
calc_weights_param = weightAndrews;
break;
case EYEM_DIST_ATLWORTH:
calc_weights_param = weightTalworth;
break;
case EYEM_DIST_USER:
calc_weights_param = weightUser;
break;
default:
break;
}
//迭代计算
for (int n = 0; n < 100; n++)
{
float sum_dist = .0, sum_w = .0;
fitCircle2D_wods(iPtnNum, taPoints, &weights[0], linebuf);
float x = linebuf[0], y = linebuf[1], r = linebuf[2];
cv::AutoBuffer<float> dist(iPtnNum);
for (int k = 0; k < iPtnNum; k++) {
dist[k] = fabs(std::sqrt(std::pow((float)taPoints[k].dX - x, 2) + std::pow((float)taPoints[k].dY - y, 2)) - r);
sum_dist += dist[k];
}
err = sum_dist;
if (sum_dist < FLT_EPSILON)
break;
/*calculate weight*/
calc_weights_param(dist, iPtnNum, &weights[0], (float)dRobustCoef);
if (std::abs(err - min_err) < FLT_EPSILON)
break;
min_err = err;
}
tpCircle.dX = linebuf[0]; tpCircle.dY = linebuf[1];
tpCircle.dR = linebuf[2];
return FUNC_OK;
}
int eyemRobustFitPlane(int iPtnNum, EyemOcsDXYZ *taPoint, int iCalcMode, double dRobustCoef, EyemOcsDABCD &tpPlane)
{
......@@ -501,3 +547,5 @@ int eyemFitCircleRANSAC(int iPtnNum, EyemOcsDXY *taPoint, EyemOcsDXYR &tpCircle)
return FUNC_OK;
}
......@@ -3,7 +3,6 @@
int eyemImageRead(const char *fileName, int iFlag, EyemImage *tpImage)
{
cv::Mat _src = cv::imread(fileName, iFlag);
if (_src.empty())
return FUNC_IMAGE_NOT_EXIST;
......@@ -13,13 +12,10 @@ int eyemImageRead(const char *fileName, int iFlag, EyemImage *tpImage)
free(tpImage->vpImage);
tpImage->vpImage = NULL;
}
//图像信息
tpImage->iWidth = _src.cols; tpImage->iHeight = _src.rows; tpImage->iDepth = _src.depth(); tpImage->iChannels = _src.channels();
//内存尺寸
int _Size = tpImage->iWidth*tpImage->iHeight*tpImage->iChannels;
//申请内存
switch (tpImage->iDepth)
{
......@@ -78,7 +74,6 @@ int eyemImageRead(const char *fileName, int iFlag, EyemImage *tpImage)
}
//拷贝数据
memcpy(tpImage->vpImage, _src.data, _Size);
return FUNC_OK;
}
......
......@@ -430,8 +430,9 @@ extern "C" {
// 函数接口
EXPORTS int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &tpLine);
EXPORTS int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, double dRobustCoef, EyemOcsDABC &tpLine);
EXPORTS int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &dRMS, EyemOcsDXYR &tpCircle);
EXPORTS int eyemRobustFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, double dRobustCoef, EyemOcsDXYR &tpCircle);
EXPORTS int eyemFitPlane(int, EyemOcsDXYZ[], int, double, EyemOcsDABCD &);
EXPORTS int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS, EyemOcsDXYR &tpCircle);
EXPORTS int eyemFitEllipse(int, EyemOcsDXY[], int, double, EyemOcsDXYLSQ *);
EXPORTS int eyemFitEllipseC(int, EyemOcsDXY[], int, double, double[]);
EXPORTS int eyemFitConics(int, EyemOcsDXY[], int, double, double[]);
......@@ -658,7 +659,7 @@ extern "C" {
#endif
// 函数接口
EXPORTS int eyemEdgesPixel(EyemImage tpImage, double dThreshold);
EXPORTS int eyemEdgesPixel(EyemImage tpImage, double dThreshold, IntPtr *hObject, int *ipNum, EyemOcsDXY **hResults);
EXPORTS int eyemEdgesSubpixel(EyemImage tpImage, IntPtr *hObject, EyemOcsDXY **tpEdges, int iFilter, int iLow, int iHigh);
EXPORTS int eyemSkeleton(EyemImage tpImage, EyemImage &skeleton);
EXPORTS int eyemSobelAmp(EyemImage tpImage, EyemImage &ImaAmp);
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!