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

求助下大佬,边缘检测问题,谢谢

[复制链接]
zczc123 发表于 2025-6-5 14:27:08 | 显示全部楼层 |阅读模式
就是下面那张图1中,我想获取三条线槽的边缘。但是第2、3条线槽识别的是亮线边缘,如图2中。但我想获取的是黑线作为边缘,就是图3那两条线。最后面是我的代码。

图1

图1

图1

cuo1.png
图2

cuo2.png
图3

  1. read_image (Image, 'C:/Users/32321/Desktop/LaserFocus/5.26/3.5.bmp')
  2. *设置线条角度为90度(垂直)
  3. LineAngle:=90     
  4. *中心线模式设置为0
  5. CenterLine:=0
  6. dev_get_window(WindowHandle)
  7. get_image_size(Image, Width, Height)
  8. *定义感兴趣区域(ROI)
  9. top:=0
  10. bottom:=100
  11. left:=0
  12. right:=100
  13. Row1:=Height * top/100.0
  14. Column1:=Width*left/100.0
  15. Row2:=Height * bottom/100.0                                                                                                                                                                                                                                                                                                                                                                                                
  16. Column2:=Width*right/100.0   
  17. Width2 := Column2-Column1
  18. Height2 := Row2-Row1
  19. gen_rectangle2_contour_xld(Rectangle, Row1 + Height2/2,  Column1 + Width2/2, 0,Width2/2,Height2/2)
  20. rectangle1_domain(Image, ImageReduced, Row1, Column1, Row2, Column2)

  21. *边缘检测参数设置
  22. *最小分数阈值
  23. ScoreMin:=0.42
  24. *最小比例
  25. MinScale:=0.8
  26. *最大比例
  27. MaxScale:=1.2
  28. *线条宽度
  29. LineWidth:=190
  30. *最大线条宽度
  31. MaxLineWidth:=MaxScale*LineWidth
  32. *最小线条宽度
  33. MinLineWidth:=MinScale*LineWidth
  34. gen_rectangle2_contour_xld(Rectangle, Height/2, Width/2, rad(LineAngle), Width, MaxLineWidth/2)
  35. gen_rectangle2_contour_xld(Rectangle, Height/2, Width/2, rad(LineAngle), Width, MinLineWidth/2)

  36. *根据ScoreMin设置alpha、Low和High参数
  37. if(ScoreMin>=0.85)
  38.     alpha:=25*ScoreMin+5
  39. elseif(ScoreMin>=0.65)
  40.     alpha:=20*ScoreMin+5
  41. elseif(ScoreMin>=0.45)
  42.     alpha:=15*ScoreMin+5
  43. elseif(ScoreMin>=0.25)
  44.     alpha:=10*ScoreMin+5
  45. else
  46.     alpha:=5*ScoreMin+5
  47. endif
  48. Low:=ScoreMin*10+5   
  49. High:=ScoreMin*60+10

  50. *边缘检测
  51. edges_sub_pix(ImageReduced, Edges,'canny_junctions', alpha, Low, High)
  52. *选择符合条件的轮廓
  53. select_contours_xld(Edges, SelectedContours, 'contour_length', MaxLineWidth*ScoreMin, 2 * Width, -0.5, 0.5)
  54. *分割轮廓为线段
  55. segment_contours_xld (SelectedContours, ContoursSplit,'lines', 5, 4, 2)
  56. *合并共线线段
  57. union_collinear_contours_xld(ContoursSplit, UnionContours, MaxLineWidth, 1, MinLineWidth, rad(15), 'attr_forget')
  58. *再次选择符合条件的轮廓(重点设置)
  59. select_contours_xld(UnionContours, ValidEdges, 'contour_length', 1000+MaxLineWidth, 2 * Width, -0.5, 0.5)
