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

求出矩形两边的最大最小距离!

[复制链接]
Halconan 发表于 2025-8-14 15:36:51 | 显示全部楼层 |阅读模式
要求:
1、在矩形的两边间隔一定距离取N个点(可自定义),要求平均间隔分到边长各个点位,不能用直线拟合需要体现出真实的轮廓状态;
2、两个对边的取完相应的点之后进行将对应的点连接,注意必须是最短距离,连线不能倾斜(换句话说就是两个对边其中一遍取点另一边做垂线求出,一条边到另一边的最短距离);
3、求出连接点的线的像素长度,求出最大、最小、平均值;
4、需要用到亚像素进行分割;
5、图片的大小为2592*2048;
欢迎各位大神来指导!!!给出验证,通过即可!简图如下,取图百度网盘:

通过网盘分享的文件:矩形直线
链接: https://pan.baidu.com/s/1YzMfHUI8XvSTZ7lQCweolw?pwd=uz58 提取码: uz58


奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
UKimiF 发表于 2025-8-18 08:55:07 | 显示全部楼层
很简单的需求,本质就是Rake找点,N间隔即pos间隔,代码如下:
  1. read_image (Image, './1-圆柱-50μs-伽马2-1.bmp')
  2. *//提取目标区域
  3. threshold (Image, RegionB, 0, 100)
  4. connection (RegionB, RegionB)
  5. select_shape_std (RegionB, RegionB, 'max_area', 70)

  6. *//提取目标上下边缘
  7. smallest_rectangle2 (RegionB, RowB, ColB, PhiB, L1B, L2B)
  8. gen_rectangle2 (RectOut, RowB, ColB, PhiB, L1B+100, L2B-100)
  9. difference (RegionB, RectOut, RegionB)
  10. connection (RegionB, RegionB)
  11. sort_region (RegionB, RegionB, 'first_point', 'true', 'row')
  12. select_obj (RegionB, RegionBU, 1)
  13. select_obj (RegionB, RegionBD, 2)

  14. *间隔点数
  15. N:=4
  16. *卡尺阈值
  17. Gray:=128
  18. *//上边缘
  19. smallest_rectangle2 (RegionBU, RowBU, ColBU, PhiBU, L1BU, L2BU)
  20. get_rect2_vertex (RowBU, ColBU, PhiBU, L1BU, L2BU, RowTL, ColTL, RowTR, ColTR, RowBL, ColBL, RowBR, ColBR)
  21. ElementsU:=round(L1BU/4)
  22. rake (Image, RegionRakeU, ElementsU, 20, N, 1, Gray, 'all', 'first', RowTL, ColTL, RowTR, ColTR, RowsU, ColsU)
  23. gen_cross_contour_xld (CrossU, RowsU, ColsU, 6, PhiBU)

  24. *//下边缘
  25. smallest_rectangle2 (RegionBD, RowBD, ColBD, PhiBD, L1BD, L2BD)
  26. get_rect2_vertex (RowBD, ColBD, PhiBD, L1BD, L2BD, RowTL, ColTL, RowTR, ColTR, RowBL, ColBL, RowBR, ColBR)
  27. ElementsD:=round(L1BD/4)
  28. rake (Image, RegionRakeD, ElementsD, 20, N, 1, Gray, 'all', 'first', RowBL, ColBL, RowBR, ColBR, RowsD, ColsD)
  29. gen_cross_contour_xld (CrossD, RowsD, ColsD, 6, PhiBU)

  30. *//以少点的一边为基准计算距离
  31. if(|RowsU|<=|RowsD|)
  32.     *上
  33.     tuple_select (RowsD, [0:|RowsU|-1], RowsD)
  34.     tuple_select (ColsD, [0:|RowsU|-1], ColsD)
  35. else
  36.     *下
  37.     tuple_select (RowsU, [0:|RowsD|-1], RowsU)
  38.     tuple_select (ColsU, [0:|RowsD|-1], ColsU)
  39. endif
  40. distance_pp (RowsU, ColsU, RowsD, ColsD, DisRes)
  41. *//找最大/最小/平均
  42. tuple_max (DisRes, Max)
  43. tuple_find_first (DisRes, Max, MaxIdx)
  44. gen_arrow_contour_xld (ArrowMax, RowsU[MaxIdx], ColsU[MaxIdx], RowsD[MaxIdx], ColsD[MaxIdx], 30, 30)

  45. tuple_min (DisRes, Min)
  46. tuple_find_first (DisRes, Min, MinIdx)
  47. gen_arrow_contour_xld (ArrowMin, RowsU[MinIdx], ColsU[MinIdx], RowsD[MinIdx], ColsD[MinIdx], 30, 30)

  48. tuple_mean (DisRes, Mean)

  49. *//可视化
  50. dev_clear_window ()
  51. dev_display (Image)
  52. dev_set_color ('red')
  53. dev_display (CrossU)
  54. dev_display (CrossD)
  55. dev_set_color ('blue')
  56. dev_display (ArrowMin)
  57. dev_set_color ('green')
  58. dev_display (ArrowMax)
  59. disp_message (200000, 'DisMin: '+Min$'.2f'+' pix', 'window', 10, 10, 'blue', 'false')
  60. disp_message (200000, 'DisMax: '+Max$'.2f'+' pix', 'window', 25, 10, 'green', 'false')
  61. disp_message (200000, 'DisMean: '+Mean$'.2f'+' pix', 'window', 40, 10, 'red', 'false')


