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

(悬赏)HALCON 多线程并发使用 FindScaledShapeModel

[复制链接]
jacktl 发表于 2024-11-10 10:34:18 | 显示全部楼层 |阅读模式
HALCON.  配合C++,为了在处理大量图片的定位时,节约时间。因此将大量图片放在多线程中同步执行,但是目前测试发现HACLON中我使用的查找模板算子,导致线程之间互斥了,窝查了下Halcon我使用的相关算子属于:Reentrant (可重入,适合并行处理,允许多线程)。
跪寻大神有偿解答,百度谷歌各种都试过了。。。代码也各种屏蔽测试。。
之前都没有使用过多线程并发进行,这次准备提速,测试了下多线程同时进行模板匹配突然遇到这个问题。。。。搞了我好几天了,目前我可以确定肯定不是我线程的问题,问题肯定出在HALCON的算子执行上。
其中
1、每个线程中使用的图片都是我单独复制的图片
2、每个线程中使用的模版也都是我读取本地100多个模板文件(为了排除这方面的原因,特意将模板文件复制了100分)

HALCON对于算子的介绍

find_scaled_shape_model (Operator)
Name
find_scaled_shape_model — Find the best matches of an isotropically scaled shape model in an image.
Parallelization
Multithreading type: reentrant (runs in parallel with non-exclusive operators).
Multithreading scope: global (may be called from any thread).
Automatically parallelized on internal data level.

希望哪位大神是否可以指点一二,一旦完美解决微信红包:500RMB  小小意思

