Halcon测量专栏-圆弧测量

news2024/11/16 13:26:31

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

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(完美方案)解决mfc140u.dll文件丢失问题,快速且有效的修复

唉&#xff0c;又是丢失了mfc140u.dll&#xff0c;这该怎么办呢&#xff1f;如果你的电脑突然找不到或丢失mfc140u.dll文件&#xff0c;那就真是太糟糕了。别担心&#xff0c;我分享给你一些干货&#xff0c;告诉你如何快速解决mfc140u.dll丢失的问题。 一.mfc140u.dll属性功能…

分布式之Ribbon使用以及原理

Ribbon使用以及原理 1、负载均衡的两种方式 服务器端负载均衡 传统的方式前端发送请求会到我们的的nginx上去&#xff0c;nginx作为反向代理&#xff0c;然后路由给后端的服务器&#xff0c;由于负载均衡算法是nginx提供的&#xff0c;而nginx是部署到服务器端的&#xff0c;所…

数据结构入门(3)2.链表接口实现

目录 前言 头文件 动态申请一个结点 单链表打印 单链表尾插 单链表的头插 单链表的尾删 单链表头删 单链表查找 单链表在pos位置之后插入x 单链表删除pos位置之后的值 在pos的前面插入 删除pos位置 销毁顺序表 前言 本文将介绍链表常见的功能的实现 头文件 #…

【Java】仓库管理系统 SpringBoot+LayUI+DTree(源码)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

【APB协议 UVM_Sequencer Driver Monitor_2024.03.04】

apb协议 写时序 地址、写信号、PSEL、写数据信号同时发生变化&#xff0c;即传输的第一个时钟被称为SETUP周期。在下个时钟上升沿,PENABLE信号拉高&#xff0c;表示ENABLE周期&#xff0c;在该周期内&#xff0c;数据、地址以及控制信号都必须保持有效。整个写传输在这个周期…

【Java常用API】正则表达式的基础使用

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

Matlab|计及需求响应和电能交互的多主体综合能源系统主从博弈优化调度策略

目录 主要内容 部分代码 结果一览 下载链接 主要内容 程序建立了多主体综合能源模型&#xff0c;采用双层模型进行求解&#xff0c;上层用自适应粒子群算法求解出各能源售价和需求响应补偿价格&#xff1b;下层采用混合整数规划算法求解出三个园区、配电网、储能…

leetcode 热题 100_旋转图像

题解一&#xff1a; 翻转数组&#xff1a;先将数组沿右上-左下对角线翻转&#xff0c;再将数组上下翻转。 class Solution {public void rotate(int[][] matrix) {int n matrix.length;for (int i 0; i < n; i) {//沿右上-左下对角线翻转for (int j 0; j < n - i - 1…

vob格式转换mp4怎么转? 如何保持vob原画质?

VOB&#xff08;Video Object&#xff09;文件格式在数字视频制作领域崭露头角。起源于DVD技术的发展&#xff0c;VOB旨在存储包括音频、视频和菜单等多媒体元素的内容。这一格式为数字娱乐提供了高质量的视频体验&#xff0c;然而&#xff0c;由于其相对封闭的特性&#xff0c…

Stable Diffusion 模型下载:Comic Babes(漫画宝贝)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 条目内容类型大模型基础模型SD 1.5来源CIVITAI作者datmuttdoe文件名称comicBabes_v2.safet…

数据治理实践——金融行业大数据治理的方向与实践

目录 一、证券数据治理服务化背景 1.1 金融数据治理发展趋势 1.2 证券行业数据治理建设背景 1.3 证券行业数据治理目标 1.4 证券行业数据治理痛点 二、证券数据治理服务化实践 2.1 国信证券数据治理建设框架 2.2 国信证券数据治理建设思路 2.3 数据模型管理 2.4 数据…

例解变分自编码器(VAE)

本文通过一个回归例子介绍变分自编码器。产生训练和测试样本的代码如下&#xff1a; # data import tensorflow as tf import numpy as np import matplotlib.pyplot as plt %matplotlib inlinedef f(x, sigma):# y 10 * sin(2 * pi) epsilonreturn 10 * np.sin(2 * np.pi *…

【漏洞分析】CVE-2024-27198可RCE身份验证绕过JetBrains TeamCity

CVE-2024-27198可RCE身份验证绕过JetBrains TeamCity 一、基本原理二、创建新的管理员用户三、自我检查四、POC 一、基本原理 向存在漏洞服务器发送一个不存在的页面请求 ?jsp/app/rest/server;.jsp 这会使服务器报错提供版本信息&#xff0c;且无需登录 Fofa app“JET_BRAIN…

Linux工具 - 好用的yum包管理器

~~~~ 前言yum是什么为什么有yum如何使用yum配置用户yum源为什么要配置yum源具体配置备份CentOS-Base.repo文件下载对应阿里yum源到本目录/etc/yum.repos.d/清理yum并生成缓存更改配置文件CentOS-Base.repo更新yum 常用命令listinstall选项-y remove选项-y update 结语 前言 本…

ON1 Portrait AI 2023:智能美颜,打造完美人像 mac版

在数字化时代&#xff0c;人像摄影的需求和追求愈发高涨。为了满足摄影师对于完美人像的追求&#xff0c;ON1推出了全新的ON1 Portrait AI 2023。这款软件结合了先进的人工智能技术与人像处理的专业知识&#xff0c;为人像摄影带来了前所未有的智能体验。 ON1 Portrait AI 202…

2024.3.11

1.结构体数组 代码&#xff1a; #include<myhead.h>struct Stu {char name[100];int age;double score; };int main(int argc, const char *argv[]) {int i,j;struct Stu t{"z",1,1};struct Stu arr[4]{{"甲乙",12,98},{"陈二",13,77},{…

docker启动时环境变量不生效(docker打包成镜像后环境变量失效)

前言 因项目需要多处部署&#xff0c;为了部署的方便&#xff0c;于是准备将项目环境打包成docker镜像以便于部署。mq、mysql这些在仓库中都有现成的镜像&#xff0c;虽然java和nginx的也都有&#xff0c;但是不知道当时是怎么想的&#xff0c;就不想搞太多镜像&#xff0c;也…

五、OpenAI实战之Assistants API

在8线小城的革委会办公室里&#xff0c;黑8和革委会主任的对话再次展开。 黑8&#xff1a;主任&#xff0c;您知道吗&#xff1f;除了OpenAI API&#xff0c;现在还有一项新的技术叫做Assistants API&#xff0c;它可以帮助我们更好地进行对话和沟通。 主任&#xff1a;Assis…

Redhat Linux(RHEL) - Primavera P6 EPPM 安装及分享

引言 继上一期发布的Oracle Linux版环境发布之后&#xff0c;近日我又制作了基于Redhat Linux 的P6虚拟机环境&#xff0c;同样里面包含了全套P6 最新版应用服务 此虚拟机仅用于演示、培训和测试目的。如您在生产环境中使用此虚拟机&#xff0c;请先与Oracle Primavera销售代表…

SD-WAN能解决企业网络的哪些问题?

SD-WAN技术的崛起为企业网络带来了全新的解决方案。在数字化转型、云计算、远程办公和5G等领域&#xff0c;SD-WAN技术展现出强劲的市场趋势。那么&#xff0c;SD-WAN究竟能够解决企业网络中的哪些难题呢&#xff1f; 提升网络带宽利用率 传统网络在连接分支机构时&#xff0c;…