如何实现视觉识别颜色

news2024/11/23 0:01:34

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. 资料内容

识别颜色-例程源代码

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/425725.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程【TCP流套接字编程】

目录 TCP流套接字编程 1.ServerSocket API 2.Socket API 3.TCP中的长短连接 4.回显程序(短连接) 5.服务器和客户端它们的交互过程 6.运行结果及修改代码 TCP流套接字编程 ❗❗两个核心&#xff1a;ServerSocket Socket 1.ServerSocket API ✨ServerSocket 是创建…

RK3568平台开发系列讲解(Linux系统篇)Linux 目录结构介绍

🚀返回专栏总目录 文章目录 一、 linux 目录结构二、 linux 文件层次标准三、 linux 目录结构沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们从目录管理入手,会更直观的理解 linux 的目录结构。 一、 linux 目录结构 Linux 整个文件系统是以“ / ”目录开…

Cobalt_Strike_4.5渗透工具的安装与使用

前言&#xff1a; Cobalt Strike是一款内网渗透测试神器&#xff0c;Cobalt Strike分为客户端和服务器端&#xff0c;该服务器端被称为团队服务器&#xff0c;是Beacon有效负载的控制器&#xff0c;同时&#xff0c;cobalt strike也具有社会工程学功能&#xff0c;团队服务器还…

企业如何使用OA系统?OA系统有哪些功能和应用的场景?

企业如何使用OA系统&#xff1f;OA系统有哪些功能和应用的场景&#xff1f; 办公自动化&#xff08;Office Automation&#xff0c;简称OA&#xff09;&#xff0c;是将计算机、通信等现代化技术运用到传统办公方式&#xff0c;进而形成的一种新型办公方式。办公自动化利用现代…

02_Uboot基本命令与内存命令

目录 U-Boot命令使用 信息查询命令 环境变量操作命令 内存操作命令 U-Boot命令使用 进入uboot的命令行模式以后输入“help”或者“&#xff1f;”,然后按下回车即可查看当前uboot 所支持的命令,如图所示: 图中只是uboot的一部分命令,具体的命令列表以实际为准。图中的命令…

Mongo初遇回忆录

序 上周&#xff0c;我和M女士分手了&#xff0c;也许是上个月&#xff0c;我不知道。也许是她太墨守成规&#xff0c;也许是我太肆意妄为&#xff0c;她说我给不了她想要的平稳和安定。她没有留下太多东西&#xff0c;我也不愿留下更多回忆。 做决定的过程中&#xff0c;我比…

「计算机控制系统」4. 计算机控制系统分析

Z平面 稳定性分析 稳态误差分析 动态过程分析 频率特性 文章目录Z平面与S平面的映射关系稳定性分析离散Routh判据Jury判据离散Nyquist判据稳态误差静态误差系数动态过程频率特性Z平面与S平面的映射关系 S平面虚轴的映射 ω\omegaω与θ\thetaθ的映射 可以看出从S平面到Z平面…

远程组态管理的好处

远程组态管理可以简化管理工作&#xff0c;帮助您节省时间和金钱。远程组态管理可以通过各种应用程序来实现&#xff0c;包括&#xff1a; •监控所有设备的状态&#xff0c;以确保它们正常工作。 •记录现场数据&#xff0c;例如温度&#xff0c;压力或流量。 •快速、轻松地…

自动驾驶「时过境迁」,这家头部出行服务平台再出发

滴滴自动驾驶复活了&#xff1f; 昨日&#xff0c;滴滴正式发布了首个自动驾驶自动运维中心&#xff0c;以及首款未来服务概念车DiDi Neuron&#xff0c;同时还公布了在技术、硬件、量产以及新业务探索方面的进展。 按照计划&#xff0c;滴滴自动驾驶正在结合新能源整车企业能…

【单链表】的增删查改

&#x1f58a;作者 : Djx_hmbb &#x1f4d8;专栏 : 数据结构 &#x1f606;今日分享 : “Onc in a blu moon” : “罕见的,千载难逢的” (出现在19世纪,指的是"在一个月内出现的第二次圆月”&#xff0c;这种现象每隔32个月发生一次。) 文章目录✔单链表的功能实现:&…

