V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wjx0912
V2EX  ›  OpenCV

请教一个 opencv 算法,图片中检测圆形对象

  •  
  •   wjx0912 · 297 天前 · 2073 次点击
    这是一个创建于 297 天前的主题,其中的信息可能已经有所发展或是发生改变。

    图片发到 2 楼,大约 2000x2000 的图片,目标机器没有显卡。算法时间可以长一点,单张图片 10 秒也可以接受。

    测了下霍夫算法,好像时间太长了,而且准确度也没法保障。

    求一个思路( opencv 不太熟,里面好像有 svm,cnn,dnn 啥的不知道是否合适),万分感谢~~~

    24 条回复    2024-03-08 14:44:39 +08:00
    wjx0912
        3
    wjx0912  
    OP
       297 天前
    wjx0912
        4
    wjx0912  
    OP
       297 天前
    wjx0912
        5
    wjx0912  
    OP
       297 天前
    wjx0912
        6
    wjx0912  
    OP
       297 天前
    还请各位大佬不吝赐教~
    bluesenzhu
        7
    bluesenzhu  
       297 天前
    你贴的什么,啥也看不到
    StephenW
        8
    StephenW  
       297 天前
    YoLov5 应该可以,训练起来也简单
    sunshijie
        9
    sunshijie  
       297 天前
    推荐 YoLov5 +1
    Muniesa
        10
    Muniesa  
       297 天前 via Android
    霍夫圆的参数对结果影响很大,如果不需要拟合圆的话,直接 yolo 吧
    xinyu391
        11
    xinyu391  
       297 天前
    yolov5 +1
    bluesenzhu
        12
    bluesenzhu  
       297 天前   ❤️ 3
    如果全是这种有规律的图案,自己手搓代码(硬编码)速度应该可以在 0.1s 内。
    你这个肉眼看特征很明显,就是白底上的小圆,二值化后找轮廓,然后手工写代码判断下是不是圆
    alexsz
        13
    alexsz  
       297 天前
    从图片上看特征还是比较明显的,第一步可以行把方形小纸片扣出来,因为圆形的直径和小纸片长宽基本保持在一个比例范围,所以可以根据小纸片尺寸指定一个适合的霍夫算法参数,第二步再用霍夫检测圆,如果检测出多个圆形,第三步可以再次根据圆形和小纸片的面积或者尺寸比例 排除一下
    0312birdzhang
        14
    0312birdzhang  
       297 天前
    intel 的 CPU 的话可以用 openvino 来加速,跑 onnx 模型没那么慢。用上面提到的 yolov5 ,应该不难。
    CynicalRose
        15
    CynicalRose  
       297 天前
    精度要求不高的话可以考虑传统算法,用 opencv 进行模板匹配。
    你可以先参考下: https://blog.csdn.net/yukinoai/article/details/88366234
    paopjian
        16
    paopjian  
       297 天前
    我试了一下,霍夫曼检测好像没问题,就是不太准

    ![202403080934.png]( https://s2.loli.net/2024/03/08/egPqBYbjLNzriAC.png)

    代码是抄的 https://aistudio.baidu.com/projectdetail/649807
    wjx0912
        17
    wjx0912  
    OP
       297 天前
    感谢大家~

    打算先试下霍夫(图片先缩放一下),然后 15 楼的模版匹配,然后再试试 yolo5
    wjx0912
        18
    wjx0912  
    OP
       297 天前
    大概率不用霍夫,这个准确度是在是难以达到。。。
    Yuhyeong
        19
    Yuhyeong  
       297 天前   ❤️ 1
    这种程度直接模式匹配就行了,用不上机器学习都。opencv 自带的有模式匹配函数
    sslzjx
        20
    sslzjx  
       297 天前
    Halcon 代码,可以试下

    * This program fits circles into circular contour segments
    * to extract their positions and radii
    *
    dev_update_off ()
    *
    * step: acquire image
    *
    read_image (Image, 'OXfE6Ph.png')

    * auto_threshold (Image, all_Region, 15.0)
    * connection (all_Region, all_ConnectedRegions)
    * select_shape (all_ConnectedRegions, all_ConnectedRegions, 'area', 'and', 7000, 14000)
    * count_obj (all_ConnectedRegions, all_NumberContours)
    * for Index := 1 to all_NumberContours by 1
    * select_obj(all_ConnectedRegions, ObjectSelected1, Index)
    * smallest_rectangle1(ObjectSelected1, Row1, Column1, Row2, Column2)
    * crop_part(Image, ImagePart, Row1, Column1, Row2-Row1, Column2-Colu)
    * endfor

    get_image_size (Image, Width, Height)
    dev_close_window ()
    dev_open_window (0, 0, Width / 2, Height / 2, 'light gray', WindowID)
    dev_set_part (0, 0, Height - 1, Width - 1)
    dev_set_line_width (3)
    dev_set_color ('white')
    dev_set_draw ('margin')
    dev_display (Image)
    set_display_font (WindowID, 14, 'mono', 'true', 'false')
    disp_continue_message (WindowID, 'black', 'true')
    stop ()
    *
    * step: segment image into regions
    *
    dev_set_colored (12)
    dev_set_line_width (2)
    dev_set_draw ('fill')

    *equ_histo_image (Image, Image)
    scale_image_max (Image, Image)
    decompose3 (Image, Image_R, Image_G, Image_B)
    * fast_threshold (Image, Region, 180, 230, 20)
    auto_threshold (Image_G, Region, 5.0)
    stop()

    connection (Region, ConnectedRegions)
    select_shape (ConnectedRegions, SelectedRegions, 'circularity', 'and', 0.6, 1.2)
    select_shape (SelectedRegions, SelectedRegions, 'area', 'and', 200, 500)
    dev_display (Image)
    dev_display (SelectedRegions)
    disp_continue_message (WindowID, 'black', 'true')
    stop ()
    *
    * step: create ROI for contour processing
    *
    boundary (SelectedRegions, RegionBorder, 'inner_filled')
    dilation_circle (RegionBorder, RegionDilation, 3.5)
    union1 (RegionDilation, RegionUnion)
    reduce_domain (Image, RegionUnion, ImageReduced)
    dev_clear_window ()
    dev_display (ImageReduced)
    disp_continue_message (WindowID, 'black', 'true')
    stop ()
    *
    * step: create contours and fit circles to them
    *
    edges_sub_pix (ImageReduced, Edges, 'canny', 1.5, 10, 40)
    segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 5, 2, 2)
    select_contours_xld (ContoursSplit, SelectedContours, 'contour_length', 25, 99999, -0.5, 0.5)
    count_obj (SelectedContours, NumberContours)
    gen_empty_obj (Circles)
    for i := 1 to NumberContours by 1
    select_obj (SelectedContours, ObjectSelected, i)
    get_contour_global_attrib_xld (ObjectSelected, 'cont_approx', Attrib)
    if (Attrib == 1)
    concat_obj (Circles, ObjectSelected, Circles)
    endif
    endfor
    union_cocircular_contours_xld (Circles, UnionContours, rad(60), rad(10), rad(30), 100, 50, 10, 'true', 1)
    dev_clear_window ()
    dev_set_color ('black')
    dev_display (UnionContours)
    disp_continue_message (WindowID, 'black', 'true')
    stop ()
    count_obj (UnionContours, NumberCircles)
    CenterRow := []
    CenterColumn := []
    dev_clear_window ()
    dev_set_color ('black')
    set_display_font (WindowID, 12, 'mono', 'true', 'false')
    dev_display (SelectedContours)
    for i := 1 to NumberCircles by 1
    select_obj (UnionContours, ObjectSelected, i)
    fit_circle_contour_xld (ObjectSelected, 'algebraic', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
    gen_circle_contour_xld (ContCircle, Row, Column, Radius, 0, rad(360), 'positive', 1.5)
    dev_set_color ('white')
    dev_display (ContCircle)
    if (i == 1)
    Row2 := Row + Radius * sin(rad(-45))
    Column2 := Column + Radius * cos(rad(-45))
    set_tposition (WindowID, Row2 - 35, Column2 + 5)
    endif
    if (i > 1)
    exist := 0
    for j := 0 to i - 2 by 1
    distance_pp (Row, Column, CenterRow[j], CenterColumn[j], DistanceCenters)
    if (DistanceCenters < 20)
    exist := 1
    endif
    endfor
    if (exist == 1)
    Row2 := Row + Radius * sin(rad(-135))
    Column2 := Column + Radius * cos(rad(-135))
    set_tposition (WindowID, Row2 - 40, Column2 - 30)
    else
    Row2 := Row + Radius * sin(rad(-45))
    Column2 := Column + Radius * cos(rad(-45))
    set_tposition (WindowID, Row2 - 35, Column2 + 5)
    endif
    endif
    disp_arrow (WindowID, Row, Column, Row2, Column2, 2)
    write_string (WindowID, i)
    if (i < 8)
    disp_message (WindowID, 'R' + i + ' = ' + Radius$'.4', 'window', i * 20, 130, 'black', 'false')
    else
    disp_message (WindowID, 'R' + i + ' = ' + Radius$'.4', 'window', (i - 7) * 20, 400, 'black', 'false')
    endif
    CenterRow := [CenterRow,Row]
    CenterColumn := [CenterColumn,Column]
    endfor
    *
    dev_update_window ('on')
    lycpang
        21
    lycpang  
       297 天前
    你换个思路,在白色的区域检测是不是有较大色差,是不是比检测形状简单多了。
    kyingstar
        22
    kyingstar  
       297 天前
    https://github.com/bubbliiiing/yolov7-pytorch 可以用这个训练,本地训练太慢可以在 https://www.autodl.com/home 上训练
    czita
        23
    czita  
       297 天前
    可以看下 opencv 的二值化和轮廓
    wjx0912
        24
    wjx0912  
    OP
       297 天前
    @Yuhyeong 谢谢
    @sslzjx 谢谢,但是 halcon 不会,学习成本有点高了~
    @lycpang 这个感觉比 yolo 还要难一点。。。
    @czita 谢谢
    @kyingstar 嗯。周末试下。谢谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1447 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 17:01 · PVG 01:01 · LAX 09:01 · JFK 12:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.