1,相关算子详解。

1.1,cooc_feature_image

         HALCON 中用于计算灰度共生矩阵(GLCM)并导出局部纹理特征的算子,适用于基于纹理的图像分析与检测。以下为详细解析:


算子功能

  • 核心作用
    基于输入区域和图像的灰度分布,计算指定方向和距离的灰度共生矩阵,并从中提取局部纹理特征(如能量、对比度等),生成与输入图像尺寸一致的特征图像‌。

  • 内部机制
    该算子等价于先调用 gen_cooc_matrix 生成灰度共生矩阵,再通过 cooc_feature_matrix 提取特征。若需多方向分析,直接调用这两个算子效率更高‌。


参数详解

输入参数

  1. Regions

    • 待分析的区域(ROI),仅处理该区域内的像素。

    • 注:算子忽略输入图像 Image 的域(Domain),仅依赖 Regions 定义的范围‌。

  2. Image

    • 输入的灰度图像,需为单通道图像。

  3. LdGray

    • 灰度层级数(1~8),默认 6。层级数减少可加速计算,但会降低精度‌。层级数指的是2的次方数例如默认值为6即2的6次方64,意思是将256级(0-255)灰度值简化为64级进行计算,减少计算量。

  4. Direction

    • 计算方向:可选 45°90°135°'mean'(四个方向的均值)‌。

输出参数

  • Energy‌(能量)
    反映灰度分布的均匀性,值高表示纹理变化平缓‌。

  • Correlation‌(相关性)
    表征像素间的线性依赖程度‌。

  • Homogeneity‌(同质性)
    描述局部灰度的一致性,值高表示纹理平滑‌。

  • Contrast‌(对比度)
    衡量灰度差异,值高表示纹理边缘清晰或突变明显‌。


应用场景

  1. 表面缺陷检测

    • 在 LCD 屏幕、金属表面等纹理复杂场景中,通过对比正常与缺陷区域的 ContrastEnergy 差异定位缺陷‌。

  2. 材质分类

    • 结合多纹理特征(如 EnergyHomogeneity)构建特征向量,用于木材种类识别或工业产品分类‌。

  3. 医学图像分析

    • 分析组织或细胞的纹理特征,辅助病理诊断。


使用示例

* 读取图像并定义 ROI 
read_image (Image, 'texture_sample.png') 
threshold (Image, Region, 128, 255)
 * 提取纹理特征图像(能量和对比度) 
cooc_feature_image (Region, Image, 6, 'mean', EnergyImage, CorrelationImage, HomogeneityImage, ContrastImage) 
* 分析特征图像中的异常区域 
threshold (ContrastImage, Defects, 50, 255)

注意事项

  • 性能优化

    • 减少 LdGray 层级可提升速度,但需权衡精度损失‌。

    • 多方向分析时,优先使用 gen_cooc_matrixcooc_feature_matrix 组合‌。

  • 区域选择

    • Regions 需精准覆盖目标纹理区域,避免背景干扰特征计算‌。

  • 并行支持

    • 支持多线程全局调用,适合实时处理或大尺寸图像分析‌。


相关算子

  • gen_cooc_matrix:生成灰度共生矩阵‌。

  • cooc_feature_matrix:直接输出特征值而非特征图像‌。

  • texture_laws:基于滤波器的纹理分析,适用于不同尺度特征提取‌。

1.2,gray_histo_abs

         HALCON 中用于计算图像区域绝对灰度直方图的算子,适用于分析特定区域内像素的灰度分布。以下为详细解析:


功能描述

  • 核心作用
    计算指定区域内图像的绝对灰度直方图,输出各灰度级的像素频数。直方图元组索引对应灰度值,元素值为该灰度值的出现次数‌。

  • gray_histo 的区别
    gray_histo 同时输出绝对和相对(百分比)直方图,而 gray_histo_abs 仅生成绝对频数直方图,适用于需要快速统计的场景‌。


参数详解

