如何实现视觉识别颜色

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):

using System;

using System.IO;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

using System.Windows.Media.Animation;

using System.Threading;

using OpenCvSharp;

using System.Drawing;

using System.Drawing.Imaging;


namespace Color_Detect

{

    /// <summary>

    /// Color_Detect

    /// </summary>

    public partial class MainWindow : System.Windows.Window

    {

        /*

         * 指针角度对应各颜色

         * 25 -> 红色

         * 90 -> 绿色

         * 150 -> 蓝色

         */

        int ANGLE_RED = 0;

        int ANGLE_GREEN = 0;

        int ANGLE_BLUE = 0;


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

        double numOfred = 0.0;

        double numOfgreen = 0.0;

        double numOfblue = 0.0;


        //创建视频图像实例

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

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

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


        //视频显示切换变量

        Boolean isChange = false;


        public MainWindow()

        {

            InitializeComponent();

        }


        private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            ANGLE_RED = 25;

            ANGLE_GREEN = 90;

            ANGLE_BLUE = 150;

        }


        //颜色指示动画函数

        int angelCurrent = 0;


        private void ColorIndicate(int where) {

            RotateTransform rt = new RotateTransform();

            rt.CenterX = 150;

            rt.CenterY = 185;


            this.indicatorPin.RenderTransform = rt;


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

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

            da.AccelerationRatio = 0.8;

            rt.BeginAnimation(RotateTransform.AngleProperty, da);


            switch (where) {

                case 25:

                    colorDisplay.Content = "红色";

                    break;

                case 90:

                    colorDisplay.Content = "绿色";

                    break;

                case 150:

                    colorDisplay.Content = "蓝色";

                    break;

                default:

                    colorDisplay.Content = "颜色指示";

                    break;

            }


            angelCurrent = where;

        }


        /// <summary>

        /// MatToBitmap(Mat image)

        /// </summary>

        public static Bitmap MatToBitmap(Mat image)

        {

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

        }


        /// <summary>

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

        /// </summary>

        public static BitmapImage BitmapToBitmapImage(Bitmap bitmap)

        {

            using (MemoryStream stream = new MemoryStream())

            {

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


                stream.Position = 0;

                BitmapImage result = new BitmapImage();

                result.BeginInit();

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

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

                result.CacheOption = BitmapCacheOption.OnLoad;

                result.StreamSource = stream;

                result.EndInit();

                result.Freeze();

                return result;

            }

        }


        //颜色检测函数

        private void filterColor() {

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

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


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

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

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


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

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


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

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

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


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


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

                    {

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

                        numOfred++;

                    }

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

                    {

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

                        numOfgreen++;

                    }

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

                    {

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

                        numOfblue++;

                    }

                }

            }


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

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

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


            if (rateOfred > 85)

            {

                ColorIndicate(ANGLE_RED);

            }

            else if (rateOfgreen > 85)

            {

                ColorIndicate(ANGLE_GREEN);

            }

            else if (rateOfblue > 85) {

                ColorIndicate(ANGLE_BLUE);

            }


            numOfred = 0;

            numOfgreen = 0;

            numOfblue = 0;

        }


        //视频显示函数

        private void ThreadCapShow()

        {


            while (true)

            {

                try

                {

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

                    if (frame.Empty())

                        break;


                    this.Dispatcher.Invoke(

                        new Action(

                            delegate

                            {

                                if (isChange)

                                {

                                    filterColor();

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

                                    resultColor = null;

                                }

                                else {

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

                                }

                            }

                            ));

                    //Cv2.WaitKey(100);

                    //bitimg = null;

                }

                catch { }

            }

        }


        //加载视频

        private void loadBtn_Click(object sender, RoutedEventArgs e)

        {

            if (originImage.Source != null) return;

            Thread m_thread = new Thread(ThreadCapShow);

            m_thread.IsBackground = true;

            m_thread.Start();

        }


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

        private void changeBtn_Click(object sender, RoutedEventArgs e)

        {

            if (!isChange)

            {

                isChange = true;

                changeBtn.Content = "返回";

            }

            else {

                isChange = false;

                changeBtn.Content = "切换";


                //指针角度归零

                ColorIndicate(0);

            }

        }

    }

}

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

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

4. 资料内容

识别颜色-例程源代码

资料内容详见 如何实现视觉识别-识别颜色

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
树莓派是一款功能强大的微型计算机,可以通过安装相应的软件包来实现颜色识别功能。而OpenCV是一款广泛使用的计算机视觉库,可以在树莓派上使用。 要在树莓派上实现颜色识别功能,首先需要安装OpenCV库。可以通过在终端中执行一系列的命令来完成安装。安装完成后,可以使用Python编写代码来进行颜色识别。 在编写代码之前,需要调用OpenCV库和其他必要的库,并读取摄像头的图像。然后,可以使用OpenCV的函数来转换图像的颜色空间,如将图像从RGB空间转换为HSV空间。 接下来,可以使用OpenCV提供的函数来定义颜色的双边阈值,以便在图像中检测到特定颜色的物体。例如,可以使用函数cv2.inRange()来确定图像中在设定的上下限之间的像素值。 最后,可以使用OpenCV提供的函数来找到检测到的颜色物体的轮廓,并在图像上进行标记。可以使用函数cv2.findContours()来找到轮廓,并使用函数cv2.drawContours()将轮廓绘制到图像上。 完成以上步骤后,将树莓派连接到摄像头,并运行编写的代码。树莓派将不断从摄像头读取图像,并进行颜色识别。识别到的颜色物体将在图像上被标记出来。 总之,通过在树莓派上安装OpenCV库,并编写相应的代码,就可以实现颜色识别功能。颜色识别可以应用于物体检测、机器人导航、智能家居等领域,并且可以通过使用不同的颜色空间和调整阈值来适应不同的应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值