QQ登录

只需一步,快速开始

上位机通过CCD视觉检测图像角度与几何坐标

[ 复制链接 ]

通过CCD视觉检测图像角度与几何坐标

通过CCD视觉检测图像角度与几何坐标

通过CCD视觉检测图像角度与几何坐标

通过CCD视觉检测图像角度与几何坐标

通过CCD视觉检测图像角度与几何坐标

通过CCD视觉检测图像角度与几何坐标

通过CCD视觉检测图像角度与几何坐标

通过CCD视觉检测图像角度与几何坐标

现在国家大力提倡工业4.0,机器人与视觉在工业上的应用正在加大,加速普及。
掌握了PLC,触摸屏编程的 会员们千万别知足止步不前;


这里介绍与分享一视觉的应用:通过CCD视觉检测图像角度与几何坐标
步骤:
1.先在一张图片上确定一个要检测的区域作为大模板;
2.再在大模板上确定一个小模板区域,作为参考区域;
3.开始对物体拍照得到图片。在图片先检测出全部大模板,再在全部大模板中检测小模板。
通过计算得出这些小模板与原始参考小模板的相对角度,以及大模板的中点。
进而得到物体的坐标及旋转角度, 机器人就可通过这参数进行位置纠正,正确抓取物体;

下面是程序核心代码
  1. BOOL CAngleDetect::Init(CString sPicName,HWND hWnd,BOOL bManuelConfirm)
  2. {
  3.         if(!IsWindow(hWnd))
  4.                 return false;
  5.         Clear();
  6.         //<>
  7.         HObject  ho_Image, ho_Region, ho_RegionBorder;
  8.         HObject  ho_RegionDilation, ho_ImageReduced, ho_Edges, ho_ModelRegion;
  9.         HObject  ho_ModelImage, ho_ModelCenter, ho_ModelContour;
  10.         HObject  ho_ModelContourAffined, ho_AsymEdgesRegion, ho_AsymEdgesRegionPolar;
  11.         HObject  ho_PolarTransModelImage, ho_RegionTrans, ho_PolarModelImage;
  12.         HObject  ho_RefinedContours, ho_PolarTransImage;
  13.         HObject  ho_SearchImageReduced, ho_ContoursAffinTrans, ho_XYTransContour;
  14.        
  15.         HTuple  hv_MinScoreMain,hv_Tolerance,hv_Interactive=bManuelConfirm,hv_Name = sPicName;
  16.         HTuple  hv_MinScorePolar, hv_ContrastMain, hv_ContrastPolar;
  17.         HTuple  hv_Greediness, hv_ContrastMin, hv_RowFitted, hv_ColumnFitted;
  18.         HTuple  hv_RadiusFitted, hv_SPhi, hv_EPhi, hv_POder;
  19.         HTuple  hv_AreaModelRegion, hv_RowModelRegion, hv_ColumnModelRegion;
  20.         HTuple  hv_RR, hv_CC, hv_AA, hv_SS, hv_Hom2DIdentity, hv_Hom2DTranslate;
  21.         HTuple  hv_Clip, hv_ImageWidth, hv_ImageHeight;
  22.         HTuple  hv_Aspect, hv_AsymModelReady;
  23.         HTuple  hv_AreaAsym, hv_RowAsym, hv_ColumnAsymn, hv_AngleRef;
  24.         HTuple  hv_PolarWidth, hv_PolarHeight, hv_Row1, hv_Column1;
  25.         HTuple  hv_Row2, hv_Column2, hv_RegionWidth, hv_AngleOverlap;
  26.         HTuple  hv_AngleRefPolar, hv_ScoreRefPolar;
  27.         HTuple  hv_ImageNum, hv_Index, hv_sIndex, hv_Row, hv_Column;
  28.         HTuple  hv_Angle, hv_Score, hv_NumMatches, hv_FinalAngle;
  29.         HTuple  hv_RowsPolar, hv_ColumnsPolar, hv_AnglesPolar, hv_RefinementFailed;
  30.         HTuple  hv_J, hv_RowPolar, hv_ColumnPolar, hv_AnglePolar;
  31.         HTuple  hv_ScorePolar, hv_HomMat2D, hv_Title;
  32.                
  33.         hv_MinScoreMain  = 0.7;//主模板外形匹配的最小值
  34.         hv_ContrastMain  = 30; //主模板外形匹配的对比度  
  35.         hv_Greediness    = 0.5;//主模板外形匹配的       
  36.         hv_ContrastPolar = 20; //小模板外形匹配的对比度
  37.         hv_MinScorePolar = 0.4;//小模板查找最小得分
  38.         hv_Tolerance     = 2.5;
  39.         hv_ContrastMin   = 10;
  40.         //<>       
  41.         ReadImage(&ho_Image, hv_Name);
  42.         Threshold(ho_Image, &ho_Region, 120, 255);
  43.         Boundary(ho_Region, &ho_RegionBorder, "inner");
  44.         DilationCircle(ho_RegionBorder, &ho_RegionDilation, 3.5);
  45.         ReduceDomain(ho_Image, ho_RegionDilation, &ho_ImageReduced);
  46.         EdgesSubPix(ho_ImageReduced, &ho_Edges, "canny", 1, 20, 40);
  47.         FitCircleContourXld(ho_Edges, "geohuber", -1, 0, 0, 3, 2, &hv_RowFitted, &hv_ColumnFitted,
  48.                 &hv_RadiusFitted, &hv_SPhi, &hv_EPhi, &hv_POder);
  49.         GenCircle(&ho_ModelRegion, hv_RowFitted, hv_ColumnFitted, hv_RadiusFitted+10);
  50.         ReduceDomain(ho_Image, ho_ModelRegion, &ho_ModelImage);
  51.         CreateShapeModel(ho_ModelImage, "auto", 0, HTuple(360).TupleRad(), "auto", "auto",
  52.                 "use_polarity", hv_ContrastMain, hv_ContrastMin, &m_hv_ModelID);
  53.         //校正主模板中点
  54.         AreaCenter(ho_ModelRegion, &hv_AreaModelRegion, &hv_RowModelRegion, &hv_ColumnModelRegion);
  55.         SetShapeModelOrigin(m_hv_ModelID, hv_RowFitted-hv_RowModelRegion, hv_ColumnFitted-hv_ColumnModelRegion);
  56.         FindShapeModel(ho_Image, m_hv_ModelID, -0.39, 0.78, 0.5, 1, 0.5, "least_squares",
  57.                 0, 0.9, &hv_RR, &hv_CC, &hv_AA, &hv_SS);
  58.         //放大显示主模板
  59.         GenCrossContourXld(&ho_ModelCenter, hv_RowFitted, hv_ColumnFitted, 12, 0.0);
  60.         GetShapeModelContours(&ho_ModelContour, m_hv_ModelID, 1);
  61.         HomMat2dIdentity(&hv_Hom2DIdentity);
  62.         HomMat2dTranslate(hv_Hom2DIdentity, hv_RowFitted, hv_ColumnFitted, &hv_Hom2DTranslate);
  63.         AffineTransContourXld(ho_ModelContour, &ho_ModelContourAffined, hv_Hom2DTranslate);
  64.         hv_Clip = hv_RadiusFitted+60;
  65.         OpenWindowFitImage(ho_Image, 0, 0, -1, 500, &m_hv_WindowHandle,hWnd);
  66.         GetImageSize(ho_Image, &hv_ImageWidth, &hv_ImageHeight);
  67.         hv_Aspect = (hv_ImageWidth.TupleReal())/hv_ImageHeight;
  68.         if (HDevWindowStack::IsOpen())
  69.                 SetPart(HDevWindowStack::GetActive(),hv_RowFitted-hv_Clip, hv_ColumnFitted-(hv_Clip*hv_Aspect),
  70.         hv_RowFitted+hv_Clip, hv_ColumnFitted+(hv_Clip*hv_Aspect));
  71.         DisplayModel(ho_Image, ho_ModelRegion, ho_ModelCenter, ho_ModelContourAffined);
  72.         //以交互或自定义形式,选择非对称区域生成一非对称模板
  73.         hv_AsymModelReady = 0;
  74.         while (0 != (hv_AsymModelReady.TupleNot()))
  75.         {
  76.                 if (HDevWindowStack::IsOpen())
  77.                         SetColor(HDevWindowStack::GetActive(),"blue");
  78.                 if (0 != hv_Interactive)
  79.                 {
  80.                         DrawDetectingRegion(&ho_AsymEdgesRegion, m_hv_WindowHandle);
  81.                         ConfirmDrawedRegion(m_hv_WindowHandle, hv_RowFitted, hv_ColumnFitted, hv_Clip, &hv_AsymModelReady);
  82.                 }
  83.                 else
  84.                 {
  85.                         GenRectangle1(&ho_AsymEdgesRegion, 315, 694, 343, 711);
  86.                         hv_AsymModelReady = 1;
  87.                 }
  88.                 DisplayModel(ho_Image, ho_ModelRegion, ho_ModelCenter, ho_ModelContourAffined );
  89.                 DisplayMarkedEdge(ho_Image, ho_AsymEdgesRegion, hv_ContrastPolar, 315, 694, m_hv_WindowHandle);
  90.         }
  91.         DistancePr(ho_AsymEdgesRegion, hv_RowFitted, hv_ColumnFitted, &m_hv_RadiusInner, &m_hv_RadiusOuter);
  92.         AreaCenter(ho_AsymEdgesRegion, &hv_AreaAsym, &hv_RowAsym, &hv_ColumnAsymn);
  93.         AngleLx(hv_RowFitted, hv_ColumnFitted, hv_RowAsym, hv_ColumnAsymn, &hv_AngleRef);
  94.         hv_PolarWidth = (m_hv_RadiusOuter*(HTuple(360).TupleRad())).TupleRound();
  95.         hv_PolarHeight = (m_hv_RadiusOuter-m_hv_RadiusInner).TupleRound();
  96.         PolarTransRegion(ho_AsymEdgesRegion, &ho_AsymEdgesRegionPolar, hv_RowFitted, hv_ColumnFitted,
  97.                 hv_AngleRef+(HTuple(180).TupleRad()), hv_AngleRef+(HTuple(540).TupleRad()),
  98.                 m_hv_RadiusInner, m_hv_RadiusOuter, hv_PolarWidth, hv_PolarHeight, "bilinear");
  99.         SmallestRectangle1(ho_AsymEdgesRegionPolar, &hv_Row1, &hv_Column1, &hv_Row2, &hv_Column2);

  100.         hv_RegionWidth               = (hv_Column2-hv_Column1)+1;
  101.         hv_AngleOverlap              = (hv_RegionWidth*(HTuple(360).TupleRad()))/hv_PolarWidth;
  102.         m_hv_PolarStartAngle         = hv_AngleRef-(hv_AngleOverlap/2);
  103.         m_hv_PolarEndAngle           = (hv_AngleRef+(HTuple(360).TupleRad()))+(hv_AngleOverlap/2);
  104.         m_hv_PolarAngleRangeExtended = m_hv_PolarEndAngle-m_hv_PolarStartAngle;
  105.         m_hv_PolarWidthExtended      = (m_hv_RadiusOuter*m_hv_PolarAngleRangeExtended).TupleRound();

  106.         PolarTransImageExt(ho_Image, &ho_PolarTransModelImage, hv_RowFitted, hv_ColumnFitted,
  107.                 m_hv_PolarStartAngle, m_hv_PolarEndAngle, m_hv_RadiusInner, m_hv_RadiusOuter, m_hv_PolarWidthExtended,
  108.                 hv_PolarHeight, "bilinear");
  109.         PolarTransRegion(ho_AsymEdgesRegion, &ho_AsymEdgesRegionPolar, hv_RowFitted, hv_ColumnFitted,
  110.                 m_hv_PolarStartAngle, m_hv_PolarStartAngle+hv_AngleOverlap, m_hv_RadiusInner, m_hv_RadiusOuter,
  111.                 hv_RegionWidth, hv_PolarHeight, "bilinear");
  112.         ShapeTrans(ho_AsymEdgesRegionPolar, &ho_RegionTrans, "convex");
  113.         ReduceDomain(ho_PolarTransModelImage, ho_RegionTrans, &ho_PolarModelImage);
  114.         CreateShapeModel(ho_PolarModelImage, 1, 0, 0, "auto", "auto", "use_polarity", hv_ContrastPolar,
  115.                 hv_ContrastMin, &m_hv_ModelIDPolar);
  116.         GetShapeModelContours(&m_ho_PolarModelContours, m_hv_ModelIDPolar, 1);
  117.         FindShapeModel(ho_PolarModelImage, m_hv_ModelIDPolar, 0, 0, hv_MinScorePolar, 1,
  118.                 0.0, "least_squares", 0, hv_Greediness, &m_hv_RowRefPolar, &m_hv_ColumnRefPolar, &hv_AngleRefPolar, &hv_ScoreRefPolar);
  119.         if (HDevWindowStack::IsOpen())
  120.                 SetPart(HDevWindowStack::GetActive(),0, 0, hv_ImageHeight-1, hv_ImageWidth-1);
  121.         if (HDevWindowStack::IsOpen())
  122.                 SetLineWidth(HDevWindowStack::GetActive(),1);
  123.         return true;
  124. }
