HALCON示例程序check_blister_mixed.hedv药品胶囊缺陷检测

本文详细介绍HALCON示例程序check_blister_mixed.hedv,该程序利用高斯混合模型(GMM)对药品胶囊进行缺陷检测。通过提取胶囊、分割连通域、筛选区域并进行颜色空间分析,实现对不同颜色胶囊的识别与分类。最终,通过对比训练数据与检测结果,判断胶囊的缺失、错误类型及数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HALCON示例程序check_blister_mixed.hedv药品胶囊缺陷检测

示例程序源码(加注释)

  • 读入图片与显示相关设置
    dev_close_window ()
    read_image (Image, ‘blister/blister_mixed_reference’)
    dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
    set_display_font (WindowHandle, 14, ‘mono’, ‘true’, ‘false’)
    dev_update_off ()
    dev_display (Image)
    dev_set_draw (‘margin’)
  • 首先提取每个胶囊
    disp_message (WindowHandle, ‘Train gmm classifier on pill types’, ‘window’, -1, -1, ‘black’, ‘true’)
  • 注意注意敲黑板,划重点。下边的这个函数是halcon函数的封装,里边代码有好多。内容是上一篇文章介绍过,大同小异,所以不理解的话看一下上一篇例子。下边的代码块是extract_pill_types里边的内容。
    extract_pill_types (Image, Chambers, ChambersUnion, Classes, PhiRef, RowRef, ColumnRef, PillTypeCount)
threshold (Image, Region, 90, 255)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 5000, 999999)
shape_trans (SelectedRegions, Blister, 'convex')
gen_empty_region (Chambers)
for I := 0 to 4 by 1
    Row := 107 + I * 70
    for J := 0 to 2 by 1
        Column := 177 + J * 150
        gen_rectangle2 (Rectangle, Row, Column, 0, 64, 30)
        concat_obj (Chambers, Rectangle, Chambers)
    endfor
endfor
difference (Blister, Chambers, Pattern)
union1 (Chambers, ChambersUnion)
orientation_region (Blister, PhiRef)
PhiRef := rad(180) + PhiRef
area_center (Blister, Area, RowRef, ColumnRef)

*  +++ Extract pattern for classification +++
select_shape (Chambers, PillType1, 'row', 'and', 1, 145)
union1 (PillType1, PillType1)
select_shape (Chambers, PillType2, 'row', 'and', 145, 270)
union1 (PillType2, PillType2)
select_shape (Chambers, PillType3, 'row', 'and', 270, 390)
union1 (PillType3, PillType3)

* Extract color space of yellow pills
reduce_domain (Image, PillType1, ImageReduced)
decompose3 (ImageReduced, ImageR, ImageG, ImageB)
threshold (ImageB, Region, 60, 95)

* Extract color space of red pills
reduce_domain (Image, PillType2, ImageReduced)
decompose3 (ImageReduced, ImageR, ImageG, ImageB)
* invert_image反转图像的灰度值
invert_image (ImageB, ImageInvert)
* hysteresis_threshold使用迟滞阈值操作
* 函数原型:hysteresis_threshold(Image : RegionHysteresis : Low, High, MaxLength : )
* Image :输入图像;RegionHysteresis :输出区域;Low:低于这个灰度不会被选中;High:高于这个灰度立刻被选中;
* MaxLength :在Low与High之间的根据MaxLength 对比度进行选择,和carry边缘类似。
hysteresis_threshold (ImageInvert, RegionHysteresis2, 190, 200, 5)

* Extract color space of green pills
reduce_domain (Image, PillType3, ImageReduced)
decompose3 (ImageReduced, ImageR, ImageG, ImageB)
invert_image (ImageB, ImageInvert)
hysteresis_threshold (ImageInvert, RegionHysteresis3, 180, 200, 10)
 
 * 求两个区域的交集
intersection (Region, PillType1, PillType1)
intersection (RegionHysteresis2, PillType2, PillType2)
PillTypeCount := [3,6,6]
intersection (RegionHysteresis3, PillType3, PillType3)
concat_obj (PillType1, PillType2, Classes)
concat_obj (Classes, PillType3, Classes)
return ()

