Commit 4ac30f0e 张士柳

1 个父辈 5d868695
#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!