[视觉实战案例]Qt+Halcon实现区域生长算法(坐标种子点+灰度值种子点)

1 算法介绍

区域生长算法:将按照事先定义的生长准则讲一个像素或子区域逐步聚合成一个完整独立的区域的过程。对于图像上某个区域R,p为区域R上指定的一个像素点,称作种子点,按照规定的生长准则逐步将与种子点z一定邻域内符合相似性判据的像素合并成一个种子群以备下一阶段的生长,这样不断的进行循环生长直到满足生长停止条件为止,从而完成了对感兴趣区域由一个种子点生长为一个独立连通区域的过程。

实现步骤

1、在图像区域中选取一个像素点作为一个种子点(x,y)。
2、根据生长规则,判断种子点周围八邻域的哪几个像素点可以作为下次生长的点,判断完后将该点存入生长点Vector,并将当前已用的种子点标记为已使用。
3、按照规则判断下一个生长点。
4、判断生长点vector容器中是否还有生长点,容器为空时结束。

Halcon中区域生长算子

regiongrowing(Image:Regions : Row, Column, Tolerance, MinSize 😃
Row:被测试的区域的垂直距离
Column:被测试的区域的水平距离
Tolerance:能忍受的最大的灰度差距
MinSize:最小的输出区域
regiongrowing (Image111, Regions, 2, 2, 4, 100)

Halcon区域生长.JPG

2 起点坐标种子点实现区域生长

在区域生长的算法中,我们需要输入一个已知的坐标点(x,y),以这个点作为起点,这里我们不使用Halcon自带的区域生长算子,而是通过算法的步骤去实现这一功能。
首先获取点击点的像素点灰度值,以这一点为起始点,向八领域按照灰度差值去计算生长点。

坐标点作为种子点.JPG

    HTuple Row,Col,Button;
    GetMbutton(m_hHalconID,&Row,&Col,&Button);
    if(Button == 1)
    {
        HObject ResultRegion;
//        HTuple posGray,GrayRows,GrayCols;
        GetGrayval(CurTestImg,Row, Col,&SelectGray);
        qDebug()<<"Gray"<<SelectGray.I();
        int curGray = SelectGray.I();
        ui->spb_gray->setValue(curGray);
        int index = ui->spb_growIndex->value();
        int posY = Row.I();
        int posX = Col.I();
        QPoint pos(posX,posY);
        RegionGrowing(CurTestImg,ResultRegion,pos,index);
        FillUp(ResultRegion,&ResultRegion);
        UpdateImgWindow();
        ui->PicShow->Region_ShowBuf.clear();
        region_Info h_RegionInfo;
        h_RegionInfo.region = ResultRegion;
        h_RegionInfo.color = "#ff0000c0";
        h_RegionInfo.size = 1;
        ui->PicShow->Region_ShowBuf.push_back(h_RegionInfo);
        ui->PicShow->updateShowInfoOnWindow();
    }

//区域生长算法
void RegionGrowDlg::RegionGrowing(HObject img, HObject &region, QPoint pt,int th)
{
    QPoint ptGrowing;						//待生长点位置
    HTuple nGrowLable = 0;								//标记是否生长过
    int nSrcValue = 0;								//生长起点灰度值
    int nCurValue = 0;								//当前生长点灰度值
//	matDst = cv::Mat::zeros(src.size(), CV_8UC1);	//创建一个空白区域,填充为黑色
    //生长方向顺序数据
    int DIR[8][2] = { { -1, -1 }, { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, 1 }, { -1, 1 }, { -1, 0 } };
    std::vector<QPoint> vcGrowPt;						//生长点栈
    vcGrowPt.push_back(pt);							//将生长点压入栈中
    //首先设置区域为空
    GenEmptyRegion(&region);
//	matDst.at<uchar>(pt.y, pt.x) = 255;				//标记生长点
    HTuple posGray;
    GetGrayval(img,pt.y(), pt.x(),&posGray);
    nSrcValue = posGray.I(); 			//记录生长点的灰度值
    qDebug()<<"选择点灰度"<<nSrcValue;
    while (!vcGrowPt.empty())						//生长栈不为空则生长
    {
        pt = vcGrowPt.back();						//取出一个生长点
        vcGrowPt.pop_back();

        //分别对八个方向上的点进行生长
        for (int i = 0; i < 8; ++i)
        {
            int ppx = (pt.x() + DIR[i][0]);
            int ppy = (pt.y() + DIR[i][1]);
            ptGrowing = QPoint(ppx,ppy);
            //检查是否是边缘点
            if (ptGrowing.x() < 0 || ptGrowing.y() < 0 || ptGrowing.x() >(hv_Width - 1) || ptGrowing.y() > (hv_Height - 1))
                continue;
            //判断该点是否在region内
//            int nGrowLable;
            TestRegionPoint(region,ptGrowing.y(), ptGrowing.x(),&nGrowLable);
//            HTuple curGray;
//            GetGrayval(img,ptGrowing.y, ptGrowing.x,&curGray);
//			nGrowLable = matDst.at<uchar>(ptGrowing.y, ptGrowing.x);		//当前待生长点的灰度值


            if (nGrowLable == 0)					//如果标记点还没有被生长
            {
                            HTuple curGray;
                            GetGrayval(img,ptGrowing.y(), ptGrowing.x(),&curGray);
                            nCurValue = curGray.I();
//				nCurValue = src.at<uchar>(ptGrowing.y, ptGrowing.x);
//                if (abs(nSrcValue - nCurValue) < th)
                //在阈值范围内则生长,这里选择灰度在当前灰度值左右th个灰度内
                if (nCurValue >nSrcValue || abs(nSrcValue - nCurValue) < th)
                {
                    HObject PointRegion;
                    GenRegionPoints(&PointRegion,ptGrowing.y(), ptGrowing.x());
                    Union2(PointRegion,region,&region);
//					matDst.at<uchar>(ptGrowing.y, ptGrowing.x) = 255;		//标记为白色
                    vcGrowPt.push_back(ptGrowing);					//将下一个生长点压入栈中
                }
            }
        }
    }
}

从函数中可以看出,区域生长算法的输入是图像、坐标点、灰度判定值,输出为生长出来的Region区域。

3 以灰度值作为种子点进行区域生长

相当于将图像中某个灰度值的像素点挑出来作为坐标种子点,然后再进行区域生长算法。这种的效果跟Halcon中局部阈值的var_threshold的效果类似。

灰度值作为种子点.gif


void RegionGrowDlg::on_spb_growIndex_valueChanged(int arg1)
{
    HObject Region,ResultRegion;
    HTuple GrayRows,GrayCols;
    int curGray = ui->spb_gray->value();
    Threshold(CurTestImg,&Region,curGray,curGray);
    GetRegionPoints(Region,&GrayRows,&GrayCols);
    GenEmptyRegion(&ResultRegion);
    for(int i=0;i<GrayRows.Length();i++)
    {
        HTuple isInside;
        int posY = GrayRows[i].I();
        int posX = GrayCols[i].I();
        TestRegionPoint(ResultRegion,posY,posX,&isInside);
        if(isInside == 1){
            continue;
        }
        else
        {
            HObject GrowRegion;
            QPoint pos(posX,posY);
            RegionGrowing(CurTestImg,GrowRegion,pos,arg1);
            Union2(GrowRegion,ResultRegion,&ResultRegion);
        }
    }
    FillUp(ResultRegion,&ResultRegion);
    UpdateImgWindow();

    ui->PicShow->Region_ShowBuf.clear();
    region_Info h_RegionInfo;
    h_RegionInfo.region = ResultRegion;
    h_RegionInfo.color = "#ff0000c0";
    h_RegionInfo.size = 1;
    ui->PicShow->Region_ShowBuf.push_back(h_RegionInfo);
    ui->PicShow->updateShowInfoOnWindow();
}

void RegionGrowDlg::on_spb_gray_valueChanged(int arg1)
{
    HObject Region,ResultRegion;
    HTuple GrayRows,GrayCols;
    Threshold(CurTestImg,&Region,arg1,arg1);
    GetRegionPoints(Region,&GrayRows,&GrayCols);
    GenEmptyRegion(&ResultRegion);
    int index = ui->spb_growIndex->value();
    for(int i=0;i<GrayRows.Length();i++)
    {
        HTuple isInside;
        int posY = GrayRows[i].I();
        int posX = GrayCols[i].I();
        TestRegionPoint(ResultRegion,posY,posX,&isInside);
        if(isInside == 1){
            continue;
        }
        else
        {
            HObject GrowRegion;
            QPoint pos(posX,posY);
            RegionGrowing(CurTestImg,GrowRegion,pos,index);
            Union2(GrowRegion,ResultRegion,&ResultRegion);
        }
    }
    FillUp(ResultRegion,&ResultRegion);
    UpdateImgWindow();

    ui->PicShow->Region_ShowBuf.clear();
    region_Info h_RegionInfo;
    h_RegionInfo.region = ResultRegion;
    h_RegionInfo.color = "#ff0000c0";
    h_RegionInfo.size = 1;
    ui->PicShow->Region_ShowBuf.push_back(h_RegionInfo);
    ui->PicShow->updateShowInfoOnWindow();
}

4 总结

区域生长算法的核心思想是将由相似性质的像素点合并到一个region区域,对于分割复杂的图像具有比较好的性能和效果,但其算法的迭代性,导致其在运算时的时间和内存的开销比较大,当噪声和灰度不均一的时候可能会出现过度分割,而且不太适合较大图像的运算场景。
项目代码下载

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: VS (Visual Studio) 和 QT(HALCON) 是两种不同的软件开发工具。 VS 是微软开发的集成开发环境,主要用于开发 Windows 操作系统和应用程序。它提供了一系列的工具和组件,例如代码编辑器、调试器、图形化界面设计工具等,使开发者能够方便地进行软件开发和调试。VS支持多种编程语言,如C++、C#等,可以满足不同开发需求。 QT(HALCON) 是一种跨平台的开发框架,主要用于开发图形化界面和多媒体应用。它提供了丰富的工具和组件,支持多种操作系统,如Windows、Linux、macOS等,使开发者能够轻松地开发不同平台的应用程序。QT还提供了Qt Creator集成开发环境,方便开发者进行代码编写和调试。 VS 和 QT 在应用开发方面有各自的优势。VS 在 Windows 平台上的开发经验丰富,支持多种编程语言,并提供了强大的调试功能,适用于开发各类 Windows 应用程序。而QT则提供了一整套的跨平台解决方案,开发者可以使用相同的代码在不同平台上进行开发,避免了重复编写代码的繁琐工作。 总而言之,VS 适用于主要在 Windows 平台进行开发的开发者,而QT 则适用于需要在多个平台上开发应用程序的开发者。开发者可以根据自己的需求选择适合的开发工具来进行应用开发。 ### 回答2: VS和Qt是两种不同的开发工具,分别用于不同的应用领域。 VS是微软开发的一款集成开发环境(IDE),主要用于Windows平台上的软件开发。它提供了丰富的功能和工具,可以用于开发各种类型的应用程序,包括桌面应用、Web应用、移动应用等。VS具有良好的集成能力,可以与其他微软产品(如.NET、Azure等)无缝连接,同时也支持多种编程语言(如C++、C#等)。 Qt是一种跨平台的应用程序开发框架,主要用于开发图形界面应用。它提供了丰富的UI组件和类库,可以简化用户界面开发的工作。Qt支持多种编程语言,包括C++、Python等,可以运行在多个操作系统上,如Windows、Linux、Mac等。Qt还提供了一系列的工具和功能,用于处理图像、网络、数据库等方面的开发。 Halcon是一种专业的机器视觉软件库,主要用于开发机器视觉应用。它提供了丰富的图像处理和分析算法,可以用于解决各种视觉相关的问题。Halcon具有良好的性能和稳定性,可以运行在多个平台上,并且支持多种编程语言。Halcon在工业自动化、品质控制、医学影像等领域得到广泛应用。 总结来说,VS适用于开发各种类型的应用程序,Qt适用于开发图形界面应用,而Halcon适用于开发机器视觉应用。在具体选择时,需要根据实际需求和开发环境来决定使用哪个工具。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值