极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2614|回复: 0

如何实现视觉识别形状

[复制链接]
发表于 2023-4-14 09:51:43 | 显示全部楼层 |阅读模式
本帖最后由 机器谱 于 2023-4-14 09:51 编辑

1. 功能说明
       通过摄像头识别圆形及矩形两种形状。


2. 电子硬件

      本实验中采用了以下硬件:

主控板
Basra主控板(兼容Arduino Uno)
扩展板
Bigfish2.1扩展板
电池7.4V锂电池
通信2510通信转接板
WiFi路由器
其它
摄像头
配置OpenCV的Visual Studio 2015.net环境的计算机一台

3. 功能实现  

    工作原理:
          ① 导入一张图片或者通过WiFi传递摄像信息给PC;
          ② 在PC端使用OpenCV对图像转化为灰度图像;
          ③ 检测圆形和矩形。
    检测圆形使用霍夫变换:
  1. vector<Vec3f> circles;

  2. HoughCircles(image, circles, HOUGH_GRADIENT, 2.0,

  3. image.rows/8, // change this value to detect circles with different distances to each other

  4. 200, 85, 0, 0 // change the last two parameters

  5.   // (min_radius & max_radius) to detect larger circles

  6. );
复制代码

    检测矩形:
  1. //多边形检测,通过约束条件寻找矩形

  2. static void findSquares(const Mat& image, vector<vector<Point> >& squares)

  3. {

  4. squares.clear();


  5. Mat pyr, timg, gray0(image.size(), CV_8U), gray;


  6. // down-scale and upscale the image to filter out the noise

  7. pyrDown(image, pyr, Size(image.cols / 2, image.rows / 2));

  8. pyrUp(pyr, timg, image.size());

  9. vector<vector<Point> > contours;


  10. // find squares in every color plane of the image

  11. for (int c = 0; c < 3; c++)

  12. {

  13. int ch[] = { c, 0 };

  14. mixChannels(&timg, 1, &gray0, 1, ch, 1);


  15. // try several threshold levels

  16. for (int l = 0; l < N; l++)

  17. {

  18. // hack: use Canny instead of zero threshold level.

  19. // Canny helps to catch squares with gradient shading

  20. if (l == 0)

  21. {

  22. // apply Canny. Take the upper threshold from slider

  23. // and set the lower to 0 (which forces edges merging)

  24. Canny(gray0, gray, 0, thresh, 5);

  25. // dilate canny output to remove potential

  26. // holes between edge segments

  27. dilate(gray, gray, Mat(), Point(-1, -1));

  28. }

  29. else

  30. {

  31. // apply threshold if l!=0:

  32. //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0

  33. gray = gray0 >= (l + 1) * 255 / N;

  34. }


  35. // find contours and store them all as a list

  36. findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);


  37. vector<Point> approx;


  38. // test each contour

  39. for (size_t i = 0; i < contours.size(); i++)

  40. {

  41. // approximate contour with accuracy proportional

  42. // to the contour perimeter

  43. approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);


  44. // square contours should have 4 vertices after approximation

  45. // relatively large area (to filter out noisy contours)

  46. // and be convex.

  47. // Note: absolute value of an area is used because

  48. // area may be positive or negative - in accordance with the

  49. // contour orientation

  50. if (approx.size() == 4 &&

  51. fabs(contourArea(Mat(approx))) > 1000 &&

  52. isContourConvex(Mat(approx)))

  53. {

  54. double maxCosine = 0;


  55. for (int j = 2; j < 5; j++)

  56. {

  57. // find the maximum cosine of the angle between joint edges

  58. double cosine = fabs(angle(approx[j % 4], approx[j - 2], approx[j - 1]));

  59. maxCosine = MAX(maxCosine, cosine);

  60. }


  61. // if cosines of all angles are small

  62. // (all angles are ~90 degree) then write quandrange

  63. // vertices to resultant sequence

  64. if (maxCosine < 0.3)

  65. squares.push_back(approx);

  66. }

  67. }

  68. }

  69. }

  70. }
