极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2428|回复: 0

如何实现视觉识别颜色

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

1. 功能说明
       通过摄像头识别特定颜色(红、绿、蓝)。摄像头采集图像信息并通过WiFi将信息传递给PC端,然后PC端根据比例判断出目标颜色在色盘上的所属颜色后,指针便会指向对应颜色。

红、绿、蓝-色块

2. 电子硬件
     本实验中采用了以下硬件:

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

3. 功能实现
工作原理:
       ① 摄像头采集图像信息;
       ② 通过WiFi将信息传递给PC端(VS2015配置的OpenCV环境);
       ③ 在PC端修改红色色域范围,用于判断摄像范围内的红色像素;
采用HSV颜色模型


       ④ 计算检测在显示的摄像范围内的红色像素区域所占比例=红色像素范围/显示的摄像范围;
       ⑤ 根据比例判断目标颜色在色盘上所属颜色;
       ⑥ 指针指向对应颜色。

3.1硬件连接
       将摄像头与路由器连接,启动路由器,将PC连接到路由器的WIFI网络。
       本实验不需要用到主控板作为下位机,可直接通过WiFi将图像信号传递给PC端,所以无需下位机编程。
主控板与WiFi正常连线,给WiFi路由器模块通电。


接线说明:
       ① 将2510通信转接板连接到扩展板的扩展坞上面;
       ② 找到1根USB线,一端连接到2510通信转接板接口上,另一端连接到WiFi路由器USB接口上;
       ③ 将摄像头线连接到WiFi路由器接口上。

