QT + opencv 实现形状(表面)模板匹配

宁睿  论坛元老 | 2025-1-12 18:34:14 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1085|帖子 1085|积分 3265

QT + opencv 实现形状(表面)模板匹配

实现思绪

1.创建模板数据:重要是提取模板的表面信息,这一步通常通过边缘检测实现。将模板的表面信息存储起来。

代码:
  1. //创建形状模板
  2. bool cvLearnShapeMatchPattern_(Mat matDst, MyShapeUiParam param, MyShapeTemplData* pTemplData)
  3. {
  4.     //图像不存在
  5.     if(matDst.empty())
  6.         return false;
  7.     //清除模板
  8.     pTemplData->clear();
  9.     //边缘检测
  10.     Mat canny, gray;
  11.     vector<Point> contours;
  12.     cv::Canny(matDst, canny, pTemplData->minThresh, pTemplData->maxThresh);
  13.     canny.copyTo(gray);
  14.     /*if(!(pTemplData->sample==0))
  15.     {
  16.         Mat element=getStructuringElement(MORPH_ELLIPSE, Size(pTemplData->dilate, pTemplData->dilate));
  17.         cv::dilate(canny, gray, element);
  18.     }*/
  19.     cvFindContour_(gray, contours, pTemplData->minLen, 10e9, pTemplData->sample);
  20.     if((int)contours.size()==0)
  21.         return false;
  22.     //压缩金字塔
  23.     int iTopLayer=param.m_iPyramid;
  24.     buildPyramid(matDst, pTemplData->vecPyramid, iTopLayer);
  25.     for(size_t i=0;i<pTemplData->vecPyramid.size();i++)
  26.     {
  27.         //轮廓信息
  28.         Mat src=pTemplData->vecPyramid[i];
  29.         vector<Point> pyrContour=cvPyrContour_(contours, matDst.size(), src.size());
  30.         pTemplData->vecPoints.push_back(pyrContour);
  31.         //显示
  32.         Mat dst=Mat::zeros(src.size(), CV_8UC1);
  33.         for(size_t j=0;j<pyrContour.size();j++)
  34.             dst.at<uchar>(pyrContour[j].y, pyrContour[j].x)=255;
  35.         imshow(QString("%1").arg(i).toStdString(), dst);
  36.         cv::waitKey(5);
  37.         //梯度信息
  38.         Mat gx, gy, mag, dir;
  39.         Sobel(src, gx, CV_32F, 1, 0);
  40.         Sobel(src, gy, CV_32F, 0, 1);
  41.         cartToPolar(gx, gy, mag, dir);
  42.         //提取梯度
  43.         vector<SPtin> vecSPtin;
  44.         for(size_t j=0;j<pyrContour.size();j++)
  45.         {
  46.             SPtin info;
  47.             Point p=pyrContour[j];
  48.             info.derivativeX=gx.at<float>(p.y, p.x);
  49.             info.derivativeY=gy.at<float>(p.y, p.x);
  50.             info.magnitude=mag.at<float>(p.y, p.x);
  51.             info.magnitudeN = info.magnitude==0 ? 0 : (1.0f / info.magnitude);
  52.             vecSPtin.push_back(info);
  53.         }
  54.         pTemplData->vecSPtins.push_back(vecSPtin);
  55.     }
  56.     //训练标记
  57.     pTemplData->bIsPatternLearned=true;
  58.     return true;
  59. }
复制代码
2.模板匹配:同样需要利用压缩金字塔的方法来提拔搜刮速度,减少参数目。然后取顶层金字塔进行旋转,和模板表面进行匹配,找到大抵角度后再进行细致的搜刮。

部分代码
  1. //模板匹配
  2. bool cvShapeMatch_(Mat matSrc, vector<MyShapeTemplData> templDatas, MyShapeUiParam param, vector<MySingleTargetMatch>& vecSingleTargetData)
  3. {
  4.     //图像
  5.     if(matSrc.empty())
  6.         return false;
  7.     //模板
  8.     if((int)templDatas.size()==0)
  9.         return false;
  10.     //決定金字塔層數 總共為1 + iLayer層
  11.     int iTopLayer=param.m_iPyramid;
  12.     vector<Mat> vecMatSrcPyr;
  13.     buildPyramid(matSrc, OutputArrayOfArrays(vecMatSrcPyr), iTopLayer);
  14.     //取顶层图片的中心点
  15.     int iTopSrcW = vecMatSrcPyr[iTopLayer].cols, iTopSrcH = vecMatSrcPyr[iTopLayer].rows;
  16.     Point2f ptCenter((iTopSrcW - 1) / 2.0f, (iTopSrcH - 1) / 2.0f);
  17.     //Caculate lowest score at every layer
  18.     vector<double> vecLayerScore(iTopLayer + 1, param.m_dScore);
  19.     for (int iLayer = 1; iLayer <= iTopLayer; iLayer++)
  20.         vecLayerScore[iLayer] = vecLayerScore[iLayer - 1] * param.m_dGreed;
  21.     //clear
  22.     vecSingleTargetData.clear();
  23.     //并行加速
  24.     omp_set_num_threads(4);
  25.     #pragma omp parallel for
  26.     for(int k=0;k<(int)templDatas.size();k++)
  27.     {
  28.         MyShapeTemplData* pTemplData = &templDatas[k];
  29.         if((int)pTemplData->vecPyramid.size()==0 || !pTemplData->bIsPatternLearned)
  30.             continue;
  31.         Mat matDst=pTemplData->vecPyramid[0];
  32.         if (matDst.empty())
  33.             continue;
  34.         if ((matDst.cols<matSrc.cols && matDst.rows>matSrc.rows) || (matDst.cols>matSrc.cols && matDst.rows<matSrc.rows))
  35.             continue;
  36.         if (matDst.size().area()>=matSrc.size ().area())
  37.             continue;
  38.         //匹配轮廓
  39.         vector<Point> Contour=pTemplData->vecPoints[0];
  40.         cvAffineTrans_(Contour, Point3f((float)(matDst.cols - 1)/2.0f, (float)(matDst.rows - 1)/2.0f, 0), Point3f(0, 0, 0));
  41.         //第一階段以最頂層找出大致角度與ROI
  42.         double dAngleStep=atan(2.0 / max(pTemplData->vecPyramid[iTopLayer].cols, pTemplData->vecPyramid[iTopLayer].rows)) * R2D;
复制代码
实现效果:实际匹配目标时,角度搜刮范围可以不必像我这样设置这么大。在相机画面中进行检测时,通常是在ROI中进行检测,速度通常在100ms以内。




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宁睿

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表