基于halcon的形状模板轮廓筛选

我这人比较懒得罗里吧嗦,基本都是直接说两点:why?how?

场景

有需求,才会去做。有时候,在一张质量不怎么好的图像上做模板,比如,有很多干扰点、背景或者其他不想要的轮廓,除了生成模板后,再慢慢去用橡皮擦来擦除它,还有一种更直接了当的方法:筛选。

CTRL + CV时刻

bool GenDesiredContours(const HXLD& srcContours, HXLD& dstContours, 
                       QPoint length, QPointF circularity, int delta = 0, int contourNum = 0);

参数1 :srcContours,输入的原始轮廓,一般先生成模板,然后Get~
参数2 :dstContours,输出筛选后的轮廓,用来重新生成模板;
参数3 :length,为筛选轮廓的最小长度值;
参数4 :circularity,为筛选轮廓的圆度值;
参数5 :delta,为依靠相邻轮廓的偏差值来判断,后续的轮廓还要不要了;
参数6 :contourNum,直接粗暴,指明就要最长的几个轮廓。

bool HalconUnity::GenDesiredContours(const HXLD& srcContours, HXLD& dstContours, 
QPoint length, QPointF circularity, int delta, int contourNum)
{
    try
    {
        HXLDtempXLDList, selectObj;
        HTuple selectXLDNum, xldLength, xldSimilarity;
        QMap<int, int> xldLengthMap;
        QList<int> xldLengthList;
        CountObj(srcContours, &selectXLDNum);
        //UnionAdjacentContoursXld(srcContours, &tempXLDList, 10, 1, "attr_keep");
        UnionCocircularContoursXld(srcContours, &tempXLDList, 1, 0, 0, 15, 5, 5, "false", 1);
        UnionCollinearContoursExtXld(tempXLDList, &tempXLDList, 10, 1, 2, 0.1, 0, -1, 1, 1, 1, 1, 1, 0, "attr_keep");

        double lengthMin, lengthMax, circularityMax;
        length.x() > 0 ? lengthMin = length.x() : lengthMin = 10;
        length.y() > 0 ? lengthMax = length.y() : lengthMax = 999999;
        circularity.y() > 0 ? circularityMax = circularity.y() : circularityMax = 1.0;
        SelectContoursXld(tempXLDList, &tempXLDList, "contour_length", lengthMin, lengthMax, 0, 0);
        CountObj(tempXLDList, &selectXLDNum);
        
        for (int i = 1; i <= selectXLDNum[0].I(); i++)
        {
            SelectObj(tempXLDList, &selectObj, i);
            CircularityXld(selectObj, &xldSimilarity);
            
            if (xldSimilarity[0].D() < circularity.x() || xldSimilarity[0].D() > circularityMax)
            {
                continue;
            }

            LengthXld(selectObj, &xldLength);
            xldLengthMap.insert(i, (int)xldLength[0].D());
            xldLengthList.append((int)xldLength[0].D());
        }

	qSort(xldLengthList);
        int judgeMaxXld = xldLengthList.length();

	if (judgeMaxXld > 2)
        {
            //参数筛选
            if (contourNum > 0.0)
            {
                if (judgeMaxXld > contourNum)
                {
                    judgeMaxXld = contourNum;
                }
            }
	    //else if (percent > 0)
            //{
            //    if ((judgeMaxXld * percent * 0.01) >= 2.0)
            //    {
            //        judgeMaxXld = (int)(judgeMaxXld * percent * 0.01);
            //    }
            //    else
            //    {
            //        judgeMaxXld -= 1;
            //    }
            //}
	
	    //差值判断
            if (delta > 0.0)
            {
                for (int j = judgeMaxXld - 2; j >= 0; j--)
                {
                    if (j > 0 && xldLengthList[j] - xldLengthList[j - 1] > delta)
                    {
                        xldLengthList = xldLengthList.mid(j);
                        judgeMaxXld = xldLengthList.length();
                        break;
                    }
                }
            }
            
            //标准差
            //{
            //    double sum = 0.0;
            //    double mean = 0.0;
            //    double variance = 0.0;
            //    double stdDeviation = 0.0;
            //    int i = 0;

	    //    for (i = 0; i < judgeMaxXld; ++i)
            //    {
            //        sum += xldLengthList[i];
            //    }

	    //    mean = sum / judgeMaxXld;
            //    for (i = 0; i < judgeMaxXld; ++i)
            //    {
            //        variance += pow(xldLengthList[i] - mean, 2);
            //    }
  	    //    stdDeviation = sqrt(variance / judgeMaxXld);

	    //    for (i = judgeMaxXld - 1; i >= 0; i--)
            //    {
            //        if (xldLengthList[i] < stdDeviation)
            //        {
            //            xldLengthList = xldLengthList.mid(i + 1);
            //            judgeMaxXld = xldLengthList.length();
            //            break;
            //        }
            //    }
            //}
         }
	    
	 int count = 0;
	
	for (int i = xldLengthList.length() - 1; i >= 0; i--)
        {
            QMap<int, int>::iterator iter = xldLengthMap.begin();
            while (iter != xldLengthMap.end())
            {
                if (iter.value() == xldLengthList[i])
                {
                    SelectObj(tempXLDList, &selectObj, iter.key());
                    if (dstContours.IsInitialized())
                    {
                        ConcatObj(dstContours, selectObj, &dstContours);
                    }
                    else
                    {
                        dstContours = selectObj;
                    }
                    count++;
                    if (count >= judgeMaxXld)
                    {
                        return true;
                    }
                    iter = xldLengthMap.erase(iter);
                    }
                else
                {
                    iter++;
                }
            }
        }
    }
    catch (HException& ex)
    {
        HandleLog::LogHalconHExcept(ex, ILogger::LogLevel::LL_INFO);
    }
    catch (...)
    {
    }
    
    return false;
}

注意

1.二次创建

筛选出来的轮廓,可以直接用CreateScaledShapeModelXld创建模板,但这个比较麻烦:如果轮廓线还是比较多、比较复杂的话,很耗时。所以我一般是再把轮廓转为区域,然后再用区域去创建模板。

2.轮廓显示

注意二次创建模板后,不要直接用新的轮廓或者区域的中心点去仿射变换,应该还是用原来第一次创建模板的区域去做变换,不然你的模板轮廓会错位显示,很尴尬。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值