复制代码
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
zjyVision 发表于 2025-6-6 14:37:49 | 显示全部楼层
直接用卡尺工具找边缘就行
  1. dev_close_window ()
  2. dev_open_window (0, 0, -1, -1, 'black', WindowHandle)
  3. read_image (Image, 'C:/Users/30658/Desktop/140819ufgxs7s0f6969fgn.jpg')
  4. get_image_size (Image, Width, Height)

  5. dev_set_line_width (1)
  6. * 标记测量位置
  7. draw_line (WindowHandle, Row1, Column1, Row2, Column2)
  8. LineParams := [Row1, Column1, Row2, Column2]

  9. * 创建测量句柄
  10. create_metrology_model (MetrologyHandle)
  11. * 添加测量对象
  12. set_metrology_model_image_size (MetrologyHandle, Width, Height)
  13. add_metrology_object_generic (MetrologyHandle, 'line', LineParams, 20, 3, 1, 30, [], [], Index)
  14. * 设置测量对象的参数
  15. set_metrology_object_param (MetrologyHandle, 'all', 'measure_transition', 'negative')
  16. set_metrology_object_param (MetrologyHandle, 'all', 'num_measures',50)
  17. set_metrology_object_param (MetrologyHandle, 'all', 'num_instances', 1)
  18. set_metrology_object_param (MetrologyHandle, 'all', 'measure_sigma', 1)
  19. set_metrology_object_param (MetrologyHandle, 'all', 'measure_length1', 20)
  20. set_metrology_object_param (MetrologyHandle, 'all', 'measure_length2', 10)
  21. set_metrology_object_param (MetrologyHandle, 'all', 'measure_threshold',15)
  22. set_metrology_object_param (MetrologyHandle, 'all', 'measure_interpolation', 'bicubic')
  23. set_metrology_object_param (MetrologyHandle, 'all', 'measure_select', 'first')
  24. set_metrology_object_param (MetrologyHandle, 'all', 'min_score', 0.7)

  25. * 执行测量,获取边缘点集
  26. dev_set_color ('yellow')
  27. apply_metrology_model (Image, MetrologyHandle)
  28. get_metrology_object_measures (Contours, MetrologyHandle, 'all', 'all', Row, Column)
  29. dev_set_color ('red')
  30. gen_cross_contour_xld (Cross, Row, Column, 6, 0.785398)

  31. * 获取最终测量数据和轮廓线
  32. dev_set_color ('green')
  33. dev_set_line_width (2)
  34. get_metrology_object_result (MetrologyHandle, 'all', 'all', 'result_type', 'all_param', Parameter)
  35. get_metrology_object_result_contour (Contour, MetrologyHandle, 'all', 'all', 1.5)

  36. * 释放测量句柄
  37. clear_metrology_model (MetrologyHandle)
复制代码
微信截图_20250606143359.png
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
回复 支持 1 反对 0

使用道具 举报

 楼主| zczc123 发表于 2025-6-6 14:56:41 | 显示全部楼层
zjyVision 发表于 2025-6-6 14:37
直接用卡尺工具找边缘就行

谢谢大佬,但是这需要手动去绘制,我想对于一系列图片可以进行自动的识别,不需要手动干预。还有没有什么方法啊?
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
zjyVision 发表于 2025-6-6 15:35:19 | 显示全部楼层
这是我举例写的只是告诉你用卡尺来测量    你可以先区域分析得到白边得到大概位置 在生成测量卡尺啊  你自己去看看例程  看看人家怎么自动定位的  
难道饭还要喂到嘴里才能吃吗。
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
回复 支持 1 反对 0

使用道具 举报

 楼主| zczc123 发表于 2025-6-6 16:01:44 | 显示全部楼层
zjyVision 发表于 2025-6-6 15:35
这是我举例写的只是告诉你用卡尺来测量    你可以先区域分析得到白边得到大概位置 在生成测量卡尺啊  你自 ...