复制代码
  1. BOOL CAngleDetect::DetectAngle(CString sPicName,BOOL bShowResult)
  2. {
  3.         if(0 == m_hv_ModelID.Length())
  4.                 return false;       
  5.         HObject  ho_Image;
  6.         HTuple   hv_MinScoreMain,hv_Greediness,hv_ImageWidth,hv_ImageHeight,hv_NumMatches,hv_Name = sPicName;
  7.         HTuple   hv_Row, hv_Column, hv_Angle, hv_Score,hv_Tolerance,hv_MinScorePolar;
  8.         HTuple   hv_RowPolar,hv_ColumnPolar,hv_AnglePolar,hv_ScorePolar,hv_HomMat2D;
  9.         hv_MinScoreMain  = 0.7;
  10.         hv_Greediness    = 0.5;
  11.         hv_Tolerance     = 2.5;
  12.         hv_MinScorePolar = 0.4;//小模板查找最小得分
  13.         ReadImage(&ho_Image, hv_Name);
  14.         GetImageSize(ho_Image, &hv_ImageWidth, &hv_ImageHeight);
  15.     FindShapeModel(ho_Image, m_hv_ModelID, 0, HTuple(360).TupleRad(), hv_MinScoreMain,
  16.         0, 0.0, "least_squares", 0, hv_Greediness, &hv_Row, &hv_Column, &hv_Angle, &hv_Score);
  17.     hv_NumMatches = hv_Row.TupleLength();
  18.     if (hv_NumMatches<=0)
  19.     {
  20.                 DisplayMessage(m_hv_WindowHandle, "未找到", "window", 12, 12, "black", "true");
  21.                 return false;
  22.     }
  23. //<>
  24.         ClearData();//清空数据
  25.         HTuple hv_PolarHeight = (m_hv_RadiusOuter-m_hv_RadiusInner).TupleRound();
  26.         HObject ho_PolarTransImage,ho_SearchImageReduced,ho_RefinedContours,ho_ContoursAffinTrans,ho_XYTransContour;
  27.         GenEmptyObj(&ho_RefinedContours);
  28.         HTuple hv_FinalAngles      = HTuple();
  29.         HTuple hv_RefinementFailed = HTuple();
  30.     HTuple end_val96           = hv_NumMatches-1;
  31.     HTuple step_val96          = 1;
  32.         HTuple hv_J;
  33.         for (hv_J=0; hv_J.Continue(end_val96, step_val96); hv_J += step_val96)
  34.         {
  35.                 PolarTransImageExt(ho_Image, &ho_PolarTransImage, HTuple(hv_Row[hv_J]), HTuple(hv_Column[hv_J]),
  36.                         m_hv_PolarStartAngle, m_hv_PolarEndAngle, m_hv_RadiusInner, m_hv_RadiusOuter, m_hv_PolarWidthExtended, hv_PolarHeight, "bilinear");               
  37.                 Rectangle1Domain(ho_PolarTransImage, &ho_SearchImageReduced, m_hv_RowRefPolar-hv_Tolerance, 0, m_hv_RowRefPolar+hv_Tolerance, m_hv_PolarWidthExtended-1);
  38.                 FindShapeModel(ho_SearchImageReduced, m_hv_ModelIDPolar, 0, 0, hv_MinScorePolar,
  39.                         1, 0.0, "least_squares", 0, hv_Greediness, &hv_RowPolar, &hv_ColumnPolar, &hv_AnglePolar, &hv_ScorePolar);
  40.                 if (0 != ((hv_ColumnPolar.TupleLength())>0))
  41.                 {
  42.                         hv_FinalAngles[hv_J]  = ((hv_ColumnPolar-m_hv_ColumnRefPolar)/(m_hv_PolarWidthExtended-1))*m_hv_PolarAngleRangeExtended;

  43.                         DATA *pData = new DATA();
  44.                         pData->Angle = HTuple(hv_FinalAngles[hv_J]).TupleDeg().D();//hv_FinalAngles[hv_J].D();
  45.                         pData->XPos = HTuple(hv_Column[hv_J]).D();
  46.                         pData->YPos = HTuple(hv_Row[hv_J]).D();
  47.                         m_DataList.AddTail(pData);
  48.                         if(bShowResult)
  49.                         {
  50.                                 VectorAngleToRigid(0, 0, 0, hv_RowPolar, hv_ColumnPolar, hv_AnglePolar, &hv_HomMat2D);
  51.                                 AffineTransContourXld(m_ho_PolarModelContours, &ho_ContoursAffinTrans, hv_HomMat2D);
  52.                                 PolarTransContourXldInv(ho_ContoursAffinTrans, &ho_XYTransContour, HTuple(hv_Row[hv_J]),
  53.                                         HTuple(hv_Column[hv_J]), m_hv_PolarStartAngle, m_hv_PolarEndAngle, m_hv_RadiusInner,
  54.                                         m_hv_RadiusOuter, m_hv_PolarWidthExtended, hv_PolarHeight, hv_ImageWidth, hv_ImageHeight);
  55.                                 ConcatObj(ho_RefinedContours, ho_XYTransContour, &ho_RefinedContours);
  56.                         }
  57.                 }
  58.                 else
  59.                 {
  60.                         hv_FinalAngles[hv_J] = HTuple(hv_Angle[hv_J]);
  61.                         hv_RefinementFailed = hv_RefinementFailed.TupleConcat(hv_J+1);
  62.                 }
  63.         }
  64.         if(bShowResult)
  65.         {       
  66.                 HTuple hv_Title = "找到模型个数: "+hv_NumMatches;
  67.                 DisplayResult(ho_Image, ho_RefinedContours, hv_Row, hv_Column, hv_Angle, hv_FinalAngles, hv_RefinementFailed, m_hv_ModelID, hv_Title, m_hv_WindowHandle);
  68.         }
  69.         return true;
  70. }