复制代码

其中get_rect2_vertex是我自己封装的算子,用于获得旋转矩形的四个拐点,代码如下:
  1. gen_rectangle2 (Rectangle, Row, Column, Phi, Length1, Length2)
  2. smallest_rectangle2 (Rectangle, Row, Column, Phi, Length1, Length2)
  3. if(abs(deg(Phi))>45)
  4.     Phi:=rad(deg(Phi)-90*(Phi/abs(Phi)))
  5.     Tmp:=Length1
  6.     Length1:=Length2
  7.     Length2:=Tmp
  8. endif

  9. tuple_sin (Phi, Sin)
  10. tuple_cos (Phi, Cos)

  11. *左上角
  12. TopLeft_X := -Length1*Cos - Length2*Sin
  13. TopLeft_Y := -Length1*Sin + Length2*Cos
  14. RowTL := Row - TopLeft_Y
  15. ColTL := Column + TopLeft_X

  16. *右上角
  17. TopRight_X := Length1*Cos - Length2*Sin
  18. TopRight_Y := Length1*Sin + Length2*Cos
  19. RowTR := Row - TopRight_Y
  20. ColTR := Column + TopRight_X

  21. *右下角
  22. LowerRight_X := Length1*Cos + Length2*Sin
  23. LowerRight_Y := Length1*Sin - Length2*Cos
  24. RowBR := Row - LowerRight_Y
  25. ColBR := Column + LowerRight_X

  26. *左下角
  27. LowerLeft_X := -Length1*Cos + Length2*Sin
  28. LowerLeft_Y := -Length1*Sin - Length2*Cos
  29. RowBL := Row - LowerLeft_Y
  30. ColBL := Column + LowerLeft_X
  31. return ()
复制代码

另外Rake工具是很常见用于测量的三方库,这里就不展示了,楼主可自行搜寻。
效果图.png
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
回复 支持 1 反对 0

使用道具 举报

Mr.Han 发表于 2025-8-18 09:47:34 | 显示全部楼层
学习学习,看看大佬思路
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| Halconan 发表于 2025-8-19 14:37:19 | 显示全部楼层
UKimiF 发表于 2025-8-18 08:55
很简单的需求,本质就是Rake找点,N间隔即pos间隔,代码如下:

其中get_rect2_vertex是我自己封装的算子, ...

大佬真牛逼啊
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
UKimiF 发表于 2025-8-19 16:28:40 | 显示全部楼层
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| Halconan 发表于 2025-8-19 16:32:44 | 显示全部楼层
UKimiF 发表于 2025-8-18 08:55
很简单的需求,本质就是Rake找点,N间隔即pos间隔,代码如下:

其中get_rect2_vertex是我自己封装的算子, ...

个别图片还是会出现找点之后出现不是两条直线最短的距离,还有一种就是出现如果有毛刺或者凸点的话那就出现只有一个点对边也找不对最短距离。
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| Halconan 发表于 2025-8-19 16:39:28 | 显示全部楼层

异常1.png 异常2.png 异常3.png

有些还是会出现这种找不到两条边的最短距离
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
UKimiF 发表于 2025-8-19 16:50:25 | 显示全部楼层
Halconan 发表于 2025-8-19 16:39
有些还是会出现这种找不到两条边的最短距离

看起来像是Rake的高度不够,你把20改大点试试呢
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| Halconan 发表于 2025-8-19 17:21:00 | 显示全部楼层
UKimiF 发表于 2025-8-19 16:50
看起来像是Rake的高度不够,你把20改大点试试呢