大前端突围之路:从RN跨平台到大前端全栈统一

本文首发自「慕课网」(imooc.com)&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注"慕课网"&#xff01; 作者&#xff1a;FE大公爵|慕课网讲师 前言 不知不觉&#xff0c;在大前端领域也混迹十年了&#xff0c;一路的经历不敢说…

接口自动化测试yaml+requests+allure技术,你学会了吗?

目录 前言 一、什么是接口自动化测试 二、为什么要进行接口自动化测试 三、接口自动化测试的流程 四、yaml语言介绍 五、requests库介绍 六、allure技术介绍 七、总结 前言 接口自动化测试是在软件开发过程中常用的一种测试方式&#xff0c;通过对接口进行自动化测试&a…

SQL Sever 单表数据查询(下)

提示&#xff1a;本篇文章是在上篇文章的基础上进行单表数据查询操作的补充,主要以例题的方式呈现. 文章目录前言1.分组&#xff1a;统计各门课程的选修人数2.分别统计男女生的平均年龄3.查询所有科目成绩在85分以上的学生的学号及其平均分4.查询平均年龄大于18岁的系部和平均年…

Linux复习 / 动静态库QA梳理 | 如何使用第三方库?

文章目录前言Q&A概念Q&#xff1a;使用静态库和使用动态库的程序有什么区别&#xff1f;Q&#xff1a;什么是静态链接/动态链接&#xff1f;使用与制作Q&#xff1a;如何制作动静态库&#xff1f;Q&#xff1a;如何使用第三方库&#xff1f;Q&#xff1a;程序加载时&#x…

C语言-实现顺序二叉树和平衡二叉树AVL

1. 结构体 在实现二叉树之前先看下结构体的一些使用方法 数组是保存一系列相同的数据。在实际问题中&#xff0c;一组数据往往有很多种不同的数据类型。例如&#xff0c;登记学生的信息&#xff0c;可能需要用到 char型的姓名&#xff0c;int型或 char型的学号&#xff0c;in…

4.6--计算机网络之TCP篇之TCP的基本认识--(复习+深入)---好好沉淀,加油呀

1.TCP 头格式有哪些&#xff1f; 序列号&#xff1a; 在建立连接时由计算机生成的随机数作为其初始值&#xff0c;通过 SYN 包传给接收端主机&#xff0c;每发送一次数据&#xff0c;就「累加」一次该「数据字节数」的大小。 用来解决网络包乱序问题。 确认应答号&#xff1a; …

MySQL优化——Explain分析执行计划详解

文章目录前言一. 查看SQL执行频率二. 定位低效率执行SQL三. explain分析执行计划3.1 id3.2 select_type3.3 table3.4 type3.5 key3.6 rows3.7 extra四. show profile分析SQL前言 在应用的的开发过程中&#xff0c;由于初期数据量小&#xff0c;开发人员写 SQL 语句时更重视功能…

酷炫的3D智慧工厂不会打造?这40+可视化大屏模板千万别错过!

数字化已成为各行各业的重要趋势&#xff0c;因为数字化能够带来精准的效益提升。小米公司最近推进了黑灯工厂业务。”24小时熄灯操作&#xff0c;全程无人工干预”&#xff0c;这是小米智能工厂的重要特征。走进工厂&#xff0c;闪烁的灯带提示生产正在进行&#xff0c;机器通…

【Spring从成神到升仙系列 四】从源码分析 Spring 事务的来龙去脉

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…

【ChatGPT】Prompt Engineering入门

Prompt Engineering入门一、什么是 Prompt Engineering&#xff1f;二、我们还需要学习 PE 吗&#xff1f;三、Prompt基础原则一、什么是 Prompt Engineering&#xff1f; 简单的理解它是给 AI 模型的指令。它可以是一个问题、一段文字描述&#xff0c;甚至可以是带有一堆参数的…