哦哦,不好意思大佬,我刚刚学,以为卡尺只能手动绘制,对这部分不熟悉,例程我现在在看。
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
hankchang 发表于 2025-6-6 16:03:54 | 显示全部楼层
  1. read_image (Image140819ufgxs7s0f6969fgn, 'C:/Users/genel/OneDrive/桌面/140819ufgxs7s0f6969fgn.jpg')
  2. binary_threshold(Image140819ufgxs7s0f6969fgn, Region, 'max_separability', 'light', UsedThreshold)
  3. reduce_domain(Image140819ufgxs7s0f6969fgn, Region, ImageReduced)

  4. binary_threshold(ImageReduced, Region1, 'max_separability', 'light', UsedThreshold1)

  5. closing_rectangle1(Region1, RegionClosing, 50, 1400)
  6. connection(RegionClosing, ConnectedRegions)
  7. select_shape(ConnectedRegions, SelectedRegions, 'height', 'and', 1700, 2300)

  8. smallest_rectangle2(SelectedRegions, Row, Column, Phi, Length1, Length2)
  9. tuple_gen_const(|Row|,0.5, Newtuple)
  10. gen_rectangle2(Rectangle, Row, Column, Phi, Length1, Newtuple)
  11. skeleton (Rectangle, Skeleton)
  12. split_skeleton_lines (Skeleton, 3, BeginRow, BeginCol, EndRow, EndCol)

  13. create_metrology_model (MetrologyHandle)
  14. for i:=0 to |Row|-1 by 1
  15.     add_metrology_object_line_measure (MetrologyHandle, BeginRow, BeginCol, EndRow, EndCol, 30, 5, 1.0, 10, [], [], Index)
  16. endfor
  17. set_metrology_object_param(MetrologyHandle, 'all', 'measure_select', 'first')
  18. set_metrology_object_param(MetrologyHandle, 'all', 'measure_transition', 'negative')
  19. set_metrology_object_param(MetrologyHandle, 'all', 'num_instances', 4)
  20. apply_metrology_model(Image140819ufgxs7s0f6969fgn, MetrologyHandle)
  21. get_metrology_object_result_contour(Contour, MetrologyHandle, 'all', 'all', 1.5)

  22. set_metrology_object_param(MetrologyHandle, 'all', 'measure_select', 'last')
  23. set_metrology_object_param(MetrologyHandle, 'all', 'measure_transition', 'positive')
  24. set_metrology_object_param(MetrologyHandle, 'all', 'num_instances', 4)
  25. apply_metrology_model(Image140819ufgxs7s0f6969fgn, MetrologyHandle)
  26. get_metrology_object_result_contour(Contour1, MetrologyHandle, 'all', 'all', 1.5)
  27. clear_metrology_model(MetrologyHandle)
复制代码
2025-06-06 16 02 45.jpg
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
xah 发表于 2025-6-6 17:24:40 | 显示全部楼层
高手在网上!
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
halconuserL 发表于 2025-6-6 19:34:06 | 显示全部楼层
先学习了
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
zjdsrs715 发表于 2025-6-8 17:03:05 | 显示全部楼层
先学习了
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
freeloop 发表于 2025-6-10 14:56:48 | 显示全部楼层


我明白楼主的想法,其他铁子一直跟你说用测量工具,这确实是正解。你应该是想了解一下首先自己该如何精确定位然后配合卡尺工具是吧?
他们写的一些阈值方法工业上一般不用,我下面这个刚好最近项目用到,你可以看一下。


开头代码:

read_image (ImageFull, 'C:/Users/SYKJ/Desktop/dlRes/1.1.jpg')
get_image_size(ImageFull, Width, Height)
crop_part(ImageFull, ImagePart, 0, 0, Width, 100)
*封装抓边函数&&
CalDetectEdges (ImagePart, ContourLeftPosi, ContourRightPosi, [0], 0, 0, Row1PosiLeft, Col1PosiLeft, Row2PosiRight, Col2PosiRight)


/////////////////////////////////
函数CalDetectEdges 详细如下:

* 数据清洗
RowLeft := []
ColLeft := []
RowRight := []
ColRight := []
get_image_size (InputImg, Width, Height)

* 第一次常规检测
CalDetectAreaEdgePart (InputImg, 25, Width, Height, InParam[0], Row1Detect, Col1Detect, Row2Detect, Col2Detect, iResultDetect)

* 第三次降低阈值检测
if (iResultDetect == -1)
    CalDetectAreaEdgePart (InputImg, 18, Width, Height, InParam[0], Row1Detect, Col1Detect, Row2Detect, Col2Detect, iResultDetect)
endif

* 显示边缘点
** gen_cross_contour_xld (Cross, Row1Detect, Col1Detect, 100, 0.785398)
** gen_cross_contour_xld (Cross, Row2Detect, Col2Detect, 100, 0.785398)

* 剪裁边缘以进行检测
crop_part (InputImg, ImagePartLeft, 0, Col1Detect-40, 80, Height)
crop_part (InputImg, ImagePartRight, 0, Col2Detect-40, 80, Height)
CalGrabLineAreaEdgePart (ImagePartLeft, 0, 39, Height-1, 39, InParam[0], InParam[0], 40, 40, 15, 40, 25, LineOutBeginRow1, LineOutBeginCol1, LineOutEndRow2, LineOutEndCol2, iResultLeft)
if (iResultLeft == -1)
    * 失败后的第二次查找
    CalGrabLineAreaEdgePart (ImagePartLeft, 0, 39, Height-1, 39, InParam[0], InParam[0], 40, 40, 10, 40, 25, LineOutBeginRow1, LineOutBeginCol1, LineOutEndRow2, LineOutEndCol2, iResultLeft)
endif