复制代码

3.1硬件连接
     将摄像头与路由器连接,启动路由器,将PC连接到路由器的WIFI网络。


接线说明:
       ① 将2510通信转接板连接到扩展板的扩展坞上面;
       ② 用3根母对母杜邦线将2510通信转接板与WiFi路由器连接起来,GND-GND、RX-RX、TX-TX;
       ③ 找到1根USB线,一端连接到2510通信转接板接口上,另一端连接到WiFi路由器USB接口上;
       ④ 将摄像头线连接到WiFi路由器接口上。

3.2示例程序
     下面提供一个可以进行识别圆形和矩形的参考例程(ShapeDetect\ShapeDetect\MainWindow.xaml.cs):
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Threading.Tasks;

  6. using System.Windows;

  7. using System.Windows.Controls;

  8. using System.Windows.Data;

  9. using System.Windows.Documents;

  10. using System.Windows.Input;

  11. using System.Windows.Media;

  12. using System.Windows.Media.Imaging;

  13. using System.Windows.Navigation;

  14. using System.Windows.Shapes;

  15. using System.Windows.Forms;

  16. using System.Runtime.InteropServices;

  17. using System.Threading;


  18. namespace ShapeDetect

  19. {

  20.     /// <summary>

  21.     /// 形状识别

  22.     /// </summary>

  23.     public partial class MainWindow : Window

  24.     {

  25.         //定义检测模式

  26.         int IMAGE_MODE = 1, VIDEO_MODE = 2;


  27.         private AutoResetEvent exitEvent;

  28.         private Thread m_thread;


  29.         //导入动态链接库

  30.         [DllImport("HoughCircles_DLL.dll")]

  31.         //检测圆

  32.         public static extern System.UIntPtr HoughCircles([MarshalAs(UnmanagedType.LPStr)]string address, int detect_mode);

  33.         [DllImport("SquareDetect_DLL.dll")]

  34.         //检测矩形

  35.         public static extern void SquareDetector([MarshalAs(UnmanagedType.LPStr)]string address, int detect_mode);


  36.         public MainWindow()

  37.         {

  38.             InitializeComponent();

  39.         }


  40.         private void Window_Loaded(object sender, RoutedEventArgs e)

  41.         {

  42.             GetIni();

  43.             imgCheckBtn.IsChecked = true;

  44.             circleCheckBtn.IsChecked = true;

  45.         }


  46.         //获取ini配置文件信息

  47.         private void GetIni()

  48.         {

  49.             ini_RW.FileName = System.Windows.Forms.Application.StartupPath + "\\Config.ini";

  50.             this.videoAddress.Text = ini_RW.ReadIni("VideoUrl", "videourl", "");

  51.             this.ipAddress.Text = ini_RW.ReadIni("ControlUrl", "controlUrl", "");

  52.             this.portBox.Text = ini_RW.ReadIni("ControlPort", "controlPort", "");

  53.         }


  54.         //修改配置

  55.         private void setBtn_Click(object sender, RoutedEventArgs e)

  56.         {

  57.             ini_RW.WriteIni("VideoUrl", "videourl", this.videoAddress.Text);

  58.             ini_RW.WriteIni("ControlUrl", "controlUrl", this.ipAddress.Text);

  59.             ini_RW.WriteIni("ControlPort", "controlPort", this.portBox.Text);


  60.             System.Windows.MessageBox.Show("配置成功!请重启程序以使配置生效。", "配置信息", MessageBoxButton.OK, MessageBoxImage.Information);

  61.             //this.Close();

  62.         }


  63.         //计数清零

  64.         private void BoxClean()

  65.         {

  66.             circleTextBox.Text = "0";

  67.             recTextBox.Text = "0";

  68.         }


  69.         //打开图片地址

  70.         private void imgBtn_Click(object sender, RoutedEventArgs e)

  71.         {

  72.             try

  73.             {


  74.                 BoxClean();

  75.                 //WPF中,OpenFileDialog位于Microsoft.Win32名称空间

  76.                 Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();

  77.                 dialog.Filter = "All files (*.*)|*.*|jpg files (*.jpg)|*.jpg|png files(*.png)|*.png";


  78.                 if (dialog.ShowDialog() == true)

  79.                 {


  80.                     string path = dialog.FileName;

  81.                     imgAddressBox.Text = path;

  82.                 }

  83.             }

  84.             catch { };

  85.         }


  86.         //检测形状判断

  87.         private void ShapeDetect(string address, int mode)

  88.         {

  89.             if (circleCheckBtn.IsChecked == true)

  90.             {

  91.                 //System.Windows.MessageBox.Show("检测圆形");

  92.                 circleTextBox.Text = HoughCircles(address, mode).ToString();

  93.             }

  94.             else if (recCheckBtn.IsChecked == true)

  95.             {

  96.                 //System.Windows.MessageBox.Show("检测矩形");

  97.                 SquareDetector(address, mode);

  98.             }

  99.         }


  100.         //图片检测

  101.         private void imgDetect()

  102.         {


  103.             if (imgAddressBox.Text == string.Empty)

  104.             {

  105.                 System.Windows.MessageBox.Show(

  106.                     "图片地址为空,请选择一张图片", "警告",

  107.                     MessageBoxButton.OK,

  108.                     MessageBoxImage.Information

  109.                     );

  110.                 return;

  111.             }

  112.             else

  113.             {

  114.                 ShapeDetect(imgAddressBox.Text, IMAGE_MODE);

  115.             }

  116.         }


  117.         //视频检测

  118.         private void videoDetect()

  119.         {

  120.             try

  121.             {

  122.                 while (true)

  123.                 {

  124.                     this.Dispatcher.Invoke(

  125.                         new Action(

  126.                             delegate

  127.                             {

  128.                                 string ip = this.videoAddress.Text;

  129.                                 ShapeDetect(ip, VIDEO_MODE);

  130.                             }

  131.                             ));

  132.                 }


  133.             }

  134.             catch { };

  135.         }


  136.         //判断检测为图片还是视频,开启形状检测

  137.         private void detectBtn_Click(object sender, RoutedEventArgs e)

  138.         {

  139.             BoxClean();

  140.             if (imgCheckBtn.IsChecked == true)

  141.             {

  142.                 imgDetect();

  143.             }

  144.             else if (videoCheckBtn.IsChecked == true)

  145.             {

  146.                 try

  147.                 {

  148.                     m_thread = new Thread(new ThreadStart(videoDetect));

  149.                     m_thread.Start();

  150.                 }

  151.                 catch { };

  152.             }

  153.         }


  154.         //按esc键退出视频检测,结束线程

  155.         private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)

  156.         {

  157.             if (e.Key == Key.Escape)

  158.             {

  159.                 exitEvent.Set();

  160.                 m_thread.Join();

  161.             }

  162.         }


  163.     }

  164. }
复制代码

      程序识别圆形及矩形两种形状,包括对图像以及视频中的物体的形状检测,可参考上面的演示视频进行操作。图片中物体的形状识别,文末资料下载中提供一张测试图片,然后选择图片按钮,选择要检测的圆形或者矩形,点击形状检测。
视频中的形状识别,选择视频按钮,选择要检测的圆形或者矩形,点击形状检测,可以使用球体或者矩形状物体进行检测。

4. 资料下载
资料内容:
​①识别形状-例程源代码
​②测试图片.jpg
资料下载地址:https://www.robotway.com/h-col-200.html

想了解更多机器人开源项目资料请关注 机器谱网站 https://www.robotway.com

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-28 17:42 , Processed in 0.039792 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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