设置首页收藏本站
开启左侧

求一个识别曲线和直线,并计算距离

[复制链接]
怒弹你鸟 发表于 前天 16:50 | 显示全部楼层 |阅读模式
产品分黑白两种,有几组不同曝光的图片组。需要获取弯钩的上沿部分,到边沿的距离。
有多组不同曝光程度的样图。

1000曝光白

1000曝光白

1000曝光棕

1000曝光棕

1500曝光白

1500曝光白

1500曝光棕.jpg

2000曝光白

2000曝光白

2000曝光棕

2000曝光棕

2500曝光白

2500曝光白

2500曝光棕

2500曝光棕

3000曝光白

3000曝光白

3000曝光棕

3000曝光棕

最终效果图

最终效果图
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| 怒弹你鸟 发表于 前天 16:52 | 显示全部楼层
最后一张图片为需要测试的内容。求大佬给个halcon代码
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
gungun 发表于 前天 20:09 | 显示全部楼层
这个样子吗
企业微信截图_17539636648754.png
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
回复 支持 1 反对 0

使用道具 举报

 楼主| 怒弹你鸟 发表于 前天 20:36 | 显示全部楼层

大佬,是这样的是这样的。方不方便给下halcon的代码
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
Yanlf 发表于 昨天 08:05 | 显示全部楼层
用尺子量下不就行了吗
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
回复 支持 1 反对 0

使用道具 举报

 楼主| 怒弹你鸟 发表于 昨天 08:55 | 显示全部楼层
Yanlf 发表于 2025-8-1 08:05
用尺子量下不就行了吗

主要不知道怎么识别出来这两个。主要是水平有点差
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
UKimiF 发表于 昨天 10:59 | 显示全部楼层
read_image (Image, './Image.jpg')
dev_get_window (WindowHandle)
*//点的rake范围
*//这里设置rake的起点和终点
Row1:=480
Column1:=590
Row2:=480
Column2:=940
rake (Image, RegionRakeP, (Column2-Column1), 50, 0.5, 1, 128, 'all', 'first',\
      Row1, Column1, Row2, Column2, RowsP, ColsP)
*//找最上面的点
tuple_min (RowsP, RowsPMin)
tuple_find_first (RowsP, RowsPMin, RowsPMinI)
gen_cross_contour_xld (CrossP, RowsP[RowsPMinI], ColsP[RowsPMinI], 40, 0.785398)

*//线的rake范围
Row1L:=1620
Col1L:=426
Row2L:=1620
Col2L:=760
rake (Image, RegionRakeL, (Col2L-Col1L), 150, 0.5, 1, 10, 'all', 'first',\
      Row2L, Col2L, Row1L, Col1L, RowsL, ColsL)
*//这里获得点后拟合一条直线
gen_contour_polygon_xld (ContL, RowsL, ColsL)
fit_line_contour_xld (ContL, 'tukey', -1, 0, 5, 2, RowBL, ColBL, RowEL, ColEL, Nr, Nc, Dist)
gen_contour_polygon_xld (ContL, [RowBL,RowEL], [ColBL,ColEL])

*//计算点到直线的垂直距离
get_pl_footpoint (RowsP[RowsPMinI], ColsP[RowsPMinI], RowBL, ColBL, RowEL, ColEL, RowF, ColF)
gen_arrow_contour_xld (ArrowRes, RowsP[RowsPMinI], ColsP[RowsPMinI], RowF, ColF, 20, 20)
distance_pl (RowsP[RowsPMinI], ColsP[RowsPMinI], RowBL, ColBL, RowEL, ColEL, Dis)

dev_clear_window ()
dev_display (Image)
dev_set_color ('red')
dev_display (CrossP)
dev_display (ContL)
dev_display (ArrowRes)
disp_message (WindowHandle, 'Res: '+Dis, 'window', 10, 10, 'red', 'false')
效果图.jpg
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
回复 支持 1 反对 0

使用道具 举报

UKimiF 发表于 昨天 11:01 | 显示全部楼层
很简单的需求,本质就是点线测量,代码里的rake是原图测量很常用的三方算子,内容如下:
SelectOut := Select
TransitionOut := Transition
*获取图像尺寸
get_image_size(Image,Width,Height)
*产生一个空显示对象,用于显示
gen_empty_obj (Regions)
*初始化边缘坐标数组
ResultRow:=[]
ResultColumn:=[]
*产生直线xld
gen_contour_polygon_xld (RegionLines, [Row1,Row2], [Column1,Column2])
*存储到显示对象
concat_obj (Regions, RegionLines, Regions)
*计算直线与x轴的夹角,逆时针方向为正向
angle_lx (Row1, Column1, Row2, Column2, ATan)

*边缘检测方向垂直由于检测直线:直线方向正向旋转90°为边缘检测方向
ATan:=ATan+rad(90)