输入参数

  1. Regions

    • 待分析的区域(ROI),仅统计该区域内的像素灰度分布‌。

  2. Image

    • 输入的灰度图像,支持多种数据类型(如 byteint1int2 等)‌。

  3. Quantization

    • 量化参数,定义相邻灰度值的频率累加方式。例如,Quantization=2 表示将每两个相邻灰度值的频数合并统计‌。

输出参数

  • AbsoluteHisto

    • 绝对灰度直方图,元组长度为 256(对应 0~255 级灰度)。例如,索引 100 的值为 500,表示灰度值 100 的像素出现 500 次‌。


‌‌注意事项

  1. 灰度范围处理

    • 对于有符号图像(如 int1int2),灰度值会映射到索引 128 或 32768 起始的位置,需注意索引与灰度值的转换关系‌。

  2. 性能优化

    • 增大 Quantization 可减少直方图长度,提升计算效率,但会降低灰度分辨率‌。

  3. 区域选择

    • 确保 Regions 精确覆盖目标区域,避免无关像素干扰统计结果‌。

  4. AbsoluteHisto‌数组长度

    • 只要输入图像的‌灰度范围‌(例如byte格式的0-255) 和 ‌Quantization 参数‌均相同,则对应的AbsoluteHisto‌数组长度相同。

如下所示:

dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
datas:=[]
for Index := 1 to 15 by 1
    read_image (Image, 'clamp_sloped/clamp_sloped_'+Index$'02')
    *计算绝对灰度直方图的数组长度是否相同
    *Quantization=8:表示将8个相邻的灰度值合并计算,如此在深度为8位的图像中
    *AbsoluteHisto的长度=256级灰度值/Quantization(这里为:8)=32
    gray_histo_abs (Image, Image, 8, AbsoluteHisto)
    
    datas:=[datas,|AbsoluteHisto|]
    stop ()
endfor

素材截图:

运行效果:


‌ AbsoluteHisto的长度=256级灰度值/Quantization(这里为:8)=32

典型应用

  1. 图像质量评估
    通过直方图分析灰度分布均匀性,检测过曝或欠曝区域‌。

  2. 阈值分割
    结合 histo_to_thresh 算子,根据直方图自动确定最佳分割阈值‌。

  3. 特征提取
    统计特定灰度级占比,用于图像分类或缺陷检测‌。


1.3,create_class_mlp

        HALCON 中用于创建多层感知机(MLP)分类器的核心算子,支持分类与回归任务。以下为详细解析与使用指南:


1. 算子功能

  • 核心作用
    创建一个基于 MLP 的监督学习模型,支持图像分类、OCR 等任务。其结构包含输入层、单隐层和输出层,通过反向传播算法调整权重参数‌23。

  • 特点

    • 支持特征向量输入,兼容多种数据预处理方法(如归一化)‌28。

    • 输出层激活函数可配置,分类任务通常使用 'softmax',回归任务可选 'linear'‌23。


2. 参数详解

输入参数

参数名

描述

示例值

NumInput

输入层维度(特征向量长度)

3(RGB 三通道特征)‌8

NumHidden

隐层神经元数量

10(需根据数据复杂度调整)‌23

NumOutput

输出层维度(类别数或回归值个数)

5(5 分类任务)‌8

OutputFunction

输出层激活函数

'softmax'(分类)、'linear'(回归)‌23

Preprocessing

输入数据预处理类型

'normalization'(归一化)‌8

NumComponents

预处理后特征维度

10(需≤NumInput)‌2

RandSeed

随机种子(控制权重初始化)

42(保证结果可复现)‌8

输出参数

  • MLPHandle‌:MLP 分类器的句柄,用于后续训练和推理‌。


3. 应用场景

  • OCR 文字识别
    create_ocr_class_mlp 配合,识别字符图像‌13。

  • 工业缺陷分类
    输入表面纹理特征,分类正常/异常区域‌8。

  • 材质分类
    基于颜色或纹理特征,区分不同材质类型‌38。


4. 使用示例

* 创建 MLP 分类器(输入 3 维特征,隐层 10 节点,输出 5 类)
 create_class_mlp (3, 10, 5, 'softmax', 'normalization', 3, 42, MLPHandle) 