复制代码
  1. void CAngleDetect::ClearData()
  2. {
  3.         POSITION pos = m_DataList.GetHeadPosition();
  4.         while(pos)
  5.         {
  6.                 DATA *pData = (DATA *)m_DataList.GetNext(pos);
  7.                 delete  pData;
  8.         }
  9.         m_DataList.RemoveAll();
  10. }
  11. CPtrList*CAngleDetect::GetDataList()
  12. {
  13.         return &m_DataList;
  14. }
  15. BOOL CAngleDetect::Clear()
  16. {
  17.         if (0 != m_hv_WindowHandle.Length())
  18.         {
  19.                 CloseWindow(m_hv_WindowHandle);
  20.                 m_hv_WindowHandle = HTuple();
  21.         }
  22.         if(0!=m_hv_ModelID.Length())
  23.         {
  24.                 ClearShapeModel(m_hv_ModelID);
  25.                 m_hv_ModelID = HTuple();
  26.         }
  27.         if(0!=m_hv_ModelIDPolar.Length())
  28.         {
  29.                 ClearShapeModel(m_hv_ModelIDPolar );
  30.                 m_hv_ModelIDPolar = HTuple();
  31.         }
  32.         ClearData();
  33.         return true;
  34. }
复制代码
  1. void CAngleDetectView::OnButton1()
  2. {
  3.         CButton*pBtn = (CButton*)GetDlgItem(IDC_CHECK1);
  4.         m_AngleDect.Init("pic/1.png",GetDlgItem(IDC_SHOW)->m_hWnd,pBtn->GetCheck());
  5. }
  6. void CAngleDetectView::OnButton2()
  7. {
  8.         LARGE_INTEGER  large_interger;
  9.         QueryPerformanceFrequency(&large_interger);  
  10.     LONGLONG ff = large_interger.QuadPart;  
  11.         QueryPerformanceCounter(&large_interger);  
  12.     LONGLONG c1 = large_interger.QuadPart;
  13.         //<>
  14.         static Index = 1;
  15.         CString sText;
  16.         sText.Format("pic/%d.png",Index);
  17.         CButton* pBtn = (CButton*)GetDlgItem(IDC_CHECK2);
  18.         if( m_AngleDect.DetectAngle(sText,!pBtn->GetCheck()) )//正常检测后
  19.         {
  20.                 QueryPerformanceCounter(&large_interger);  
  21.         LONGLONG c2 = large_interger.QuadPart;
  22.                 CComboBox*pBox1 = (CComboBox*)GetDlgItem(IDC_COMBO1);
  23.                 CComboBox*pBox2 = (CComboBox*)GetDlgItem(IDC_COMBO2);
  24.                 CComboBox*pBox3 = (CComboBox*)GetDlgItem(IDC_COMBO3);
  25.                 CComboBox*pBox4 = (CComboBox*)GetDlgItem(IDC_COMBO4);
  26.                 pBox1->ResetContent();
  27.                 pBox2->ResetContent();
  28.                 pBox3->ResetContent();
  29.                 pBox4->ResetContent();
  30.                 double dbTime = (double)(c2-c1)/ff;
  31.                 sText.Format("%f",dbTime*1000);
  32.                 pBox4->InsertString(0,sText);
  33.                 pBox4->SetCurSel(0);//用时
  34.        
  35.                 DATA *pData;
  36.                 POSITION pos = m_AngleDect.GetDataList()->GetHeadPosition();
  37.                 while(pos)
  38.                 {
  39.                         pData = (DATA *)m_AngleDect.GetDataList()->GetNext(pos);
  40.                         sText.Format("%f",pData->XPos);
  41.                         pBox1->InsertString(0,sText);
  42.                         pBox1->SetCurSel(0);
  43.                         sText.Format("%f",pData->YPos);
  44.                         pBox2->InsertString(0,sText);
  45.                         pBox2->SetCurSel(0);
  46.                         sText.Format("%f",pData->Angle);
  47.                         pBox3->InsertString(0,sText);
  48.                         pBox3->SetCurSel(0);
  49.                 }
  50.         }
  51.         Index++;
  52.         if(Index>16)
  53.                 Index=1;
  54. }
复制代码


完整代码及可执行程序,会员可下载学习及使用
百度云附件:上位机通过CCD视觉检测图像角度与几何坐标.rar   
  

如果您认可,可联系功能定制!

  

如果您着急,充值会员可直接联系发您资料!

  

QQ联系我

微信扫扫联系我

  


回复

使用道具 举报

大神点评(1)

快速回复 返回列表 客服中心 搜索