我这人比较懒得罗里吧嗦,基本都是直接说两点:why?how?
基于halcon的直线查找之拟合
直线的检测在halcon中主要有两种方式:直线拟合和卡尺直线。这里分享直线拟合,直线卡尺请移步:直线卡尺
普通直线拟合
halcon有方便快捷的fit_line_contour_xld算子。用法简单粗暴:
①draw_line画一条直线;
②gen_region_line生成直线区域;
③gen_contour_region_xld直线区域转xld轮廓;
④然后你可以直接fit_line_contour_xld拟合直线,也可以先get_contour_xld对轮廓的点坐标自己做一些筛选。
但是如果需求不允许使用阻塞线程的、交互性的draw系列算子,或者无法获取一系列的点坐标呢?
这里介绍一种只用两点坐标,甚至一点坐标 + 斜率,就能拟合直线的方法:
CTRL + CV时刻
直接上代码: 直接copy拿去用吧
下面是写好的 拟合代码,这里的参数类型可以改成其他同类的类型,或者其他容器类。
// 拟合代码,外部调用,我这里是传入首尾两点,起始可以传入任意位置的点来拟合,
// 传入不是首尾点的话,计算方式要做一点修改
bool FitLine(HTuple start, HTuple end, HTuple& phi)
{
//公式AX + BY + C = 0
double a = 0;
double b = 0;
double c = 0;
a = end[0].D() - start[0].D();
b = start[1].D() - end[1].D();
c = end[1].D() * start[0].D() - start[1].D() * end[0].D();
HTuple len = HTuple();
DistancePp(start[0], start[1], end[0], end[1], &len);
AngleLx(start[0], start[1], end[0], end[1], &phi);
//x_len是x轴的直角边长度,看需求是用斜边len长,还是x_len长度,或者再求个y轴长度都行
double x_len = cos(phi[0].D() * 180 / PI) * len[0].D();
QList<double> rows, cols;
rows.append(start[0].D());
cols.append(start[1].D());
double newX = 0;
double newY = 0;
//len[0].D() / 10.0,除10是点与点的像素间隔,你可以用5、20、17任意数字都行。
//当然,别用负值,比较间隔没有负值 - -0
for(int i = 2; i < static_cast<int>(len[0].D() / 10.0) - 2; i++)
{
newX = start[1].D() + (i * 10);
newY = (-1 * a * newX - c) / b;
rows.append(newY);
cols.append(newX);
}
rows.append(end[0].D());
cols.append(end[1].D());
QPoint startPoint, endPoint;
if(FitLineByTwoPoint(rows, cols, startPoint, endPoint))
{
AngleLx(startPoint.x(), startPoint.y(), endPoint.x(), endPoint.y(), &phi);
//这里可以在形参那里多传入一个HObject引用来获取直线结果对象
//HObject line;
//GenRegionLine(&line, startPoint.x(), startPoint.y(), endPoint.x(), endPoint.y());
//DispObj(line, winID);
return true;
}
return false;
}
// 拟合代码,被FitLine使用:参数类型是QList,是Qt的,可以改成HTuple或者标准类型。
bool FitLineByTwoPoint(QList<double> rows, QList<double> cols, QPoint& startPoint, QPoint& endPoint)
{
try
{
HTuple dst_rows = HTuple();
HTuple dst_cols = HTuple();
for (int i = 0; i < rows.length(); i++)
{
dst_rows.Append(rows[i]);
dst_cols.Append(cols[i]);
}
//SortPairs(rows, cols, &dst_rows, &dst_cols);
HTuple rowBegin = HTuple(), colBegin = HTuple(), rowEnd = HTuple(), colEnd = HTuple(), nr = HTuple(), nc = HTuple(), dist = HTuple();
HXLDCont lineXLD = HXLDCont(dst_rows, dst_cols);
FitLineContourXld(lineXLD, "tukey", -1, 0, 5, 2, &rowBegin, &colBegin, &rowEnd, &colEnd, &nr, &nc, &dist); //tukey剔除算法为halcon推荐算法
startPoint = QPoint(colBegin.D(), rowBegin.D());
endPoint = QPoint(colEnd.D(), rowEnd.D());
return true;
}
catch (HException* ex)
{
}
return false;
}
注意
我懒得写