*根据检测直线按顺序产生测量区域矩形,并存储到显示对象
for i:=1 to Elements by 1
     *如果只有一个测量矩形,作为卡尺工具,宽度为检测直线的长度
     if(Elements == 1)
            RowC:=(Row1+Row2)*0.5
            ColC:=(Column1+Column2)*0.5
            *判断是否超出图像,超出不检测边缘
            if(RowC>Height-1 or RowC<0 or ColC>Width-1 or ColC<0)
                   continue
            endif
            distance_pp(Row1, Column1, Row2, Column2, Distance)
            DetectWidth:=Distance
            gen_rectangle2_contour_xld (Rectangle, RowC, ColC, ATan, DetectHeight/2, Distance/2)
     else
            *如果有多个测量矩形,产生该测量矩形xld
            RowC:=Row1+(((Row2-Row1)*(i-1))/(Elements-1))
            ColC:=Column1+(Column2-Column1)*(i-1)/(Elements-1)
            *判断是否超出图像,超出不检测边缘
            if(RowC>Height-1 or RowC<0 or ColC>Width-1 or ColC<0)
                   continue
            endif
            gen_rectangle2_contour_xld (Rectangle, RowC, ColC, ATan, DetectHeight/2, DetectWidth/2)
     endif
     
     *把测量矩形xld存储到显示对象
     concat_obj (Regions, Rectangle, Regions)
     if(i==1)
            *在第一个测量矩形绘制一个箭头xld,用于指示边缘检测方向
            RowL2:=RowC+DetectHeight/2*sin(-ATan)
            RowL1:=RowC-DetectHeight/2*sin(-ATan)
            ColL2:=ColC+DetectHeight/2*cos(-ATan)
            ColL1:=ColC-DetectHeight/2*cos(-ATan)
            gen_arrow_contour_xld (Arrow1, RowL1, ColL1, RowL2, ColL2, 25, 25)
            *把xld存储到显示对象
            concat_obj (Regions, Arrow1, Regions)
     endif
     *产生测量对象句柄
     gen_measure_rectangle2 (RowC, ColC, ATan, DetectHeight/2, DetectWidth/2, Width, Height, 'nearest_neighbor', MeasureHandle)

     *设置极性
       if (TransitionOut=='negative')
              TransitionOut := 'negative'
       elseif (TransitionOut=='positive')
              TransitionOut := 'positive'
     else
              TransitionOut := 'all'
     endif
     *设置边缘位置。最强点是从所有边缘中选择幅度绝对值对大点,需要设置为'all'
       if (SelectOut=='first')
              SelectOut := 'first'
       elseif (SelectOut=='last')
              SelectOut := 'last'
     else
              SelectOut := 'all'
     endif
     *检测边缘
       measure_pos (Image, MeasureHandle, Sigma, Threshold, TransitionOut, SelectOut, RowEdge, ColEdge, Amplitude, Distance)
     *清除测量对象句柄
     close_measure (MeasureHandle)
     
     *临时变量初始化
     *保存找到指定边缘的坐标
     tRow:=0
     tCol:=0
     *保存边缘的幅度绝对值
     t:=0
     *找到的边缘必须至少为1个
     tuple_length (RowEdge, Number)
     if(Number<1)
            continue
     endif
     
     *有多个边缘时,选择幅度绝对之后最大的边缘
     for j:= 0 to Number-1 by 1
            if(abs(Amplitude[j])>t)
                   tRow:=RowEdge[j]
                   tCol:=ColEdge[j]
                   t:=abs(Amplitude)
            endif
     endfor
     *把找到的边缘保存在输出数组
     if(t>0)
            ResultRow:=[ResultRow,tRow]
            ResultColumn:=[ResultColumn,tCol]
     endif
endfor
return ()
然后另一个get_pl_footpoint是我自己封装的算子,计算点到直线的垂点,内容如下:
x1:=Column_P1
y1:=Row_P1
x2:=Column_P2
y2:=Row_P2
x:=Column
y:=Row

* 检查是否为垂直线
if (x2 - x1 == 0)
    * 垂直线的情况,垂点的 x 坐标与直线的 x 坐标相同,y 坐标与点的 y 坐标相同
    Column_Foot := x1
    Row_Foot := y
else
    * 非垂直线的情况,使用原来的计算公式
    k := (y2 - y1) / (x2 - x1)
    A := k
    B := -1
    C := y1 - k * x1

    Column_Foot := (B * B * x - A * B * y - A * C) / (A * A + B * B)
    Row_Foot := (A * A * y - A * B * x - B * C) / (A * A + B * B)
endif
return ()
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
回复 支持 1 反对 0

使用道具 举报

 楼主| 怒弹你鸟 发表于 昨天 11:29 | 显示全部楼层
UKimiF 发表于 2025-8-1 11:01
很简单的需求,本质就是点线测量,代码里的rake是原图测量很常用的三方算子,内容如下:
SelectOut := Sele ...

感谢大佬
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表