本帖最后由 机器谱 于 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): - 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. 资料下载
资料内容:识别颜色-例程源代码
资料下载地址:https://www.robotway.com/h-col-200.html
想了解更多机器人开源项目资料请关注 机器谱网站 https://www.robotway.com
|