NumClasses := |PillTypeCount|

  • 创建创建高斯混合模型

  • 输入参数: NumDim:几个特征;NumClasses:样本分类个数;NumCenters:类中心的个数;CovarType:

  • 协方差矩阵(‘Spherical’,‘diag’,‘full’);Preprocessing:预处理是否使用,及特征向量转换类型;

  • NumComponents:预处理参数,转换特征数;RandSend:迭代次数,初始化GMM;

  • 输出参数:GMMHandle:高斯混合模型
    create_class_gmm (3, 3, [1,5], ‘spherical’, ‘normalization’, 10, 42, GMMHandle)

  • 含义:增加训练样本(图片区),放入GMM 进行训练数据

  • 输入参数:Image:训练的图像(多通道);ClassRegions:图像中用于训练的类区域;

  • GMMHandle:高斯混合模型;Randomize:高斯噪声标准差
    add_samples_image_class_gmm (Image, Classes, GMMHandle, 0)

  • 含义:训练高斯混合模型

  • 输入参数:GMMHandle:高斯混合模型;MixIter: 期望最大值算法中迭代最大数;

  • Threshold:期望误差阈值,超过此值,计算取消;

  • ClassPriors:类的先验概率类型;(‘training’,‘uniform’)'uniform’表示使用相同的权重,1/NumClasses;'training’表示类发生的概率是依据样本中的概率推断。

  • Regularize:调整值,为了防止计算中出现奇异协方差矩阵。增加到协方差矩阵的对角线上的一个很小的值

  • 输出参数:Centers:每个类的中心个数

  • Iter:每个类的迭代次数
    train_class_gmm (GMMHandle, 100, 0.001, ‘training’, 0.0001, Centers, Iter)

  • 检测胶囊
    Count := 12
    for FileIndex := 1 to Count by 1

    • 读入图片
      read_image (Image, ‘blister/blister_mixed_’ + FileIndex$‘02’)
    • 阈值分割
      threshold (Image, Region, 90, 255)
    • 分割连通域
      connection (Region, ConnectedRegions)
    • 面积对区域筛选
      select_shape (ConnectedRegions, SelectedRegions, ‘area’, ‘and’, 5000, 9999999)
    • 求取最大区域边缘
      shape_trans (SelectedRegions, RegionTrans, ‘convex’)
    • 利用椭圆变换,得出区域角度
      orientation_region (RegionTrans, Phi)
      if (abs(Phi) > rad(90))
      Phi := rad(180) + Phi
      endif
    • 求取区域面积与中心坐标
      area_center (RegionTrans, Area1, Row, Column)
    • 创建平移旋转变换矩阵
      vector_angle_to_rigid (Row, Column, Phi, RowRef, ColumnRef, PhiRef, HomMat2D)
    • 使用仿射变换矩阵进行任意仿射变换
      affine_trans_image (Image, ImageAffinTrans, HomMat2D, ‘constant’, ‘false’)
    • 减少图像定义域
      reduce_domain (ImageAffinTrans, ChambersUnion, ImageReduced)
    • 将图片分为rgb三通道图像
      decompose3 (ImageAffinTrans, ImageR, ImageG, ImageB)
    • 对每个胶囊进行识别检测
    • 含义:使用GMM分类一个图像
    • 输入参数:Image:训练的图像(多通道);GMMHandle:GMM模型;
    • RejectionThreshold:分类拒绝阈值,如果图像所有的像素概率低于此值将不会分类任何类。
    • 输出参数:ClassRegions:分类的各个区域
      classify_image_class_gmm (ImageReduced, ClassRegions, GMMHandle, 0.005)
    • 对ClassRegions进行计数
      count_obj (ClassRegions, Number)
    • 生成空区域
      gen_empty_obj (FinalClasses)
    • 分割连通域
      connection (Chambers, ChambersRemaining)
      for Index := Number to 1 by -1
      dev_clear_window ()
      • 选择ClassRegions区域中的第Index个对象
        select_obj (ClassRegions, Region, Index)
      • 求交集
        intersection (ChambersRemaining, Region, Region)
      • 使用面积与宽度进行区域筛选
        select_shape (Region, PillsOfOneType, [‘area’,‘width’], ‘and’, [200,40], [3000,68])
      • 求取两个区域的差集
        difference (ChambersUnion, PillsOfOneType, RegionDifference)
      • 分割连通域
        connection (RegionDifference, ConnectedRegions)
      • 使用面积进行区域筛选
        select_shape (ConnectedRegions, SelectedRegions, ‘area’, ‘and’, 0, 7868)
      • 求取区域的最大边缘
        shape_trans (SelectedRegions, SelectedRegions, ‘convex’)
      • 联合区域
        union1 (SelectedRegions, SelectedRegions)
      • 求取区域差集
        difference (ChambersRemaining, SelectedRegions, ChambersRemaining)
      • 联合两个区域
        concat_obj (SelectedRegions, FinalClasses, FinalClasses)
        endfor
    • 得出结果进行处理得出结论
      gen_empty_obj (MissingPills)
      gen_empty_obj (WrongPills)
      gen_empty_obj (WrongNumberOfPills)
      difference (ChambersUnion, FinalClasses, LeftOvers)
      area_center (LeftOvers, Area, Row1, Column1)
      if (Area > 0)
      connection (LeftOvers, LeftOvers)
      count_obj (LeftOvers, Number)
      for Index := 1 to Number by 1
      select_obj (LeftOvers, ObjectSelected, Index)
      intensity (ObjectSelected, ImageB, Mean, Deviation)
      if (Deviation > 40)
      concat_obj (WrongPills, ObjectSelected, WrongPills)
      else
      concat_obj (MissingPills, ObjectSelected, MissingPills)
      endif
      endfor
      endif
    • Compute histogram
      CountFinalClass := []
      for Index := 1 to NumClasses by 1
      select_obj (FinalClasses, ObjectSelected, Index)
      connection (ObjectSelected, ObjectSelected)
      count_obj (ObjectSelected, Size)
      CountFinalClass := [CountFinalClass,Size]
      endfor
    • Display classification results and output allover statistic
      display_results (ImageAffinTrans, LeftOvers, FinalClasses, WrongPills, CountFinalClass, PillTypeCount, WindowHandle)
      if (FileIndex < Count)
      disp_continue_message (WindowHandle, ‘black’, ‘true’)
      endif
      stop ()
      endfor
  • Clear classifier handle
    clear_class_gmm (GMMHandle)

