保姆級講解實時識別色子的點數的算法_Halcon篇


在以前的賭場中會有人出老千預先知道色子的點數,不清楚現在的國際賭場是否還有(話說我也不會去賭博的,哈哈哈哈哈哈)
那么,本文就把這種用Halcon編寫的實時識別色子點數的算法分享出來
本文會有兩個關於圖像分割的

核心算法:
距離變換與分水嶺算法

distance_transform (ConnectedRegions, DistanceImage, ‘octagonal’, ‘true’, 1000, 1000)

watersheds_threshold (ImageScaleMax, Basins, 10)
下面會有一個數據集,是一系列一堆色子放在一起的圖片(1000*1000)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 識別的效果如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文是使用Halcon編寫算法,下一篇博客會再提供一篇用開源視覺庫OpenCV 編寫的算法。

* Image Acquisition 01: Code generated by Image Acquisition 01
dev_close_window ()
dev_open_window (0, 0, 500, 500, 'black', WindowHandle)
*dev_set_draw ('margin')
*dev_set_color ('black')
set_display_font (WindowHandle, 30, 'mono', 'true', 'false')
list_files ('D:/Dices/', ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
ResultIndex:=1
for Index := 0 to |ImageFiles| - 1 by 1
    read_image (Image, ImageFiles[Index])
    get_image_size (Image, Width, Height)
    threshold (Image, Regions, 180, 255)
    fill_up (Regions, RegionFillUp)
    connection (RegionFillUp, ConnectedRegions)
    distance_transform (ConnectedRegions, DistanceImage, 'octagonal', 'true', 1000, 1000)
    convert_image_type (DistanceImage, ImageConverted, 'byte')
    invert_image (ImageConverted, ImageInvert)
    scale_image_max (ImageInvert, ImageScaleMax)
    *watersheds (ImageScaleMax, Basins1, Watersheds)
    watersheds_threshold (ImageScaleMax, Basins, 10)
    intersection (Basins, ConnectedRegions, RegionIntersection)
    
    select_shape (RegionIntersection, SelectedRegions, 'area', 'and', 30000, 100000)
    count_obj (SelectedRegions, Number)
    dev_display (Image)
    for Index1 := 1 to Number by 1
        select_obj (SelectedRegions, ObjectSelected, Index1)
        reduce_domain (Image, ObjectSelected, ImageReduced)
        threshold (ImageReduced, Regions1, 0, 150)
        fill_up (Regions1, RegionFillUp1)
        connection (RegionFillUp1, ConnectedRegions1)
        select_shape (ConnectedRegions1, SelectedRegions1, 'area', 'and', 200, 20000)
        count_obj (SelectedRegions1, Number1)
        area_center (ObjectSelected, Area, Row, Column)
        disp_message (WindowHandle, Number1, 'image', Row, Column, 'green', 'false')
        
    endfor
*     dump_window_image (Image1, WindowHandle)
*         write_image (Image1, 'jpg', 0, 'D:/Dices/Results/'+ResultIndex+'.jpg')
*         ResultIndex:=ResultIndex+1
    stop()
endfor

  

感興趣的可以把數據集下載下來,跑一跑程序,看下效果。
那么下面開始講解本文的核心算法:
1,
距離變換算法
distance_transform(Region : DistanceImage : Metric, Foreground, Width, Height : )
以下是介紹:

Name
distance_transform — Compute the distance transformation of a region.

Signature
distance_transform(Region : DistanceImage : Metric, Foreground, Width, Height : )

Description
distance_transform computes for every point of the input region Region (or its complement, respectively) the distance of the point to the border of the region. The parameter Foreground determines whether the distances are calculated for all points within the region (Foreground = 'true') or for all points outside the region (Foreground = 'false'). The distance is computed for every point of the output image DistanceImage, which has the specified dimensions Width and Height. The input region is always clipped to the extent of the output image. If it is important that the distances within the entire region should be computed, the region should be moved (see move_region) so that it has only positive coordinates and the width and height of the output image should be large enough to contain the region. The extent of the input region can be obtained with smallest_rectangle1.

The parameter Metric determines which metric is used for the calculation of the distances. If Metric = 'city-block', the distance is calculated from the shortest path from the point to the border of the region, where only horizontal and vertical “movements” are allowed. They are weighted with a weight of 1. If Metric = 'chessboard', the distance is calculated from the shortest path to the border, where horizontal, vertical, and diagonal “movements” are allowed. They are weighted with a weight of 1. If Metric = 'octagonal', a combination of these approaches is used, which leads to diagonal paths receiving a higher weight. If Metric = 'chamfer-3-4', horizontal and vertical movements are weighted with a weight of 3, while diagonal movements are weighted with a weight of 4. To normalize the distances, the resulting distance image is divided by 3. Since this normalization step takes some time, and one usually is interested in the relative distances of the points, the normalization can be suppressed with Metric = 'chamfer-3-4-unnormalized'. Finally, if Metric = 'euclidean', the computed distance is approximately Euclidean.

Execution Information
Multithreading type: reentrant (runs in parallel with non-exclusive operators).
Multithreading scope: global (may be called from any thread).
Processed without parallelization.
Parameters
Region (input_object)  region(-array) → object
Region for which the distance to the border is computed.

DistanceImage (output_object)  image → object (int4)
Image containing the distance information.

Metric (input_control)  string → (string)
Type of metric to be used for the distance transformation.

Default value: 'city-block'
List of values: 'chamfer-3-4', 'chamfer-3-4-unnormalized', 'chessboard', 'city-block', 'euclidean', 'octagonal'
Foreground (input_control)  string → (string)
Compute the distance for pixels inside ('true') or outside ('false') the input region.

Default value: 'true'
List of values: 'false', 'true'
Width (input_control)  extent.x → (integer)
Width of the output image.

Default value: 640

Suggested values: 160, 192, 320, 384, 640, 768

Typical range of values: 1 ≤ Width

Height (input_control)  extent.y → (integer)
Height of the output image.

Default value: 480

Suggested values: 120, 144, 240, 288, 480, 576
Typical range of values: 1 ≤ Height

  

看不懂沒關系,本文會以圖示分析該算法,直觀明了:
距離變換算法計算的是傳入該算法的每個不聯通的區域里的每個點到該區域邊緣的最近距離,計算方式常用的方式是
‘chamfer-3-4’, ‘chamfer-3-4-unnormalized’, ‘chessboard’, ‘city-block’, ‘euclidean’, ‘octagonal’
‘city-block’:水平垂直方向
‘chessboard’: 水平垂直方向+對角線四個方向
‘octagonal’: 正八邊形八個方向,如下圖:

 

 

 就是這畫紅線的八個方向。
關於算法的原理,如下:

 

 

 

比如說,這個不規則的多邊形是我傳入給算法的其中一個區域,
那么其中的紅點是我要計算的距離值,
顯而易見,這條最短距離如下:

 

 

 

那么,該最短距離就會傳給這個像素的值。
在實際運行中,該算法的工作效果如下:

 

 

 

 

 

 上面這些不同顏色的框框是傳進去的各個區域,連通域已被打散。
得出來的這些亮亮的點就是結果,最亮代表該點離邊緣的距離越大,反映在8位圖像上也就是最亮。
經過圖像格式轉換就會變成下面的樣子:

 

 

 

這就會為下面的聯通域的分水嶺的算法做出鋪墊。
下面開始講解分水嶺算法閾值分割:

watersheds_threshold (Operator)
Name
watersheds_threshold — Extract watershed basins from an image using a threshold.

Signature
watersheds_threshold(Image : Basins : Threshold : )

Description
The operator watersheds_threshold segments regions (basins) that are separated from each other by a watershed that has a height of at least Threshold.

In the first step, watersheds_threshold computes the watersheds without applying a threshold, resulting in the same basins that would be obtained when calling watersheds (for more details please refer to the description of watersheds). In the second step, the basins are successively merged if they are separated by a watershed that is smaller than Threshold. Let B1 and B2 be the minimum gray values of two neighboring basins and W the minimum gray value of the watershed that separates the two basins. The watershed is eliminated and the two basins are merged if
max{ W - B1 , W - B2 } < Threshold
The thus obtained basins are returned in Basins.

If Threshold is set to 0, watersheds_threshold is comparable to watersheds except that no watersheds but only expanded basins are returned. If Threshold is set to the maximum gray value range of Image then no two basins are separated by a watershed exceeding Threshold, and hence, Basins will contain only one region.
Execution Information
Multithreading type: reentrant (runs in parallel with non-exclusive operators).
Multithreading scope: global (may be called from any thread).
Processed without parallelization.
Parameters
Image (input_object)  singlechannelimage → object (byte / uint2 / real)
Image to be segmented.

Basins (output_object)  region-array → object
Segments found (dark basins).

Threshold (input_control)  number → (integer / real)
Threshold for the watersheds.

Default value: 10

Suggested values: 0, 5, 10, 20, 30, 50

Restriction: Threshold >= 0

看不懂沒關系,下面圖示講解:
那么字如其名,將圖像看成地理上的地形地貌,
該立體圖可以如下所示:

 

 

 

 

該立體圖對應的是那張經過距離變換的圖像:

 

 

分水嶺嘛,就是在峽谷最低哇處開口注水,然后地形地貌高聳的地方就會形成大壩,或者說是一條條脊。
詳細理論講解可以看該博客

圖像處理——分水嶺算法

https://blog.csdn.net/fengye2two/article/details/79116105
或者教材,《數字圖像處理》岡薩雷斯版
然后加上閾值分割:具體圖示如下:

 

 

算法的原文講解其實是和以上圖示是一樣的。
運行我的程序,
你就會看到,識別效果很完美。

————————————————
版權聲明:本文為CSDN博主「/我愛西紅柿炒雞蛋/」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/m0_47472749/article/details/120185047


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM