Halcon测量专栏-圆弧测量

1.前言

1.1什么是圆弧

圆上任意两点间的部分叫做圆弧。由于圆弧有正反的特性,即为有顺时针方向和逆时针方向,在确定圆弧时,也需要确定圆弧的方向。

1.2halcon实现方式

针对圆弧的问题。1:它与圆是相似的,都具备中心坐标和半径,还有起始和终点角度;2:定义一个圆弧方向,以顺时针为测量方向。

2.halcon程序

2.1halcon程序


read_image (Image, 'D:/1NewWork/work/2.26/.png')

get_image_size (Image, Width, Height)
*获得圆上初始采样点
row:=[296,949,2046]
column:=[2555,3063,1192]
********************************拟合弧形采样ROI*****************
gen_contour_polygon_xld (Contour, row, column)
fit_circle_contour_xld (Contour, 'algebraic', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
gen_circle_contour_xld (ContCircle, Row, Column, Radius, EndPhi,StartPhi,  'positive', 1)
*gen_circle_contour_xld (ContCircle, Row, Column, Radius, 1,EndPhi,  'positive', 1)
dev_display (Image)
dev_display (ContCircle)
row1:=[]
column1:=[]
gen_empty_obj (EmptyObject)
gen_empty_obj (EmptyObject2)

phi:=3.14*2-StartPhi

tuple_abs (StartPhi-EndPhi+3.14*2, Abs)
tuple_ceil (Abs/3.1415926*90, Ceil)
**********************************弧形采样*********************
for Index := 0to Ceil-1 by 1
    tuple_sin(phi+rad(Index*2),Sin)
    tuple_cos(phi+rad(Index*2),Cos)
    *创建测量矩形
    gen_measure_rectangle2 (Row+Radius*Sin, Column+Radius*Cos, -Index*3.1415926/180*2-phi, 50, 5, Width, Height, 'nearest_neighbor', MeasureHandle)
    *绘制测量矩形轮廓用于显示
    gen_rectangle2_contour_xld (Rectangle,Row+Radius*Sin, Column+Radius*Cos, -Index*3.1415926/180*2-phi, 50, 5)
    *开启测量
    measure_pos (Image, MeasureHandle, 2, 20, 'all', 'last', RowEdge, ColumnEdge, Amplitude, Distance)
    *绘制测量结果
    gen_cross_contour_xld (Cross, RowEdge, ColumnEdge, 20, 1)
    concat_obj (Cross, EmptyObject, EmptyObject)
    concat_obj (EmptyObject2, Rectangle, EmptyObject2)

    row1:=[row1,RowEdge]
    column1:=[column1,ColumnEdge]
endfor

gen_contour_polygon_xld (Contour1, row1, column1)
*********************输出结果横纵坐标与半径,起始与结束的角度*****************
fit_circle_contour_xld (Contour1, 'algebraic', -1, 0, 0, 3, 2, Row2, Column2, Radius2, StartPhi2, EndPhi2, PointOrder2)
gen_circle_contour_xld (ContCircle2, Row2, Column2, Radius2,EndPhi2, StartPhi2,  'positive', 1)
dev_display (Image)
dev_display (ContCircle)
dev_display (EmptyObject2)
dev_display (EmptyObject)
dev_display (ContCircle2)

2.2halcon程序讲解

2.2.1读取图像和绘制ROI

read_image (Image, 'D:/1NewWork/work/2.26/.png')
get_image_size (Image, Width, Height)
*获得圆上初始采样点
row:=[296,949,2046]
column:=[2555,3063,1192]
********************************拟合弧形采样ROI*****************
gen_contour_polygon_xld (Contour, row, column)
fit_circle_contour_xld (Contour, 'algebraic', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)

找圆弧与找圆是类似的,都需要一个基准的ROI区域,但是圆弧在于,它需要起始点和终点,中间点为圆心位置。根据3点绘制圆的方式,所以ROI选取,3个采样点即可

2.2.2拟合采样点,并绘制弧线ROI

gen_contour_polygon_xld (Contour, row, column)
fit_circle_contour_xld (Contour, 'algebraic', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
gen_circle_contour_xld (ContCircle, Row, Column, Radius, EndPhi,StartPhi,  'positive', 1)
*gen_circle_contour_xld (ContCircle, Row, Column, Radius, 1,EndPhi,  'positive', 1)
dev_display (Image)
dev_display (ContCircle)

通过选取的3点ROI拟合一个圆,获取到圆心坐标,半径,圆弧的起始和终点

2.2.3圆弧检测

row1:=[]
column1:=[]
gen_empty_obj (EmptyObject)
gen_empty_obj (EmptyObject2)

phi:=3.14*2-StartPhi

tuple_abs (StartPhi-EndPhi+3.14*2, Abs)
tuple_ceil (Abs/3.1415926*90, Ceil)
**********************************弧形采样*********************
for Index := 0to Ceil-1 by 1
    tuple_sin(phi+rad(Index*2),Sin)
    tuple_cos(phi+rad(Index*2),Cos)
    *创建测量矩形
    gen_measure_rectangle2 (Row+Radius*Sin, Column+Radius*Cos, -Index*3.1415926/180*2-phi, 50, 5, Width, Height, 'nearest_neighbor', MeasureHandle)
    *绘制测量矩形轮廓用于显示
    gen_rectangle2_contour_xld (Rectangle,Row+Radius*Sin, Column+Radius*Cos, -Index*3.1415926/180*2-phi, 50, 5)
    *开启测量
    measure_pos (Image, MeasureHandle, 2, 20, 'all', 'last', RowEdge, ColumnEdge, Amplitude, Distance)
    *绘制测量结果
    gen_cross_contour_xld (Cross, RowEdge, ColumnEdge, 20, 1)
    concat_obj (Cross, EmptyObject, EmptyObject)
    concat_obj (EmptyObject2, Rectangle, EmptyObject2)

    row1:=[row1,RowEdge]
    column1:=[column1,ColumnEdge]
endfor

gen_contour_polygon_xld (Contour1, row1, column1)
*********************输出结果横纵坐标与半径,起始与结束的角度*****************
fit_circle_contour_xld (Contour1, 'algebraic', -1, 0, 0, 3, 2, Row2, Column2, Radius2, StartPhi2, EndPhi2, PointOrder2)
gen_circle_contour_xld (ContCircle2, Row2, Column2, Radius2,EndPhi2, StartPhi2,  'positive', 1)
dev_display (Image)
dev_display (ContCircle)
dev_display (EmptyObject2)
dev_display (EmptyObject)
dev_display (ContCircle2)

根据定义的圆弧,以初始点为起始点,顺时针旋转,旋转指定角度,并使用测量矩形对每个采样区域进行采样,将所有采样点重新拟合为圆即可得到最终结果
在这里插入图片描述

2.2.4注意事项

尤为要注意圆弧是有方向的,文中预先定义圆弧方向为顺时针方向

3.C#程序工具实现

#region // 圆弧测量
public static bool ArcMeasure(HObject image,HTuple Row1,HTuple Column1,HTuple Row2,HTuple Column2,
            HTuple Row3,HTuple Column3, HTuple Sigma, HTuple Threshold,
            out HObject ConCircle,out HTuple CenterRow,out HTuple CenterColumn,out HTuple ResultR,
            out HTuple StartPhi,out HTuple EndPhi)
{
    HOperatorSet.GenEmptyObj(out ConCircle);
    CenterRow = -1;
    CenterColumn = -1;
    ResultR = -1;
    StartPhi = -1;
    EndPhi = -1;

    try
    {
        HOperatorSet.GetImageSize(image, out HTuple width, out HTuple height);
        HTuple Row = new HTuple(),Column=new HTuple();
        Row[0] = Row1; Row[1] = Row2; Row[2] = Row3;
        Column[0]= Column1; Column[1]= Column2; Column[2] = Column3;
        HOperatorSet.GenContourPolygonXld(out HObject  Contour, Row, Column);
        HOperatorSet.FitCircleContourXld(Contour, "algebraic", -1, 0, 0, 3, 2, out HTuple row,
                out HTuple column, out HTuple radius, out HTuple startPhi, out HTuple endPhi, out HTuple pointOrder);
        HTuple row1=new HTuple(),column1=new HTuple(),phi=0;
        HOperatorSet.GenEmptyObj(out HObject emptyObject);
        HOperatorSet.GenEmptyObj(out HObject emptyObject2);
        phi = Math.PI*2 - startPhi;
        HOperatorSet.TupleAbs(startPhi - endPhi+Math.PI*2, out HTuple abs);
        HOperatorSet.TupleCeil(abs / Math.PI * 90, out HTuple ceil);

        

        for (int i = 0; i < ceil-1; i++)
        {
            HOperatorSet.TupleSin(phi + i * 2 * Math.PI / 180 , out HTuple sin);
            HOperatorSet.TupleCos(phi + i * 2 * Math.PI / 180 , out HTuple cos);

            HOperatorSet.GenMeasureRectangle2(row + radius * sin, column + radius * cos, ((((-i) * 3.1415926) / 180) * 2) - phi ,
                50, 5, width, height, new HTuple("nearest_neighbor"), out HTuple measureHandle);
            HOperatorSet.MeasurePos(image, measureHandle, 2, 20, new HTuple("all"), new HTuple("last"), out HTuple rowEdge,
                out HTuple columnEdge, out HTuple amplitude, out HTuple distance);
            row1 = row1.TupleConcat(rowEdge);
            column1 = column1.TupleConcat(columnEdge);
        }
        HOperatorSet.GenContourPolygonXld(out HObject contour, row1, column1);
        HOperatorSet.FitCircleContourXld(contour, new HTuple("algebraic"), -1, 0, 0, 3, 2, out CenterRow, out CenterColumn,
            out ResultR, out StartPhi, out EndPhi , out HTuple pointOrder2);
        HOperatorSet.TupleLength(CenterRow, out HTuple length);
        if (length == 0)
        {
            return false;
        }
        HOperatorSet.GenCircleContourXld(out ConCircle, CenterRow, CenterColumn, ResultR, EndPhi, StartPhi, new HTuple("positive"), 1);
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}
#endregion
#region // 单点查找
/// <summary>
/// 单个点查找
/// </summary>
/// <param name="Image">输入图像</param>
/// <param name="Row1">输入直线起始横坐标</param>
/// <param name="Column1">输入直线起始列坐标</param>
/// <param name="Row2">输入直线终点横坐标</param>
/// <param name="Column2">输入直线终点列坐标</param>
/// <param name="MeasureWide">输入测量矩形宽度</param>
/// <param name="Sigma">输入测量矩形的高斯滤波值</param>
/// <param name="Thrashold">输入最小边缘对比度</param>
/// <param name="ResultRow">输出结果横坐标</param>
/// <param name="ResultColumn">输出结果列坐标</param>
/// <returns>拟合成功返回true,拟合失败返回false</returns>
static public bool PointMeasure_(HObject Image, HTuple Row1, HTuple Column1,HTuple Row2,HTuple Column2,
            HTuple MeasureWide, HTuple Sigma, HTuple Thrashold, 
            out HTuple ResultRow, out HTuple ResultColumn)
{
    ResultRow = -1; ResultColumn = -1;
    try
    {
        HTuple hv_TmpCtrl_Row, hv_TmpCtrl_Column, hv_TmpCtrl_Dr, hv_TmpCtrl_Dc, hv_TmpCtrl_Phi,
                hv_TmpCtrl_Len1;
        HOperatorSet.GetImageSize(Image, out HTuple width, out HTuple height);
            hv_TmpCtrl_Row = 0.5 * (Row1 + Row2);
            hv_TmpCtrl_Column = 0.5 * (Column1 + Column2);
            hv_TmpCtrl_Dr = Row1 - Row2;
            hv_TmpCtrl_Dc = Column2 - Column1;
            hv_TmpCtrl_Phi = hv_TmpCtrl_Dr.TupleAtan2( hv_TmpCtrl_Dc);
            hv_TmpCtrl_Len1 = 0.5 * ((((hv_TmpCtrl_Dr * hv_TmpCtrl_Dr) + (hv_TmpCtrl_Dc * hv_TmpCtrl_Dc))).TupleSqrt());
        HOperatorSet.GenMeasureRectangle2(hv_TmpCtrl_Row, hv_TmpCtrl_Column, hv_TmpCtrl_Phi,
            hv_TmpCtrl_Len1, MeasureWide, width, height, "nearest_neighbor", out HTuple measureHandle);
        HOperatorSet.MeasurePos(Image, measureHandle, Sigma, Thrashold, new HTuple("all"), new HTuple("first"), out ResultRow,
            out ResultColumn, out HTuple amplitude, out HTuple distance);
        HOperatorSet.TupleLength(ResultRow, out HTuple length);
        if (length==0)
        {
            return false;
        }
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}
#endregion

总结

弧形检测,与圆检测依旧类型,都是通过一定量的采样点去拟合出几何图形。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/449020.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

视频监控汇聚管理系统EasyCVR平台RTMP推流异常是什么原因?

AI视频智能分析/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff08;专网、内网、局域网、广域网、公网等&#xff09;&#xff0c;支持设备通过4G、5G、WIFI、有线等方式接入&#xff0c;并将设备进行统一集中接入与视频汇聚管理&#xff0c;经平台接入的视频流能实现多…

王道机试C++第 5 章 数据结构二:队列queue和21年蓝桥杯省赛选择题Day32

目录 5.2 队列 1&#xff0e;STL-queue 课上演示&#xff1a; 基本代码展示&#xff1a; 2. 队列的应用 例:约瑟夫问题 No. 2 题目描述&#xff1a; 思路提示&#xff1a; 代码展示&#xff1a; 例&#xff1a;猫狗收容所 题目描述&#xff1a; 代码表示&#xff1…

安防视频监控汇聚平台EasyCVR使用RTMP推流出现异常的原因排查与解决

AI视频智能分析/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff08;专网、内网、局域网、广域网、公网等&#xff09;&#xff0c;支持设备通过4G、5G、WIFI、有线等方式接入&#xff0c;并将设备进行统一集中接入与视频汇聚管理&#xff0c;经平台接入的视频流能实现多…

大数据开发 hadoop集群 2.hadoop框架入门

自从我学会了寻找&#xff0c;我就已经找到 ——史铁生 —— 24.3.10 内容简介 Hadoop入门&#xff1a; ①概念 ②环境准备 ③hadoop生产集群搭建 ④常见错误的解决方案 ①概念&#xff1a;1.Hadoop是什么 2.Hadoop发展历史 3.Hadoop…

【Linux】线程封装_互斥

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;线程封装Thread.cpp &#x1f449;&am…

骨传导耳机哪个牌子好?五大热门品质机型盘点,体验超赞!

在蓝牙耳机中&#xff0c;骨传导耳机凭借不入耳佩戴更健康等优点&#xff0c;迅速成为当下的热门款式&#xff0c;但随着骨传导耳机市场的品牌日渐增多&#xff0c;以及市场上不专业的骨传导耳机泛滥成灾的问题&#xff0c;有很多消费者在选择骨传导耳机的时候&#xff0c;都出…

【算法】Hash存储——开放寻址法

模拟散列表 维护一个集合&#xff0c;支持如下几种操作&#xff1a; I x&#xff0c;插入一个整数 x&#xff1b; Q x&#xff0c;询问整数 x是否在集合中出现过&#xff1b; 现在要进行 N次操作&#xff0c;对于每个询问操作输出对应的结果。 输入格式 第一行包含整数 N&am…

代码随想录 贪心算法-中等题目-序列问题

376.摆动序列 376. 摆动序列 中等 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如&#xff0c; [1, 7…

spring boot 访问 static public 目录下的静态资源报404解决办法

1.前提是你没有修改spring boot 默认拦截路径&#xff0c;跟默认访问资源的目录。 在idea 设置中 把 compiler 下的 Buid project automatically 勾选上

开源的java视频处理库介绍

本文将为您详细讲解 Java 开源的视频处理库&#xff0c;以及它们的特点、区别和应用场景。Java 社区提供了多种视频处理库&#xff0c;这些库可以帮助您在 Java 应用程序中实现视频的录制、编辑、转换和播放等功能。 1. JCodec 特点 - 基于 Java 的视频编解码库。 - 支…

ChatGpt只能看,但无法发送消息的解决办法

这几天发现chatgpt没法发送消息了,我以为是网络问题,又过了几天还是不能发,我以为是梯子的问题,可给我急坏了,于是我用无痕模式发现可以访问额. 但是无痕模式毕竟不是长久之计,于是找到了一个方法 1.首先把电脑缓存全清除了 第一种方法: 快捷键是 : ctrlshiftdel (这会吧浏览…

分支需求管理方式

此文为上一篇文章的后续 我们来回顾一下&#xff0c;现在&#xff0c;你的小组负责的系统&#xff0c;有主干分支&#xff0c;每次新的需求&#xff0c;你都从主干(formal)拉取分支(dev-日期-需求名)进行修改&#xff0c;自测通过后&#xff0c;合并至测试分支(test)进行提测&a…

Python高级二

一、异常 1、定义 异常是在程序执行过程中出现的错误或意外情况。当程序遇到异常时&#xff0c;它会中断当前的执行流程&#xff0c;并尝试找到相应的异常处理机制来解决问题。 2、常见异常类型 SyntaxError&#xff1a;语法错误&#xff0c;通常是代码书写不符合Python语法规则…

VSCode单机活动栏图标无法收起

如果活动栏为展开状态&#xff0c;单击活动栏图标可以正常收起&#xff0c;但无法通过再次单击打开&#xff0c;解决方案如下&#xff1a; 设置->工作台->外观&#xff1a; Activity Bar:Icon Click Behavior: 切换为默认的toggle

C++ 作业 24/3/11

1、提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数&#xff08;要求使用C风格字符串完成&#xff09; #include <iostream>using namespace std;int main() {string str;cout << "please enter str:&…

【Flutter 面试题】如何理解Flutter中的Widget、State、Context ,他们是为了解决什么问题?

【Flutter 面试题】如何理解Flutter中的Widget、State、Context &#xff0c;他们是为了解决什么问题&#xff1f; 文章目录 写在前面解答补充说明完整代码示例运行结果如下详细说明 写在前面 &#x1f64b; 关于我 &#xff0c;小雨青年 &#x1f449; CSDN博客专家&#xff…

svg简单教程

推荐查看这个视频 一小时讲完SVG 简介 scalable 英 /ˈskeɪləbl/ 美 /ˈskeɪləbl/ adj. &#xff08;计算机&#xff09; 可扩展的&#xff1b;可改变大小的&#xff0c;可缩放的&#xff1b;可攀登的&#xff1b;可称量的&#xff1b;可去鳞的 vector 英 /ˈvektə/ 美…

CTP-API开发系列之五:SimNow环境介绍

CTP-API开发系列之五&#xff1a;SimNow环境介绍 CTP-API开发系列之五&#xff1a;SimNow环境介绍SimNow模拟测试环境第一套第二套登录关键字段可视化终端常见问题 CTP-API开发系列之五&#xff1a;SimNow环境介绍 如果你要研发一套国内期货程序化交易系统&#xff0c;从模拟测…

Valid8Proxy:一款功能强大的工作代理获取、验证和存储工具

关于Valid8Proxy Valid8Proxy是一款功能强大且用户友好的代理管理工具&#xff0c;该工具功能丰富&#xff0c;旨在帮助广大研究人员获取、验证和存储工作代理的相关信息。 无论你是需要用于网络资源爬取、网络数字匿名化还是测试网络安全的代理&#xff0c;Valid8Proxy都可以…

如何利用AWS CloudFront 自定义设置SSL

Amazon CloudFront 提供三种选项&#xff0c;可以加速整个网站并从 CloudFront 的边缘站点通过安全的 HTTPS 方式交付内容。除能够安全地从边缘站点交付内容外&#xff0c;您还可以配置 CDN 来使用针对源提取的 HTTPS 连接&#xff0c;这样您的数据就会实现从源到最终用户的端到…