2024-11-10_104844.jpg


  1. std::vector<HObject> WnLibOfFindScaleShapeModel::apply(const std::vector<HObject>& inputs, bool& error, std::string& errMsg,
  2.                                                   const HTuple dataDictionary)
  3. {
  4.         // Local iconic variables

  5.         HObject ho_ImageReduced, ho_ModelContours, ho_Cross;

  6.         // Local control variables
  7.         HTuple hv_windowHandle, hv_FindScaleShapeModelParam;
  8.         HTuple hv_HomMat2D_Read, hv_ModelID;
  9.         HTuple hv_ErrCode, hv_Number;
  10.         HTuple hv_ActualRow, hv_ActualColumn, hv_Angle, hv_Scale;
  11.         HTuple hv_Score, hv_HomMat2D, hv_MovementOfObject;
  12.         HTuple hv_deltaAngle, hv_CenterData;


  13.         //Matching 01: Find the model
  14.         HTuple hv_FindScore;
  15.         HTuple hv_ReturnCode;
  16.         HObject ho_TransContours;
  17.         HObject ho_RegionAffineTrans;
  18.         GenEmptyObj(&(ho_TransContours));
  19.         GenEmptyObj(&(ho_RegionAffineTrans));
  20.         error = false;
  21.         errMsg = "";




  22.         const HTuple hv_DataDictionary = dataDictionary;
  23.         try
  24.         {
  25.                 GetMessageTuple(hv_DataDictionary, "ErrCode", &hv_ErrCode);
  26.                 hv_ReturnCode = hv_ErrCode;
  27.                 //判断上一个过程是否正常
  28.                 if (0 != (hv_ErrCode < 0))
  29.                 {
  30.                         return { ho_TransContours, ho_RegionAffineTrans };
  31.                 }

  32.                 //上一步执行正常,方可执行下面步骤
  33.            //************************************获取输入参数************************************
  34.                 const HObject image = inputs[0];
  35.                 const HObject ho_RoiRegion = inputs[1];
  36.                 const HObject ho_ShapeModelRegion = inputs[2];

  37.                 //读取参数
  38.                 GetMessageTuple(hv_DataDictionary, "WindowHandle", &hv_windowHandle);
  39.                 GetMessageTuple(hv_DataDictionary, "FindScaleShapeModelParam", &hv_FindScaleShapeModelParam);
  40.                 GetMessageTuple(hv_DataDictionary, "HomMat2D_Read", &hv_HomMat2D_Read);
  41.                 GetMessageTuple(hv_DataDictionary, "ScaleShapeModeID", &hv_ModelID);

  42.                 int modeIIII = hv_ModelID.I();


  43.                 HTuple hv_WindowHandle = hv_windowHandle[0];
  44.                 const HTuple hv_AngleStart = hv_FindScaleShapeModelParam[0];
  45.                 const HTuple hv_AngleExtent = hv_FindScaleShapeModelParam[1];
  46.                 const HTuple hv_ScaleMin = hv_FindScaleShapeModelParam[2];
  47.                 const HTuple hv_ScaleMax = hv_FindScaleShapeModelParam[3];
  48.                 const HTuple hv_ScoreMin = hv_FindScaleShapeModelParam[4];
  49.                 const HTuple hv_ValidScore = hv_FindScaleShapeModelParam[5];


  50.                 CountObj(ho_RoiRegion, &hv_Number);
  51.                 if (0 != (hv_Number > 0))
  52.                 {
  53.                         ReduceDomain(image, ho_RoiRegion, &ho_ImageReduced);
  54.                 }
  55.                 else
  56.                 {
  57.                         CropDomain(image, &ho_ImageReduced);
  58.                 }

  59.                 //HTuple        m_ParamPathIndex = "01";
  60.                 //HTuple        m_MatchType = "形状";
  61.                 //HTuple        m_ParamPath = ".\\HalconObject\\芯片\\定位相机\\2024071118295566\";
  62.                 //HTuple        m_FullParamPath = m_ParamPath + m_MatchType + "\";
  63.                 //const HTuple hv_ModelPath = m_FullParamPath + "匹配模板" + "01" + ".shm";
  64.                 //ReadShapeModel(hv_ModelPath, &hv_ModelID);

  65.                 //auto start = std::chrono::high_resolution_clock::now();
  66.                 //// 将时间点转换为时间戳(以纳秒为单位)
  67.                 //auto startTime = std::chrono::duration_cast<std::chrono::nanoseconds>(start.time_since_epoch()).count();

  68.                 //设置查询超时
  69.                 //SetShapeModelParam(hv_ModelID, "timeout", 3000);
  70.                 FindScaledShapeModel(ho_ImageReduced, hv_ModelID, hv_AngleStart, hv_AngleExtent,
  71.                                      hv_ScaleMin, hv_ScaleMax, hv_ScoreMin, 1, 0.5, "least_squares", 0, 0.1, &hv_ActualRow,
  72.                                      &hv_ActualColumn, &hv_Angle, &hv_Scale, &hv_Score);

  73.                

  74.                 //auto end = std::chrono::high_resolution_clock::now();
  75.                 //// 将时间点转换为时间戳(以纳秒为单位)
  76.                 //auto endTime = std::chrono::duration_cast<std::chrono::nanoseconds>(end.time_since_epoch()).count();

  77.                 //std::cout << "匹配开始时间:"<< startTime <<"          结束时间:"<< endTime << std::endl;
  78.                 //std::this_thread::sleep_for(std::chrono::milliseconds(100));

  79.                  
  80.         

  81.                 //hv_ActualRow = hv_ActualRow;
  82.                 //hv_ActualColumn = hv_ActualColumn;
  83.                 //const HTuple hv_ActualAngel = hv_Angle;
  84.                 //GetShapeModelContours(&ho_ModelContours, hv_ModelID, 1);
  85.                 //{
  86.                 //        const HTuple end_val54 = (hv_Score.TupleLength()) - 1;
  87.                 //        const HTuple step_val54 = 1;
  88.                 //        for (HTuple hv_I = 0; hv_I.Continue(end_val54, step_val54); hv_I += step_val54)
  89.                 //        {
  90.                 //                HomMat2dIdentity(&hv_HomMat2D);
  91.                 //                HomMat2dRotate(hv_HomMat2D, hv_ActualAngel, 0, 0, &hv_HomMat2D);
  92.                 //                HomMat2dTranslate(hv_HomMat2D, hv_ActualRow, hv_ActualColumn, &hv_HomMat2D);
  93.                 //                AffineTransContourXld(ho_ModelContours, &(ho_TransContours), hv_HomMat2D);
  94.                 //        }
  95.                 //}
  96.                 //               
  97.                 ////*************************************计算圆心偏移量******************
  98.                 //if (0 != ((hv_Score.TupleLength()) > 0))
  99.                 //{
  100.                 //        //测试代码
  101.                 //        const float fScre = hv_Score.D();

  102.                 //        if (0 != (HTuple(hv_Score[0]) >= hv_ValidScore))
  103.                 //        {
  104.                 //                //VectorAngleToRigid(HTuple(hv_HomMat2D_Read[0]), HTuple(hv_HomMat2D_Read[1]),
  105.                 //                //                   0, hv_ActualRow, hv_ActualColumn, hv_Angle, &hv_MovementOfObject);
  106.                 //                //AffineTransRegion(ho_ShapeModelRegion, &(ho_RegionAffineTrans), hv_MovementOfObject,
  107.                 //                //                  "nearest_neighbor");

  108.                 //                HomMat2dIdentity(&hv_MovementOfObject);
  109.                 //                HomMat2dScale(hv_MovementOfObject, HTuple(hv_Scale[0]), HTuple(hv_Scale[0]),
  110.                 //                        HTuple(hv_HomMat2D_Read[0]), HTuple(hv_HomMat2D_Read[1]), &hv_MovementOfObject);
  111.                 //                HomMat2dRotate(hv_MovementOfObject, hv_Angle, HTuple(hv_HomMat2D_Read[0]),
  112.                 //                        HTuple(hv_HomMat2D_Read[1]), &hv_MovementOfObject);
  113.                 //                HomMat2dTranslate(hv_MovementOfObject, hv_ActualRow - HTuple(hv_HomMat2D_Read[0]),
  114.                 //                        hv_ActualColumn - HTuple(hv_HomMat2D_Read[1]), &hv_MovementOfObject);
  115.                 //                AffineTransRegion(ho_ShapeModelRegion, &(ho_RegionAffineTrans), hv_MovementOfObject,
  116.                 //                        "nearest_neighbor");   

  117.                 //                //下面的方法,用于避免在创建模板时使用了掩膜,一旦使用掩膜,图像中心就不一定是区域中心了
  118.                 //                //因此在创建模板时,提前记录了图像中心位置
  119.                 //                if (0 != ((hv_HomMat2D_Read.TupleLength()) >= 5))
  120.                 //                {
  121.                 //                        const HTuple hv_OrigShapeRegionRow = hv_HomMat2D_Read[3];
  122.                 //                        const HTuple hv_OrigShapeRegionColumn = hv_HomMat2D_Read[4];
  123.                 //                        AffineTransPixel(hv_MovementOfObject, hv_OrigShapeRegionRow, hv_OrigShapeRegionColumn,
  124.                 //                                         &hv_ActualRow, &hv_ActualColumn);
  125.                 //                        GenCrossContourXld(&ho_Cross, hv_ActualRow, hv_ActualColumn, 120, 0);
  126.                 //                }

  127.                 //                //当前角度+原始模板角度=实际物体角度---->相对图像水平面
  128.                 //                if (0 != ((hv_HomMat2D_Read.TupleLength()) >= 3))
  129.                 //                {
  130.                 //                        hv_deltaAngle = hv_HomMat2D_Read[2];
  131.                 //                }
  132.                 //                else
  133.                 //                {
  134.                 //                        hv_deltaAngle = 0;
  135.                 //                }
  136.                 //                const HTuple hv_ActualAngle = (hv_Angle.TupleDeg()) + hv_deltaAngle;

  137.                 //                hv_CenterData.Clear();
  138.                 //                hv_CenterData.Append(hv_ActualRow);
  139.                 //                hv_CenterData.Append(hv_ActualColumn);
  140.                 //                hv_CenterData.Append(hv_ActualAngle);
  141.                 //                hv_CenterData.Append(hv_Score[0]);
  142.                 //                SetMessageTuple(dataDictionary, "CenterData", hv_CenterData);
  143.                 //                hv_ReturnCode = 1;
  144.                 //        }
  145.                 //        else
  146.                 //        {
  147.                 //                hv_FindScore = hv_Score[0];
  148.                 //                hv_ReturnCode = -11;
  149.                 //        }
  150.                 //}
  151.                 //else
  152.                 //{
  153.                 //        hv_FindScore = 0;
  154.                 //        hv_ReturnCode = -12;
  155.                 //}
  156.         }
  157.         catch (HException& e)
  158.         {
  159.                 CVisionPublicMethod::Get_HExceptionMsg(e, error, errMsg);
  160.                 hv_ReturnCode = -13;
  161.         }

  162.         ClearShapeModel(hv_ModelID);
  163.         SetMessageTuple(dataDictionary, "ErrCode", hv_ReturnCode);

  164.         //赋值输出参数
  165.         return {ho_TransContours, ho_RegionAffineTrans};
复制代码

上面代码我注释了一部分(主要用于排除问题,不影响我测试结果)

多线程互斥了

多线程互斥了





奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
Jo_Kang 发表于 2024-11-11 10:27:11 | 显示全部楼层
CropDomain此算子影响时长
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| jacktl 发表于 2024-11-11 17:16:42 | 显示全部楼层
主要我发现有些算子在多线程中似乎会出现线程互斥,按照算子手册说明,我用的算子应该互相不影响的,就比如算子FindScaledShapeModel,在使用不同图片,不同模版数据时,多线程中同时调用FindScaledShapeModel,本应该不会出现相互影响的状况。
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
neo3301 发表于 2024-11-12 19:25:24 | 显示全部楼层
错误提示什么,我以前遇到过多线程偶发崩溃的情况,你这个apply()中尽量不要包含模板的加载部分,这不符合halcon的设计,尽量初始化的时候单独加载,多线程中只执行匹配
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
duibuqininshur 发表于 2024-11-14 10:33:18 | 显示全部楼层
可以先试一下halcon自带的多线程方案程序
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| jacktl 发表于 2024-11-15 19:40:12 | 显示全部楼层
neo3301 发表于 2024-11-12 19:25
错误提示什么,我以前遇到过多线程偶发崩溃的情况,你这个apply()中尽量不要包含模板的加载部分,这不符合h ...

多线程中我确实会每次从文件中读取模板信息,主要的这个程序是一个通过程序,每次匹配的模板不固定,因此我设计的时候就每次读取文件(耗时可以忽略)。
程序是不会报错的,因为程序可以正常匹配,只不过多线程之间HALCON的算子似乎出现了互斥现象,无法独立运行,经测试线程01在执行Find匹配时,测试的结果就是线程02的Find就处于等待状态。。。。根据手册说明这个不应该的。
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
 楼主| jacktl 发表于 2024-11-15 19:41:17 | 显示全部楼层
duibuqininshur 发表于 2024-11-14 10:33
可以先试一下halcon自带的多线程方案程序

这个我也在PDF中手册中看了,目前今天有点空,准备研究下,最近在现场调试别的设备。。。回复不及时,抱歉各位!!!
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
GBLZ 发表于 2024-11-21 10:30:12 | 显示全部楼层
可以尝试:find_scaled_shape_models (Operator)
ModelIDs 参数与输入的Image 数量相同,或是 输入一个Image 多个ModelIDs;对应的是  [Image1,Image2...][ModelID1,ModelID2...]  与  [Image] [ModelID1,ModelID2...]
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
neo3301 发表于 2024-11-21 13:25:41 | 显示全部楼层
jacktl 发表于 2024-11-11 17:16
主要我发现有些算子在多线程中似乎会出现线程互斥,按照算子手册说明,我用的算子应该互相不影响的,就比如 ...

halcon 多模板的设计使用思路是 加载多个模板到modelist,然后再多线程匹配,模板加载跟识别搞在一起容易出问题,你这种情况 可以多试几台设备,应该每台设备的情形不一样
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
zj_ 发表于 2025-2-5 15:44:43 | 显示全部楼层
请问楼主,解决了吗
奖励计划已经开启,本站鼓励作者发布最擅长的技术内容和资源,流量变现就在现在,[点我]加入吧~~~Go
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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