测试来看,改大并不能改变现有找不到最短边的问题,个人感觉是不是可以用较少的点的对边你和成一条直线然后再做改点到这条边的垂线这样的话是最短的
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
UKimiF 发表于 2025-8-19 18:29:42 | 显示全部楼层
我刚刚把你的图片都下载看了一下,是卡尺过度阈值的问题,所以我建议要么把Gray:=40过度阈值改成40,或者在这之前把RegionB使用region_to_bin转化成Bin图像用于测量就可以解决这个问题,代码如下:
  1. list_files ('./Image', ['files','follow_links','recursive'], ImageFiles)
  2. tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
  3. for Index := 0 to |ImageFiles| - 1 by 1
  4.     read_image (Image, ImageFiles[Index])
  5.     *//提取目标区域
  6.     threshold (Image, RegionB, 0, 100)
  7.     connection (RegionB, RegionB)
  8.     select_shape_std (RegionB, RegionB, 'max_area', 70)
  9.    
  10.     *//提取目标上下边缘
  11.     smallest_rectangle2 (RegionB, RowB, ColB, PhiB, L1B, L2B)
  12.     gen_rectangle2 (RectOut, RowB, ColB, PhiB, L1B+100, L2B-100)
  13.     difference (RegionB, RectOut, RegionB)
  14.     connection (RegionB, RegionB)
  15.     sort_region (RegionB, RegionB, 'first_point', 'true', 'row')
  16.     select_obj (RegionB, RegionBU, 1)
  17.     select_obj (RegionB, RegionBD, 2)
  18.    
  19.     get_image_size (Image, Width, Height)
  20.     threshold (Image, RegionBA, 0, 100)
  21.     region_to_bin (RegionBA, BinImage, 255, 0, Width, Height)
  22.    
  23.     *间隔点数
  24.     N:=4
  25.     *卡尺阈值
  26.     Gray:=40
  27.     *//上边缘
  28.     smallest_rectangle2 (RegionBU, RowBU, ColBU, PhiBU, L1BU, L2BU)
  29.     get_rect2_vertex (RowBU, ColBU, PhiBU, L1BU-10, L2BU, RowTL, ColTL, RowTR, ColTR, RowBL, ColBL, RowBR, ColBR)
  30.     ElementsU:=round(L1BU/4)
  31.     rake (BinImage, RegionRakeU, ElementsU, 40, N, 1, Gray, 'all', 'first', RowTL, ColTL, RowTR, ColTR, RowsU, ColsU)
  32.     gen_cross_contour_xld (CrossU, RowsU, ColsU, 6, PhiBU)
  33.    
  34.     *//下边缘
  35.     smallest_rectangle2 (RegionBD, RowBD, ColBD, PhiBD, L1BD, L2BD)
  36.     get_rect2_vertex (RowBD, ColBD, PhiBD, L1BD-10, L2BD, RowTL, ColTL, RowTR, ColTR, RowBL, ColBL, RowBR, ColBR)
  37.     ElementsD:=round(L1BD/4)
  38.     rake (BinImage, RegionRakeD, ElementsD, 40, N, 1, Gray, 'all', 'first', RowBL, ColBL, RowBR, ColBR, RowsD, ColsD)
  39.     gen_cross_contour_xld (CrossD, RowsD, ColsD, 6, PhiBU)
  40.    
  41.     *//以少点的一边为基准计算距离
  42.     if(|RowsU|<=|RowsD|)
  43.         *上
  44.         tuple_select (RowsD, [0:|RowsU|-1], RowsD)
  45.         tuple_select (ColsD, [0:|RowsU|-1], ColsD)
  46.     else
  47.         *下
  48.         tuple_select (RowsU, [0:|RowsD|-1], RowsU)
  49.         tuple_select (ColsU, [0:|RowsD|-1], ColsU)
  50.     endif
  51.     distance_pp (RowsU, ColsU, RowsD, ColsD, DisRes)
  52.     *//找最大/最小/平均
  53.     tuple_max (DisRes, Max)
  54.     tuple_find_first (DisRes, Max, MaxIdx)
  55.     gen_arrow_contour_xld (ArrowMax, RowsU[MaxIdx], ColsU[MaxIdx], RowsD[MaxIdx], ColsD[MaxIdx], 30, 30)
  56.    
  57.     tuple_min (DisRes, Min)
  58.     tuple_find_first (DisRes, Min, MinIdx)
  59.     gen_arrow_contour_xld (ArrowMin, RowsU[MinIdx], ColsU[MinIdx], RowsD[MinIdx], ColsD[MinIdx], 30, 30)
  60.    
  61.     tuple_mean (DisRes, Mean)
  62.    
  63.     *//可视化
  64.     dev_clear_window ()
  65.     dev_display (Image)
  66.     dev_set_color ('red')
  67.     dev_display (CrossU)
  68.     dev_display (CrossD)
  69.     dev_set_color ('blue')
  70.     dev_display (ArrowMin)
  71.     dev_set_color ('green')
  72.     dev_display (ArrowMax)
  73.     disp_message (200000, 'DisMin: '+Min$'.2f'+' pix', 'window', 10, 10, 'blue', 'false')
  74.     disp_message (200000, 'DisMax: '+Max$'.2f'+' pix', 'window', 25, 10, 'green', 'false')
  75.     disp_message (200000, 'DisMean: '+Mean$'.2f'+' pix', 'window', 40, 10, 'red', 'false')
  76.    
  77.    
  78.     stop ()
  79. endfor
复制代码
1.png
2.png
3.png
4.png
5.png
6.png
7.png
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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