处理思路

此例子使用GMM高斯分类器进行胶囊识别识别,因为一版药上有多个种类的药片。

后记

大家有什么问题可以向我提问哈,我看到了第一时间回复,希望在学习的路上多多结交良师益友。

<think>好的,用户的问题是想将Halcon的detect_indent_fft.hdev示例程序转换为OpenCV C++实现,需要FFT检测的转换教程和示例代码。首先,我得回忆一下Halcon的这个示例是做什么的。根据提供的引用,这个示例使用快速傅里叶变换(FFT)来检测图像中的周期性缺陷,比如表面压痕。Halcon中的步骤可能包括图像预处理、FFT变换、频域滤波、逆变换以及缺陷分析。 接下来,我需要考虑OpenCV中对应的功能。OpenCV的FFT函数在C++中主要通过dft()函数实现,但使用时需要注意通道和复数矩阵的处理。用户提到的Halcon示例可能包含以下步骤:读取图像、转换为频域、滤波处理、逆变换回空间域,然后进行后处理分析。 首先,图像预处理部分可能需要高斯模糊来减少噪声,这在OpenCV中可以用GaussianBlur()。然后进行FFT变换,需要将图像扩展到适合的尺寸(通常是2的幂次,但OpenCV会自动处理,不过最好手动优化),转换到浮点类型,并进行频域变换。这里需要注意,Halcon的rft_generic可能生成实部虚部分开的图像,而OpenCV的dft()会生成复数矩阵,可能需要处理为双通道(实部和虚部)。 频域处理部分,Halcon示例可能创建高斯滤波器来抑制低频成分,突出缺陷。在OpenCV中需要构造类似的滤波器,可能是一个高斯带通或高通滤波器。然后将频域图像与滤波器相乘,这里涉及到复数乘法,需要注意频域的中心化(即移位后的频域,低频在中心)。 逆变换后,需要将结果转换回空间域,取绝对值并归一化,然后进行阈值处理或其他分析。例如,计算梯度或寻找最大最小值来确定缺陷位置。 还需要考虑Halcon中的优化选项,比如optimize_rft_speed,可能涉及图像补零或金字塔处理来加速FFT。在OpenCV中,可能需要手动调整图像尺寸到最优(如接近2的幂次)以提高计算效率。 此外,用户提供的引用中提到优化结果受硬件影响,所以在C++实现时要注意多线程或硬件加速选项,但OpenCV默认可能已经优化了这些部分。 现在,将这些步骤转化为代码。首先读取图像,转换为灰度,高斯模糊。然后扩展图像到最佳尺寸(可以用getOptimalDFTSize()),创建复数矩阵,进行dft。接着生成高斯带通滤波器,中心在频域中心,进行乘法。然后逆变换,处理结果,寻找缺陷区域。 可能的难点在于滤波器的构造,需要根据具体缺陷调整参数,比如高斯的标准差。此外,结果的后处理可能需要形态学操作或阈值处理来突出缺陷。 最后,测试代码时需要调整参数,比如高斯滤波器的半径,频域处理的阈值,以及后处理步骤,确保检测效果接近Halcon示例。</think>以下是将Halcon的`detect_indent_fft.hdev`转换为OpenCV C++实现的核心步骤与示例代码: --- ### 关键步骤解析 1. **图像预处理** - 高斯模糊消除高频噪声 - 转换为单通道灰度图 $$ \text{预处理公式:} I_{blur} = G_{\sigma} * I_{original} $$ (其中$G_{\sigma}$表示高斯核)[^2] 2. **频域变换** - 扩展图像至最优FFT尺寸(OpenCV自动优化) - 执行FFT并中心化低频分量 $$ \text{FFT移位公式:} F_{shift}(u,v) = (-1)^{u+v} \cdot F(u,v) $$ 3. **频域滤波** - 构建高斯带通滤波器抑制低频/高频干扰 $$ H(u,v) = e^{-\frac{D^2(u,v)}{2\sigma^2}} \quad (D为到中心的距离) $$ 4. **缺陷检测** - 逆FFT重建空间域图像 - 通过梯度计算增强缺陷特征 $$ \text{梯度幅值:} |\nabla I| = \sqrt{(\frac{\partial I}{\partial x})^2 + (\frac{\partial I}{\partial y})^2} $$ --- ### OpenCV C++ 实现代码 ```cpp #include <opencv2/opencv.hpp> cv::Mat detect_indent_fft(const cv::Mat& input) { // 1. 图像预处理 cv::Mat gray, blurred; cv::cvtColor(input, gray, cv::COLOR_BGR2GRAY); cv::GaussianBlur(gray, blurred, cv::Size(5,5), 0.8); // 2. 优化FFT尺寸 int opt_rows = cv::getOptimalDFTSize(blurred.rows); int opt_cols = cv::getOptimalDFTSize(blurred.cols); cv::Mat padded; cv::copyMakeBorder(blurred, padded, 0, opt_rows - blurred.rows, 0, opt_cols - blurred.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0)); // 3. 执行FFT cv::Mat planes[] = {cv::Mat_<float>(padded), cv::Mat::zeros(padded.size(), CV_32F)}; cv::Mat complexImg; cv::merge(planes, 2, complexImg); cv::dft(complexImg, complexImg, cv::DFT_COMPLEX_OUTPUT); // 4. 构建高斯带通滤波器(示例参数) cv::Mat filter = cv::Mat::zeros(padded.size(), CV_32FC2); float D0 = 30.0f, sigma = 15.0f; cv::Point center(padded.cols/2, padded.rows/2); for(int i=0; i<padded.rows; ++i) { for(int j=0; j<padded.cols; ++j) { float D = cv::norm(cv::Point(j,i) - center); float val = exp(-(D*D - D0*D0)*(D*D - D0*D0)/(2*sigma*sigma*sigma*sigma)); filter.at<cv::Vec2f>(i,j) = cv::Vec2f(val, val); } } // 5. 频域滤波 cv::mulSpectrums(complexImg, filter, complexImg, 0); // 6. 逆FFT cv::idft(complexImg, complexImg, cv::DFT_SCALE | cv::DFT_REAL_OUTPUT); cv::Mat result; cv::split(complexImg, planes); cv::magnitude(planes[0], planes[1], result); cv::normalize(result, result, 0, 1, cv::NORM_MINMAX); // 7. 缺陷增强 cv::Mat grad_x, grad_y; cv::Sobel(result, grad_x, CV_32F, 1, 0); cv::Sobel(result, grad_y, CV_32F, 0, 1); cv::magnitude(grad_x, grad_y, result); return result; } ``` --- ### 参数调优建议 1. **高斯模糊参数**:$\sigma$值影响噪声抑制效果,建议范围0.5-1.5 2. **带通滤波器参数**: - $D_0$控制中心抑制区域半径(典型值:图像短边尺寸的5%-20%) - $\sigma$决定过渡带宽度(建议$\sigma = D_0/3$)[^2] 3. **后处理优化**:可增加形态学操作或动态阈值处理增强缺陷特征 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值