CalGrabLineAreaEdgePart (ImagePartRight, 0, 39, Height-1, 39, InParam[0], InParam[0], 40, 40, 15, 40, 25, LineOutBeginRow3, LineOutBeginCol3, LineOutEndRow4, LineOutEndCol4, iResultRight)
if (iResultRight == -1)
    * 失败后的第二次查找
    CalGrabLineAreaEdgePart (ImagePartRight, 0, 39, Height-1, 39, InParam[0], InParam[0], 40, 40, 10, 40, 25, LineOutBeginRow3, LineOutBeginCol3, LineOutEndRow4, LineOutEndCol4, iResultRight)
endif

* 添加一下保护
if (iResultLeft == 0)
    * 直接返回坐标即可
    RowLeft := [LineOutBeginRow1, LineOutEndRow2] + ReturnRow
    ColLeft := [LineOutBeginCol1+Col1Detect-40, LineOutEndCol2+Col1Detect-40] + ReturnCol
    SortPoints (RowLeft, ColLeft, 0, 'Row', RowLeft, ColLeft)
    gen_contour_polygon_xld (ContourLeft, RowLeft, ColLeft)
else
    RowLeft := [0, Height-1]
    ColLeft := [0, 0]
endif

if (iResultRight == 0)
    RowRight := [LineOutBeginRow3, LineOutEndRow4] + ReturnRow
    ColRight := [LineOutBeginCol3+Col2Detect-40, LineOutEndCol4+Col2Detect-40] + ReturnCol
    SortPoints (RowRight, ColRight, 0, 'Row', RowRight, ColRight)
    * 显示结果
    gen_contour_polygon_xld (ContourRight, RowRight, ColRight)
else
    RowRight := [0, Height-1]
    ColRight := [Width-1, Width-1]
endif
return ()




/////////////////////////////////
函数CalDetectAreaEdgePart详细如下:


try
    iResultDetect := 0
    * 数据初始化
    Row1 := 0
    Col1 := 0
    Row2 := 0
    Col2 := 0

    * 图像缩放以减小时间
    zoom_image_size (InputImg, ImageZoom, Width*0.125, Height*0.125, 'constant')
    get_image_size (ImageZoom, WidthZoom, HeightZoom)
    * 使用整张图像做测量
**     gen_rectangle2 (Rectangle1, (HeightZoom)/2, (WidthZoom)/2, 0, (WidthZoom)/2, (HeightZoom)/2)
    gen_measure_rectangle2 ((HeightZoom)/2, (WidthZoom)/2, 0, (WidthZoom)/2, (HeightZoom)/2, WidthZoom, HeightZoom, 'nearest_neighbor', MeasureHandleUp)
    measure_pos (ImageZoom, MeasureHandleUp, 1, DetectThresh, 'all', 'all', RowEdgeFirstUp, ColumnEdgeFirstUp, Amplitude, Distance)
**     gen_contour_polygon_xld (Contour1, [0, HeightZoom-1], [ColumnEdgeFirstUp[0], ColumnEdgeFirstUp[0]])
**     gen_contour_polygon_xld (Contour2, [0, HeightZoom-1], [ColumnEdgeFirstUp[1], ColumnEdgeFirstUp[1]])
    * 如果检测出多个点则使用按照Col值
    if (|RowEdgeFirstUp| <= 1)
        iResultDetect := -1
        return ()
    else
        * 如果有抓取到2个以上的点则进行排序
        SortPoints (RowEdgeFirstUp, ColumnEdgeFirstUp, 0, 'Col', RowEdgeFirstUp, ColumnEdgeFirstUp)
        * 左右端点如下:
        * 还原检测区域
        Row1 := Height/2-1
        Col1 := ColumnEdgeFirstUp[0]/0.125
        Row2 := Height/2-1
        Col2 := ColumnEdgeFirstUp[|ColumnEdgeFirstUp|-1]/0.125
    endif
**     dev_display (InputImg)
**     gen_cross_contour_xld (Cross, Row1, Col1, 100, 0.785398)
**     gen_cross_contour_xld (Cross, Row2, Col2, 100, 0.785398)
**     stop ()
    return ()
catch (Exception)
    iResultDetect := -1
    return ()
endtry



/////////////////////////////////
函数CalGrabLineAreaEdgePart详细如下:


try
    iResult := 0
    get_image_size (ImageInput, Width, Height)
    distance_pp (BeginRow, BeginCol, EndRow, EndCol, Distance)