* 添加训练样本(假设 Image 为特征图,ClassRegions 为标签区域)
 add_samples_image_class_mlp (Image, ClassRegions, MLPHandle) 
* 训练模型(迭代 200 次,学习率 0.01) 
train_class_mlp (MLPHandle, 200, 0.01, 0.01, Error, ErrorLog)
 * 分类预测
 classify_image_class_mlp (Image, ResultRegions, MLPHandle, 0.5) 

5. 注意事项

  • 隐层设计
    隐层节点数需权衡模型复杂度与过拟合风险,通常通过交叉验证选择‌。

  • 数据预处理
    归一化('normalization')可加速训练收敛,避免数值溢出‌。

  • 训练参数调优
    学习率过高可能导致震荡,过低则收敛缓慢;建议结合 ErrorLog 监控训练过程‌。


‌2,应用。

* 原始案例:工业领域-木材-classify_wood.hdev
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files ('木板图片', ['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)
*木板材质
Classes := ['苹果树','梨树','柏树','枫树','松树']
FeaturesExtended:=[]
FeaturesExtended1:=[]

*--------------1,计算特征点数,用于后续模型创建使用--------------
read_image (Image, ImageFiles[0])
* Image Acquisition 01: Do something
dev_close_window()
get_image_size(Image, Width, Height)
dev_open_window(0, 0, Width, Height, 'black', WindowHandle)
dev_display(Image)
rgb1_to_gray(Image, GrayImage)   
threshold (GrayImage, Regions, 31, 254)
clip_region_rel (Regions, RegionClipped, 10, 10, 10, 30)
connection(RegionClipped, ConnectedRegions)
select_shape_std (ConnectedRegions, SelectedRegions, 'max_area', 0)
*LdGray:灰度层级数(1~8),默认 6,这里也为6。层级数减少可加速计算,但会降低精度‌。

*层级数指的






*层级数指的是2的次方数例如默认值为6即2的6次方64,意思是将256级(0-255)
*灰度值简化为64级进行计算,减少计算量。


*Energy(能量)反映灰度分布的均匀性,值高表示纹理变化平缓。
*Correlation(相关性)表征像素间的线性依赖程度。
*Homogeneity(同质性)描述局部灰度的一致性,值高表示纹理平滑。
*Contrast(对比度)衡量灰度差异,值高表示纹理边缘清晰或突变明显。
cooc_feature_image (Image, Image, 6, 90, Energy, Correlation, Homogeneity, Contrast)

sobel_amp (Image, EdgeAmplitude, 'sum_abs',3)
*AbsoluteHistoEdgeAmplitude:灰度图直方图绝对值
*注意:只要输入图像的‌灰度范围‌(例如byte格式的0-255) 和 ‌Quantization 参数‌均相同时*gr
*gr
*gray_histo_abs 输出的AbsoluteHisto 数据长度‌便相同
*如果只是推导特征数量可以省略图像预处理   
gray_histo_abs (EdgeAmplitude, EdgeAmplitude, 8, AbsoluteHistoEdgeAmplitude)
FeaturesExtended := [Energy,Correlation,Homogeneity,Contrast]
FeaturesExtended := [FeaturesExtended,AbsoluteHistoEdgeAmplitude]
*计算灰度共生矩阵获取局部纹理特征
cooc_feature_image (SelectedRegions, Image, 6, 90, Energy, Correlation, Homogeneity, Contrast)    
sobel_amp (Image, EdgeAmplitude, 'sum_abs', 3)
*输入图像的‌ ‌灰度范围‌ 和 ‌Quantization 参数‌ 均相同时,gray_histo_abs 输出的AbsoluteHisto 数据长度‌相同gray_
gray_
gray_histo_abs (EdgeAmplitude, EdgeAmplitude, 8, AbsoluteHistoEdgeAmplitude)
FeaturesExtended1 := [FeaturesExtended,Energy,Correlation,Homogeneity,Contrast]
FeaturesExtended1 := [FeaturesExtended1,AbsoluteHistoEdgeAmplitude]
*NumFeatures数组长度=(4(指的是:Energy,Correlation,Homogeneity,Contrast)+AbsoluteHistoEdgeAmplitude数组长度)*2
NumFeatures := |FeaturesExtended1|
NumClasses := |Classes|
NumHidden := 15

*-----------------2创建分类器------------------------------
*NumOutput:输出的数量,数量需与后续添加的样例数量一致
create_class_mlp (NumFeatures, 15, 5, 'softmax', 'normalization', 10, 42, MLPHandle)

*-----------------3添加样例---------------------------------
for i := 0 to |ImageFiles| - 1 by 1
    read_image (Image, ImageFiles[i])    
    rgb1_to_gray(Image, GrayImage)   
    threshold (GrayImage, Regions, 31, 254)
    clip_region_rel (Regions, RegionClipped, 10, 10, 10, 30)
    connection(RegionClipped, ConnectedRegions)        
    select_shape_std (ConnectedRegions, SelectedRegions, 'max_area', 0)
    cooc_feature_image (SelectedRegions, Image, 6, 90, Energy, Correlation, Homogeneity, Contrast)
    
    sobel_amp (Image, EdgeAmplitude, 'sum_abs', 3)
    gray_histo (EdgeAmplitude, EdgeAmplitude, AbsoluteHisto, RelativeHisto)
    gray_histo_abs (EdgeAmplitude, EdgeAmplitude, 8, AbsoluteHistoEdgeAmplitude)
    FeaturesExtended := [Energy,Correlation,Homogeneity,Contrast]
    FeaturesExtended := [FeaturesExtended,AbsoluteHistoEdgeAmplitude]
    cooc_feature_image (Image, Image, 6, 90, Energy, Correlation, Homogeneity, Contrast)    
    sobel_amp (Image, EdgeAmplitude, 'sum_abs', 3)
    *输入图像的‌ ‌灰度范围‌ 和 ‌Quantization 参数‌ 均相同时,gray_histo_abs 输出的                     
    
    
    *AbsoluteHisto 数据长度‌相同   
    
    gray_histo_abs (EdgeAmplitude, EdgeAmplitude, 8, AbsoluteHistoEdgeAmplitude)
    FeaturesExtended1 := [FeaturesExtended,Energy,Correlation,Homogeneity,Contrast]
    FeaturesExtended1 := [FeaturesExtended1,AbsoluteHistoEdgeAmplitude]
    FeatureVector := real(FeaturesExtended1)
    *3添加样本
    * Image Acquisition 01: Code generated by Image Acquisition 01
    
    add_sample_class_mlp (MLPHandle, FeatureVector, i)
endfor

*------------------4训练分类器---------------------------
train_class_mlp (MLPHandle, 200, 1, 0.0001, Error, ErrorLog)
stop()
write_class_mlp(MLPHandle, '1.gmc')

*-----------------5应用分类器进行识别------------------------

for i := |ImageFiles| - 1 to 0 by -1
    read_image (Image, ImageFiles[i])
    rgb1_to_gray(Image, GrayImage)
    
    threshold (GrayImage, Regions, 31, 254)
    *这里和前面添加样例一样,如此其实可以封装成一个方法
    clip_region_rel (Regions, RegionClipped, 10, 10, 10, 30)
    connection(RegionClipped, ConnectedRegions)        
    select_shape_std (ConnectedRegions, SelectedRegions, 'max_area', 0)
    cooc_feature_image (SelectedRegions, Image, 6, 90, Energy, Correlation, Homogeneity, Contrast)
    
    sobel_amp (Image, EdgeAmplitude, 'sum_abs', 3)
    gray_histo_abs (EdgeAmplitude, EdgeAmplitude, 8, AbsoluteHistoEdgeAmplitude)
    FeaturesExtended := [Energy,Correlation,Homogeneity,Contrast]
    FeaturesExtended := [FeaturesExtended,AbsoluteHistoEdgeAmplitude]
    cooc_feature_image (Image, Image, 6, 90, Energy, Correlation, Homogeneity, Contrast)
    
    sobel_amp (Image, EdgeAmplitude, 'sum_abs', 3)
    gray_histo_abs (EdgeAmplitude, EdgeAmplitude, 8, AbsoluteHistoEdgeAmplitude)
    FeaturesExtended1 := [FeaturesExtended,Energy,Correlation,Homogeneity,Contrast]
    FeaturesExtended1 := [FeaturesExtended1,AbsoluteHistoEdgeAmplitude]
    *计算出当前图像的特征点
    FeatureVector := real(FeaturesExtended1)
    *识别
    * FoundClassIDs:查找到的target,Confidence查找的target评分,其数量由num设置这里为2
    classify_class_mlp (MLPHandle, FeatureVector, 2, FoundClassIDs, k)
    dev_display(Image)
    result:= 'found class:   ' + Classes[FoundClassIDs[0]]
    disp_message(WindowHandle, result, 'image', 12, 12, 'black', 'true')
    stop()
endfor
clear_class_mlp (MLPHandle)


Halcon官方相应案例

* 案例:工业领域-木材-classify_wood.hdev
* The object of this example is to classify different
* kinds of wood according to their surface texture.
* 特征量是由原图与1/4原图的灰度共生矩阵的四个值、灰度直方图绝对值构成
file_exists ('classify_wood.gmc', FileExists)
if (FileExists)
    USE_STORED_CLASSIFIER := 1
else
    USE_STORED_CLASSIFIER := 0
endif
* First, the path to the images is set, the initial image
* is read and the settings are specified.
get_system ('image_dir', HalconImages)
get_system ('operating_system', OS)
if (OS{0:2} == 'Win')
    tuple_split (HalconImages, ';', HalconImages)
else
    tuple_split (HalconImages, ':', HalconImages)
endif
ImagePath := '/wood/'
ReadOK := false
dev_get_preferences ('suppress_handled_exceptions_dlg', SaveMode)
dev_set_preferences ('suppress_handled_exceptions_dlg', 'true')
for k := 0 to |HalconImages| - 1 by 1
    try
        read_image (Image, HalconImages[k] + ImagePath + 'apple/apple_01')
        ReadPath := HalconImages[k] + ImagePath
        ReadOK := true
        break
    catch (Exception)
    endtry
endfor
if (not ReadOK)
    disp_message (WindowID, 'Could not find the images in $HALCONIMAGES', 'window', -1, -1, 'black', 'true')
    stop ()
endif
dev_set_preferences ('suppress_handled_exceptions_dlg', SaveMode)
read_image (Image, ImagePath + 'apple/apple_01')
get_image_pointer1 (Image, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, Width, Height, WindowID)
set_display_font (WindowID, 22, 'mono', 'true', 'false')
dev_display (Image)
dev_update_off ()
* Now the different wood classes are specified.
Classes := ['apple','beech','cherry','maple','oak','walnut']
* The program uses by default a stored classifier. If you, however,
* want to perform the training, set USE_STORED_CLASSIFIER to 0.
* If the classifier can not be found, USE_STORED_CLASSIFIER
* is set to 0 automatically.
if (USE_STORED_CLASSIFIER == 1)
    read_class_mlp ('classify_wood.gmc', MLPHandle)
    NumClasses := |Classes|
else
    * 本地函数:生成特征量,这里共生成72个特征量
    gen_features (Image, FeatureVector)
    NumFeatures := |FeatureVector|
    NumClasses := |Classes|
    NumHidden := 15
    create_class_mlp (NumFeatures, NumHidden, NumClasses, 'softmax', 'normalization', 10, 42, MLPHandle)
    for CorrectClassID := 0 to NumClasses - 1 by 1
        list_files (ReadPath + Classes[CorrectClassID], 'files', Files)
        for k := 0 to |Files| - 1 by 2
            read_image (Image, Files[k])
            dev_display (Image)
            gen_features (Image, FeatureVector)
            add_sample_class_mlp (MLPHandle, FeatureVector, CorrectClassID)
        endfor
    endfor
    train_class_mlp (MLPHandle, 200, 1, 0.0001, Error, ErrorLog)
    write_class_mlp (MLPHandle, 'classify_wood.gmc')
    disp_message (WindowID, 'Training of wood textures completed\nPress \'Run\' to continue', 'window', -1, -1, 'black', 'true')
    stop ()
endif
Errors := 0
Count := 0
for CorrectClassID := 0 to NumClasses - 1 by 1
    list_files (ReadPath + Classes[CorrectClassID], 'files', Files)
    for k := 0 to |Files| - 1 by 1
        Count := Count + 1
        read_image (Image, Files[k])
        gen_features (Image, FeatureVector)
        * FoundClassIDs:查找到的target,Confidence查找的target评分,其数量由num设置这里为2
        classify_class_mlp (MLPHandle, FeatureVector, 2, FoundClassIDs, Confidence)
        dev_display (Image)
        dev_set_color ('blue')
        disp_message (WindowID, 'correct class: ' + Classes[CorrectClassID], 'window', 24, 12, 'black', 'true')
        if (CorrectClassID != FoundClassIDs[0])
            dev_set_color ('red')
            set_tposition (WindowID, 55, 12)
            write_string (WindowID, 'found class:   ' + Classes[FoundClassIDs[0]])
            Errors := Errors + 1
            disp_continue_message (WindowID, 'black', 'true')
            stop ()
        endif
        wait_seconds (0.1)
    endfor
endfor
ErrorRate := real(Errors) / Count * 100.0
clear_class_mlp (MLPHandle)

本地函数

gen_features(Image:::FeatureVector)

* 本地函数:gen_features(Image:::FeatureVector)
FeatureVector := []
* Compute features.
gen_sobel_features (Image, FeatureVector, FeatureVector)
* Downscale the image (image pyramid) and compute features.
zoom_image_factor (Image, Zoomed1, 0.5, 0.5, 'constant')
gen_sobel_features (Zoomed1, FeatureVector, FeatureVector)
* Uncomment lines to use further pyramid levels:
zoom_image_factor (Zoomed1, Zoomed2, 0.5, 0.5, 'constant')
* gen_sobel_features (Zoomed2, FeatureVector, FeatureVector)
* zoom_image_factor (Zoomed2, Zoomed3, 0.5, 0.5, 'constant')
* gen_sobel_features (Zoomed3, FeatureVector, FeatureVector)
* zoom_image_factor (Zoomed3, Zoomed4, 0.5, 0.5, 'constant')
* gen_sobel_features (Zoomed4, FeatureVector, FeatureVector)
FeatureVector := real(FeatureVector)
return ()

* 本地函数:gen_sobel_features(Image::Features:FeaturesExtended)

* 本地函数:gen_sobel_features(Image::Features:FeaturesExtended)
* Coocurrence matrix for 0 deg and 90 deg:
* 计算灰度共生矩阵
cooc_feature_image (Image, Image, 6, 0, Energy, Correlation, Homogeneity, Contrast)
cooc_feature_image (Image, Image, 6, 90, Energy, Correlation, Homogeneity, Contrast)
* Absolute histogram of edge amplitudes:
sobel_amp (Image, EdgeAmplitude, 'sum_abs', 3)
* 计算灰度直方图绝对值
* 8:表示连续的8个灰度值级合并计算为一个,故这里计算得到的
* AbsoluteHistoEdgeAmplitude==32==256/8
gray_histo_abs (EdgeAmplitude, EdgeAmplitude, 8, AbsoluteHistoEdgeAmplitude)
* Entropy and anisotropy:
* entropy_gray (Image, Image, Entropy, Anisotropy)
* Absolute histogram of gray values:
* gray_histo_abs (Image, Image, 8, AbsoluteHistoImage)
* Add features to feature vector:
FeaturesExtended := [Features,Energy,Correlation,Homogeneity,Contrast]
FeaturesExtended := [FeaturesExtended,AbsoluteHistoEdgeAmplitude]
* FeaturesExtended := [FeaturesExtended,Entropy,Anisotropy]
* FeaturesExtended := [FeaturesExtended,AbsoluteHistoImage]
return ()

效果

3,Demo链接。

https://download.csdn.net/download/lingxiao16888/90498453

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