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

基于halcon的直线查找之卡尺

直线的检测在halcon中主要有两种方式:直线拟合和卡尺直线。这里分享卡尺方法,拟合请移步:直线拟合

直线卡尺

首先把整体思路列出来:
CreateMetrologyModel创建一个测量句柄;
AddMetrologyObjectLineMeasure添加一个线“Line”的模型;
SetMetrologyObjectParam设置相关测量参数。比如:卡尺垂直于边的长度,卡尺的宽度,卡尺的个数,保留的卡尺个数,边缘最低对比度等;
ApplyMetrologyModel开始找边;
GetMetrologyObjectMeasuresGetMetrologyObjectResultContour将找到的边界结果显示,同时获得每个卡尺找到的点坐标。

是不是很简单?没错,就这么简单无脑。作为调包侠,是还是觉得用的算子有点多啊…感觉给别人用这么多函数有点low?那就自己再封一层壳吧,瞬间高大上了。

CTRL + CV时刻

直接copy拿去用吧

// 代码量有点冗杂,很多参数判断。起始作为底层供调用的方法,无需写这些判断,推荐判断安全性的问题应该交给上层调用者来保证,底层保证效率就行,避免上层判断,底层又判断,造成重复耗时。可以删掉,从CreateMetrologyModel开始。void FindLineCaliper(HObject ho_Image, HObject* ho_ResultContour, HObject* ho_MeasureContour,HTuple hv_Row1, HTuple hv_Column1, HTuple hv_Row2, HTuple hv_Column2, HTuple hv_MeasureLength,HTuple hv_MeasureWidth, HTuple hv_MeasureSigma, HTuple hv_MeasureThreshold, HTuple hv_NumInstances,HTuple hv_MeasureSelect, HTuple hv_MeasureTransition, HTuple hv_NumMeasures,HTuple* hv_LineFind, HTuple* hv_RowStart, HTuple* hv_ColumnStart, HTuple* hv_RowEnd,HTuple* hv_ColumnEnd, HTuple* hv_RowFrame, HTuple* hv_ColumnFrame)
{HObject  ho_MeasuredLines;HTuple  hv_num_instances, hv_measure_select, hv_measure_transition;HTuple  hv_num_measures, hv_ValueName, hv_Value, hv_Channels;HTuple  hv_Width, hv_Height, hv_IsNumber, hv_Index, hv_Index1;HTuple  hv_IsString, hv_NumMatches1, hv_NumMatches2, hv_IsString1;HTuple  hv_NumMatches3, hv_NumMatches4, hv_MetrologyHandle;HTuple  hv_IndexLine, hv_RowMeasure, hv_ColumnMeasure, hv_IndexSearch;HTuple  hv_Frame_Parameter, hv_Index2, hv_NumMatches5, hv_NumMatches6;;//*********找直线函数**********//****输入参数:Image:输入图像, 需要单通道图像*****//****输入参数:Row1,Column1,Row2,Column2:找直线的参考基准线, 其位置与需要找的直线位置相同或近似平行*****//****输入参数:MeasureLength,MeasureWidth,MeasureSigma,MeasureThreshold:卡尺的长宽, Sigma值和阈值,支持数组输入*****//****输入参数:ParameterName,ParameterValue:检测控制参数名称和值, 具体请见下表*****//****输入参数: NumInstances: 检测的直线数量,必须为正整数***//****输入参数: NumMeasures: 检测的卡尺数量*****//****输入参数:MeasureTransition:找线的方式, 由暗到明, 由明到暗,只能是'positive'或'negative'*****//****输入参数:MeasureSelect: 每个卡尺内找到的点是最近点还是最远点, 只能是'first'或'last'*****//****输出参数:LineFind: 0:无法找到直线;1:可以找到直线*****//****输出参数:RowStart,ColumnStart,RowEnd,ColumnEnd:找到的直线起点与终点的坐标*****//****输出参数:ResultContour:生成的直线图形*****//****输出参数:MeasureContour:生成的卡尺图形*****//****输出参数:RowFrame,ColumnFrame:每个卡尺找到的点的坐标*****//****函数作者:*****//****更新时间:*****//******************//****默认参数值*****//******************(*hv_LineFind) = 0;(*hv_RowStart) = 0;(*hv_ColumnStart) = 0;(*hv_RowEnd) = 0;(*hv_ColumnEnd) = 0;(*hv_RowFrame) = HTuple();(*hv_ColumnFrame) = HTuple();hv_num_instances = 1;hv_measure_select = "last";hv_measure_transition = "positive";hv_num_measures = 40;hv_ValueName.Clear();hv_ValueName[0] = "num_instances";hv_ValueName[1] = "num_measures";hv_ValueName[2] = "measure_transition";hv_ValueName[3] = "measure_select";//****参数类型和范围确认*****//****int/real 型:['int',min,max], min=<输入值<=max,上下限若是无穷大,则写作'' *****//****string 型:['string','a','b',...,'z'],输入值需是'a','a','b',...,'z'中的任意一个值*****hv_Value.Clear();hv_Value[0] = "int";hv_Value[1] = 1;hv_Value[2] = "";hv_Value[3] = "int";hv_Value[4] = 1;hv_Value[5] = "";hv_Value[6] = "string";hv_Value[7] = "positive";hv_Value[8] = "negative";hv_Value[9] = "string";hv_Value[10] = "first";hv_Value[11] = "last";//*************************************//****1.判断输入参数是否满足计算要求*****//*************************************//****a.判断输入图像是否为单通道图像*****CountChannels(ho_Image, &hv_Channels);if (0 != (hv_Channels != 1)){Rgb1ToGray(ho_Image, &ho_Image);}GetImageSize(ho_Image, &hv_Width, &hv_Height);//****b.判断输入的直线参数是否为number,若出现非数字格式的输入情况,则直接返回*****TupleIsNumber((((((((hv_Row1.TupleConcat(hv_Column1)).TupleConcat(hv_Row2)).TupleConcat(hv_Column2)).TupleConcat(hv_MeasureLength)).TupleConcat(hv_MeasureWidth)).TupleConcat(hv_MeasureThreshold)).TupleConcat(hv_NumInstances)).TupleConcat(hv_NumMeasures),&hv_IsNumber);{HTuple end_val50 = (hv_IsNumber.TupleLength()) - 1;HTuple step_val50 = 1;for (hv_Index = 0; hv_Index.Continue(end_val50, step_val50); hv_Index += step_val50){if (0 != (HTuple(hv_IsNumber[hv_Index]) == 0)){return;}}}//****判断输入参数名称和数值的类型是否正确*****//****MeasureLeght≥1*****{HTuple end_val58 = (hv_MeasureLength.TupleLength()) - 1;HTuple step_val58 = 1;for (hv_Index1 = 0; hv_Index1.Continue(end_val58, step_val58); hv_Index1 += step_val58){if (0 != (HTuple(hv_MeasureLength[hv_Index1]) < 1)){hv_MeasureLength[hv_Index1] = 1;}}}//****MeasureWidth≥1*****{HTuple end_val65 = (hv_MeasureWidth.TupleLength()) - 1;HTuple step_val65 = 1;for (hv_Index1 = 0; hv_Index1.Continue(end_val65, step_val65); hv_Index1 += step_val65){if (0 != (HTuple(hv_MeasureWidth[hv_Index1]) < 1)){hv_MeasureWidth[hv_Index1] = 1;}}}//****MeasureSigma≥0.4*****{HTuple end_val72 = (hv_MeasureSigma.TupleLength()) - 1;HTuple step_val72 = 1;for (hv_Index1 = 0; hv_Index1.Continue(end_val72, step_val72); hv_Index1 += step_val72){if (0 != (HTuple(hv_MeasureSigma[hv_Index1]) < 0.4)){hv_MeasureSigma[hv_Index1] = 0.4;}}}//****MeasureThreshold≥1, MeasureThreshold≤255*****{HTuple end_val79 = (hv_MeasureThreshold.TupleLength()) - 1;HTuple step_val79 = 1;for (hv_Index1 = 0; hv_Index1.Continue(end_val79, step_val79); hv_Index1 += step_val79){if (0 != (HTuple(hv_MeasureThreshold[hv_Index1]) < 1)){hv_MeasureThreshold[hv_Index1] = 1;}if (0 != (HTuple(hv_MeasureThreshold[hv_Index1]) > 255)){hv_MeasureThreshold[hv_Index1] = 255;}}}//****NumInstances ≥1*****TupleInt(hv_NumInstances, &hv_num_instances);if (0 != (hv_num_instances < 1)){hv_num_instances = 1;}//****NumMeasures ≥1******TupleInt(hv_NumMeasures, &hv_num_measures);if (0 != (hv_num_measures < 1)){hv_num_measures = 1;}//****MeasureTransion: 'positive' or 'negative'*****TupleIsString(hv_MeasureTransition, &hv_IsString);if (0 != hv_IsString){TupleRegexpTest(hv_MeasureTransition, (HTuple("positive").Append("ignore_case")), &hv_NumMatches1);if (0 != (hv_NumMatches1 == 1)){hv_measure_transition = "positive";}TupleRegexpTest(hv_MeasureTransition, (HTuple("negative").Append("ignore_case")), &hv_NumMatches2);if (0 != (hv_NumMatches2 == 1)){hv_measure_transition = "negative";}TupleRegexpTest(hv_MeasureTransition, (HTuple("all").Append("ignore_case")), &hv_NumMatches3);if (0 != (hv_NumMatches3 == 1)){hv_measure_transition = "all";}}//****MeasureSelect: 'first' or 'last'*****TupleIsString(hv_MeasureSelect, &hv_IsString1);if (0 != hv_IsString1){TupleRegexpTest(hv_MeasureSelect, (HTuple("first").Append("ignore_case")), &hv_NumMatches4);if (0 != (hv_NumMatches4 == 1)){hv_measure_select = "first";}TupleRegexpTest(hv_MeasureSelect, (HTuple("last").Append("ignore_case")), &hv_NumMatches5);if (0 != (hv_NumMatches5 == 1)){hv_measure_select = "last";}TupleRegexpTest(hv_MeasureSelect, (HTuple("all").Append("ignore_case")), &hv_NumMatches6);if (0 != (hv_NumMatches6 == 1)){hv_measure_select = "all";}}//********************//****2.找直线函数*****//********************CreateMetrologyModel(&hv_MetrologyHandle);//****添加多个直线寻找---3/7*****//for Index3 := 0 to |MeasureLength|-1 by 1//for Index4 := 0 to |MeasureWidth|-1 by 1//for Index5 := 0 to |MeasureSigma|-1 by 1//for Index6 := 0 to |MeasureThreshold|-1 by 1//set_metrology_model_image_size (MetrologyHandle, Width, Height)//add_metrology_object_line_measure (MetrologyHandle, Row1, Column1, Row2, Column2, MeasureLength[Index3], MeasureWidth[Index4], MeasureSigma[Index5], MeasureThreshold[Index6], [], [], IndexLine)//endfor//endfor//endfor//endfor//add_metrology_object_line_measure (MetrologyHandle, Row1, Column1, Row2, Column2, MeasureLength, MeasureWidth, MeasureSigma, MeasureThreshold, [], [], Index)SetMetrologyModelImageSize(hv_MetrologyHandle, hv_Width, hv_Height);AddMetrologyObjectLineMeasure(hv_MetrologyHandle, hv_Row1, hv_Column1, hv_Row2,hv_Column2, hv_MeasureLength, hv_MeasureWidth, hv_MeasureSigma, hv_MeasureThreshold,HTuple(), HTuple(), &hv_IndexLine);SetMetrologyObjectParam(hv_MetrologyHandle, "all", "num_instances", hv_num_instances);SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_select", hv_measure_select);SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_transition", hv_measure_transition);SetMetrologyObjectParam(hv_MetrologyHandle, "all", "num_measures", hv_num_measures);ApplyMetrologyModel(ho_Image, hv_MetrologyHandle);if (0 != (hv_IndexLine > 0)){GetMetrologyObjectMeasures(&(*ho_MeasureContour), hv_MetrologyHandle, "all", "all", &hv_RowMeasure, &hv_ColumnMeasure);GetMetrologyObjectResultContour(&ho_MeasuredLines, hv_MetrologyHandle, "all", "all", 1.5);(*hv_LineFind) = 1;}else{(*hv_LineFind) = 0;}//**********************//****3.获取直线参数*****//**********************{HTuple end_val163 = hv_IndexLine;HTuple step_val163 = 1;for (hv_IndexSearch = 0; hv_IndexSearch.Continue(end_val163, step_val163); hv_IndexSearch += step_val163){GetMetrologyObjectResult(hv_MetrologyHandle, hv_IndexSearch, "all", "result_type", "all_param", &hv_Frame_Parameter);if (0 != ((hv_Frame_Parameter.TupleLength()) == (hv_num_instances * 4))){(*hv_LineFind) = 1;{HTuple end_val167 = ((hv_Frame_Parameter.TupleLength()) / 4) - 1;HTuple step_val167 = 1;for (hv_Index2 = 0; hv_Index2.Continue(end_val167, step_val167); hv_Index2 += step_val167){(*hv_RowStart)[hv_Index2] = HTuple(hv_Frame_Parameter[hv_Index2 * hv_num_instances]);(*hv_ColumnStart)[hv_Index2] = HTuple(hv_Frame_Parameter[(hv_Index2 * hv_num_instances) + 1]);(*hv_RowEnd)[hv_Index2] = HTuple(hv_Frame_Parameter[(hv_Index2 * hv_num_instances) + 2]);(*hv_ColumnEnd)[hv_Index2] = HTuple(hv_Frame_Parameter[(hv_Index2 * hv_num_instances) + 3]);}}}if (0 != (HTuple((*hv_LineFind) == 1).TupleOr(hv_IndexSearch == hv_IndexLine))){GetMetrologyObjectResultContour(&(*ho_ResultContour), hv_MetrologyHandle, hv_IndexSearch, "all", 1.5);GetMetrologyObjectMeasures(&(*ho_MeasureContour), hv_MetrologyHandle, hv_IndexSearch, "all", &(*hv_RowFrame), &(*hv_ColumnFrame));ClearMetrologyModel(hv_MetrologyHandle);break;}}}return;
}