3.2示例程序
       下面提供一个可以进行3个颜色(红、绿、蓝)识别的参考例程(MainWindow.xaml.cs):
  1. using System;

  2. using System.IO;

  3. using System.Collections.Generic;

  4. using System.Linq;

  5. using System.Text;

  6. using System.Threading.Tasks;

  7. using System.Windows;

  8. using System.Windows.Controls;

  9. using System.Windows.Data;

  10. using System.Windows.Documents;

  11. using System.Windows.Input;

  12. using System.Windows.Media;

  13. using System.Windows.Media.Imaging;

  14. using System.Windows.Navigation;

  15. using System.Windows.Shapes;

  16. using System.Windows.Media.Animation;

  17. using System.Threading;

  18. using OpenCvSharp;

  19. using System.Drawing;

  20. using System.Drawing.Imaging;


  21. namespace Color_Detect

  22. {

  23.     /// <summary>

  24.     /// Color_Detect

  25.     /// </summary>

  26.     public partial class MainWindow : System.Windows.Window

  27.     {

  28.         /*

  29.          * 指针角度对应各颜色

  30.          * 25 -> 红色

  31.          * 90 -> 绿色

  32.          * 150 -> 蓝色

  33.          */

  34.         int ANGLE_RED = 0;

  35.         int ANGLE_GREEN = 0;

  36.         int ANGLE_BLUE = 0;


  37.         //各颜色像素所占窗口的比例

  38.         double numOfred = 0.0;

  39.         double numOfgreen = 0.0;

  40.         double numOfblue = 0.0;


  41.         //创建视频图像实例

  42.         VideoCapture capture = new VideoCapture("http://192.168.8.1:8083/?action=stream");

  43.         Mat frame = new Mat();   //存储视频每一帧图像像素

  44.         Mat resultColor = new Mat(); //存储检测后的颜色像素


  45.         //视频显示切换变量

  46.         Boolean isChange = false;


  47.         public MainWindow()

  48.         {

  49.             InitializeComponent();

  50.         }


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

  52.         {

  53.             ANGLE_RED = 25;

  54.             ANGLE_GREEN = 90;

  55.             ANGLE_BLUE = 150;

  56.         }


  57.         //颜色指示动画函数

  58.         int angelCurrent = 0;


  59.         private void ColorIndicate(int where) {

  60.             RotateTransform rt = new RotateTransform();

  61.             rt.CenterX = 150;

  62.             rt.CenterY = 185;


  63.             this.indicatorPin.RenderTransform = rt;


  64.             double timeAnimation = Math.Abs(angelCurrent - where) * 5;

  65.             DoubleAnimation da = new DoubleAnimation(angelCurrent, where, new Duration(TimeSpan.FromMilliseconds(timeAnimation)));

  66.             da.AccelerationRatio = 0.8;

  67.             rt.BeginAnimation(RotateTransform.AngleProperty, da);


  68.             switch (where) {

  69.                 case 25:

  70.                     colorDisplay.Content = "红色";

  71.                     break;

  72.                 case 90:

  73.                     colorDisplay.Content = "绿色";

  74.                     break;

  75.                 case 150:

  76.                     colorDisplay.Content = "蓝色";

  77.                     break;

  78.                 default:

  79.                     colorDisplay.Content = "颜色指示";

  80.                     break;

  81.             }


  82.             angelCurrent = where;

  83.         }


  84.         /// <summary>

  85.         /// MatToBitmap(Mat image)

  86.         /// </summary>

  87.         public static Bitmap MatToBitmap(Mat image)

  88.         {

  89.             return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(image);

  90.         }


  91.         /// <summary>

  92.         /// BitmapToBitmapImage(System.Drawing.Bitmap bitmap)

  93.         /// </summary>

  94.         public static BitmapImage BitmapToBitmapImage(Bitmap bitmap)

  95.         {

  96.             using (MemoryStream stream = new MemoryStream())

  97.             {

  98.                 bitmap.Save(stream, ImageFormat.Png); //格式选Bmp时,不带透明度


  99.                 stream.Position = 0;

  100.                 BitmapImage result = new BitmapImage();

  101.                 result.BeginInit();

  102.                 // According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed."

  103.                 // Force the bitmap to load right now so we can dispose the stream.

  104.                 result.CacheOption = BitmapCacheOption.OnLoad;

  105.                 result.StreamSource = stream;

  106.                 result.EndInit();

  107.                 result.Freeze();

  108.                 return result;

  109.             }

  110.         }


  111.         //颜色检测函数

  112.         private void filterColor() {

  113.             Mat hsvImage = frame.CvtColor(ColorConversionCodes.BGR2HSV);

  114.             resultColor = new Mat(hsvImage.Rows, hsvImage.Cols, MatType.CV_8UC3, Scalar.All(255));


  115.             double H = 0.0, S = 0.0, V = 0.0;

  116.             float area = (float)(hsvImage.Rows * hsvImage.Cols);

  117.             float rateOfred = 0, rateOfgreen = 0, rateOfblue = 0;


  118.             for (int i = 0; i < hsvImage.Rows; i++) {

  119.                 for (int j = 0; j < hsvImage.Cols; j++) {


  120.                     H = hsvImage.Get<Vec3b>(i, j)[0];

  121.                     S = hsvImage.Get<Vec3b>(i, j)[1];

  122.                     V = hsvImage.Get<Vec3b>(i, j)[2];


  123.                     var color = frame.Get<Vec3b>(i, j);


  124.                     if (((H >= 0 && H <= 10) || (H >= 125 && H <= 180)) && S >= 43 && V >= 46) //红色像素所在hsv范围

  125.                     {

  126.                         resultColor.Set<Vec3b>(i, j, color);

  127.                         numOfred++;

  128.                     }

  129.                     else if ((H >= 33 && H <= 83) && S >= 43 && V >= 46) //绿色像素所在hsv范围

  130.                     {

  131.                         resultColor.Set<Vec3b>(i, j, color);

  132.                         numOfgreen++;

  133.                     }

  134.                     else if ((H > 100 && H < 124) && S >= 43 && V >= 46) //蓝色像素所在hsv范围

  135.                     {

  136.                         resultColor.Set<Vec3b>(i, j, color);

  137.                         numOfblue++;

  138.                     }

  139.                 }

  140.             }


  141.             rateOfred = (float)(numOfred) / area * 100;

  142.             rateOfgreen = (float)(numOfgreen) / area * 100;

  143.             rateOfblue = (float)(numOfblue) / area * 100;


  144.             if (rateOfred > 85)

  145.             {

  146.                 ColorIndicate(ANGLE_RED);

  147.             }

  148.             else if (rateOfgreen > 85)

  149.             {

  150.                 ColorIndicate(ANGLE_GREEN);

  151.             }

  152.             else if (rateOfblue > 85) {

  153.                 ColorIndicate(ANGLE_BLUE);

  154.             }


  155.             numOfred = 0;

  156.             numOfgreen = 0;

  157.             numOfblue = 0;

  158.         }


  159.         //视频显示函数

  160.         private void ThreadCapShow()

  161.         {


  162.             while (true)

  163.             {

  164.                 try

  165.                 {

  166.                     capture.Read(frame); // same as cvQueryFrame

  167.                     if (frame.Empty())

  168.                         break;


  169.                     this.Dispatcher.Invoke(

  170.                         new Action(

  171.                             delegate

  172.                             {

  173.                                 if (isChange)

  174.                                 {

  175.                                     filterColor();

  176.                                     originImage.Source = BitmapToBitmapImage(MatToBitmap(resultColor));

  177.                                     resultColor = null;

  178.                                 }

  179.                                 else {

  180.                                     originImage.Source = BitmapToBitmapImage(MatToBitmap(frame));

  181.                                 }

  182.                             }

  183.                             ));

  184.                     //Cv2.WaitKey(100);

  185.                     //bitimg = null;

  186.                 }

  187.                 catch { }

  188.             }

  189.         }


  190.         //加载视频

  191.         private void loadBtn_Click(object sender, RoutedEventArgs e)

  192.         {

  193.             if (originImage.Source != null) return;

  194.             Thread m_thread = new Thread(ThreadCapShow);

  195.             m_thread.IsBackground = true;

  196.             m_thread.Start();

  197.         }


  198.         //切换视频显示,显示检测结果

  199.         private void changeBtn_Click(object sender, RoutedEventArgs e)

  200.         {

  201.             if (!isChange)

  202.             {

  203.                 isChange = true;

  204.                 changeBtn.Content = "返回";

  205.             }

  206.             else {

  207.                 isChange = false;

  208.                 changeBtn.Content = "切换";


  209.                 //指针角度归零

  210.                 ColorIndicate(0);

  211.             }

  212.         }

  213.     }

  214. }
复制代码

程序设定的颜色为红色、绿色、蓝色,可以使用色卡或者特定颜色的物体来检测。


注意:程序中的比例值设置为85%时,可以进行三种颜色的识别判断,建议测试的色块距离小一些,识别效果会更好。


4. 资料下载
资料内容:识别颜色-例程源代码
​资料下载地址:https://www.robotway.com/h-col-200.html

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

回复

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-4-28 15:10 , Processed in 0.051999 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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