**     gen_cross_contour_xld (Cross1, BeginRow, BeginCol, 100, 0.785398)
**     gen_cross_contour_xld (Cross1, EndRow, EndCol, 100, 0.785398)
    measureRecLen1 := MeasureLength
    measureRecLen2 := MeasureLength2
    * 测量步长--移动矩形的步数
    RowStepLength := 0
    ColumnStepLength := 0

    if (PhiCC == 90 or PhiCC == 270)
        RowStepLength := 0
        if (BeginCol <EndCol)
            ColumnStepLength := int(Distance/Steps)
        else
            ColumnStepLength := -int(Distance/Steps)
        endif
    else
        if (BeginRow > EndRow)
            RowStepLength := -int(Distance/Steps)
        else
            RowStepLength := int(Distance/Steps)
        endif
        ColumnStepLength := 0
    endif

    * 测量矩形总的移动步数
    measureSteps := Steps
**     gen_cross_contour_xld (Cross, (BeginRow+EndRow)/2, (BeginCol+EndCol)/2, 100, 0.785398)
**     gen_rectangle2 (Rectangle, (BeginRow+EndRow)/2, (BeginCol+EndCol)/2, rad(Phi), measureRecLen1, measureRecLen2)
    gen_measure_rectangle2 ((BeginRow+EndRow)/2, (BeginCol+EndCol)/2, rad(Phi), measureRecLen1, measureRecLen2, Width, Height, 'nearest_neighbor', MeasureHandle)

    EdgeLineRow := []
    EdgeLineCol := []
    for step := 0 to measureSteps by 1
        translate_measure (MeasureHandle, BeginRow + step*RowStepLength, BeginCol + step*ColumnStepLength)
        measure_pos (ImageInput, MeasureHandle, 1, ThreshGrab, 'all', 'all', RowEdgeFirst, ColumnEdgeFirst, Amplitude, Distance1)
        if (|RowEdgeFirst| == 1)
            tuple_concat (EdgeLineRow, RowEdgeFirst[0], EdgeLineRow)
            tuple_concat (EdgeLineCol, ColumnEdgeFirst[0], EdgeLineCol)
        elseif (|RowEdgeFirst| > 1)
            FindClosePoint (RowEdgeFirst[0], StandCol, RowEdgeFirst, ColumnEdgeFirst, 0, fitRow, fitCol)
            tuple_concat (EdgeLineRow, fitRow, EdgeLineRow)
            tuple_concat (EdgeLineCol, fitCol, EdgeLineCol)
        else
            continue
        endif
    endfor
    * 如果没有找到线段则返回失败
    if (|EdgeLineRow| == 0)
        iResult := -1
        return ()
    endif

    * 拟合直线
    gen_contour_polygon_xld (ContourLine, EdgeLineRow, EdgeLineCol)
    fit_line_contour_xld (ContourLine, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
    * 返回结果
    LineOutBeginRow := RowBegin
    LineOutBeginCol := ColBegin
    LineOutEndRow := RowEnd
    LineOutEndCol := ColEnd
    return ()
catch (Exception)
    iResult := -1
    return ()
endtry



/////////////////////////////////
函数SortPoints详细如下:


if (OrderBy == 'Col')
    tuple_sort_index (Cols, Idx)
elseif (OrderBy == 'Row')
    tuple_sort_index (Rows, Idx)
endif

if (IncOrDec == 0)
    SortedRows := subset(Rows, Idx)
    SortedCols := subset(Cols, Idx)
    return ()
else
    * 先进行升序
    TempRows := subset(Rows, Idx)
    TempCols := subset(Cols, Idx)
    * 反转
    tuple_inverse (TempRows, InvertedRows)
    tuple_inverse (TempCols, InvertedCols)
    SortedRows := InvertedRows
    SortedCols := InvertedCols
    return ()
endif
return ()



/////////////////////////////////
函数FindClosePoint详细如下:


tuple_length (Rows, Length)
distance := []
for I := 0 to Length-1 by 1
    distance_pp (RowObj, ColObj, Rows[I], Cols[I], Dis)
    tuple_concat (distance, Dis, distance)
endfor
tuple_sort_index (distance, Indices)
Rows := subset(Rows, Indices)
Cols := subset(Cols, Indices)
if (MinOrMax == 0)
    * 最近
    OutRow := Rows[0]
    OutCol := Cols[0]
else
    * 最远
    OutRow := Rows[Length-1]
    OutCol := Cols[Length-1]
endif

return ()



A1.png
A2.png
A3.png
A4.png
A5.png
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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