注意

我还有更简洁的版本

基于halcon的直线查找之卡尺相关推荐

  1. Halcon自定义直线卡尺rake

    拟合直线 rake工具 1. 为什么要开发rake工具 2. rake工具封装的三个函数 2.1 创建ROI的函数:draw_rake 2.2 边缘测量的函数:rake 2.3 拟合直线的函数:pts ...

  2. 基于halcon与c#联合的视觉处理软件

    1.视觉软件 当我们拿到一个视觉项目,如果有一个拖拽式视觉软件去帮我们完成这样一个项目,既省时又省力,学什么halcon.opencv.visionpro,甚至头疼的C++.C#,统统不需要,也能快速 ...

  3. 【愚公系列】2023年04月 Halcon机器视觉-基于Halcon车牌识别

    文章目录 前言 1.Halcon是什么 2.车牌识别 3.车牌识别系统 一.基于Halcon车牌识别 1.车牌识别的流程 二.车牌识别前预处理 三.开始车牌识别 四.识别车牌上面的中文 1.处理需要识 ...

  4. halcon拟合直线

    halcon拟合直线 read_image (hImage, 'E:/vs2012/halcon卡尺例程/白光碗光效果4.bmp') get_image_pointer1(hImage, Pointe ...

  5. 递归二分法php,PHP基于二分法实现数组查找功能示例【循环与递归算法】

    本文实例讲述了PHP基于二分法实现数组查找功能.分享给大家供大家参考,具体如下: 二分法.分别使用while循环的方法和递归调用的方法. // 二分法的使用数组必须是有序的,或升序,或降序 $arr ...

  6. 基于HALCON的模板匹配方法总结

    很早就想总结一下前段时间学习HALCON的心得,但由于其他的事情总是抽不出时间.去年有过一段时间的集中学习,做了许多的练习和实验,并对基于HDevelop的形状匹配算法的参数优化进行了研究,写了一篇& ...

  7. 带你读AI论文:基于Transformer的直线段检测

    摘要:本文提出了一种基于Transformer的端到端的线段检测模型.采用多尺度的Encoder/Decoder算法,可以得到比较准确的线端点坐标.作者直接用预测的线段端点和Ground truth的 ...

  8. halcon 差异模型 异物_基于HALCON的形状匹配算法的研究和心得总结

    很早就想总结一下前段时间学习HALCON的心得,但由于其他的事情总是抽不出时间.去年有过一段时间的集中学习,做了许多的练习和实验,并对基于HDevelop的形状匹配算法的参数优化进行了研究,写了一篇& ...

  9. 查找(四)-------基于B树的查找和所谓的B树

    关于B树,不想写太多了,因为花在基于树的查找上的时间已经特么有点多了,就简单写写算了,如果以后有需要,或者有时间,可以再深入写写 首先说一下,为什么要有B树,以及B树是什么,很多数据结构和算法的书上来 ...

最新文章

  1. python常用数据结构的常用操作
  2. qthread destroyed while thread is still running
  3. SQL Server 2005 在建立与服务器的连接时出错,错误26收藏
  4. Java 动作事件_java按钮动作事件
  5. 二、CSS知识总结(上篇)
  6. 知识蒸馏在推荐系统中的应用
  7. 抖音云控_抖音云控/快手云控:引领5G电商短视频新潮流
  8. 学习方向、当前要做的事
  9. SLF4J:Failed to load class org.slf4j.impl.StaticLoggerBinder
  10. 数据3分钟丨墨天轮2021年度数据库奖项及中国数据库魔力象限等多项成果发布...
  11. Ansible Tower - 使用入门 3 - 通过模板运行 Git 上的 Playbook 和 Role
  12. linux ssh端口是否打开,如何查看linux中的ssh端口开启状态
  13. form标签的action之前 加密_口令爆破之突破前端JS加密
  14. 为SSD加速 实战4KB对齐技巧1/3
  15. SVN客户端使用详细
  16. 饿了么微信小程序抓取
  17. Misra c规则简介
  18. java将小写的日期转换为大写的日期
  19. Linux操作系统笔记(基本命令+环境安装项目部署+Shell编程)
  20. 斑马打印机 android驱动,斑马ZC300驱动-斑马Zebra ZC300打印机驱动下载 v01.03.00官方版 - 51驱动网...

热门文章

  1. vr虚拟现实技术的前景!对未来发展带来有利的趋势吗?
  2. iOS 优化资源文件
  3. 在Windows下配置与使用CVSNT - dudu - 博客园
  4. 设计原则:单一职责原则
  5. 霍尼韦尔战略合作上工申贝;华科精准获美敦力中国基金千万元战略投资 | 美通企业日报...
  6. android4.3 打包成image,DCloud 离线打包之Android Studio
  7. 红杉观点|生成式AI:一个创造性的新世界
  8. MSI BIOS更新迷惑行为
  9. Arcmap设置经纬网只显示度不显示分
  10. FQ队列对quantum的处理