机器视觉入门之路(六十,神奇的线图像第五变,找圆工具匹配识别实现)

本文主要是介绍机器视觉入门之路(六十,神奇的线图像第五变,找圆工具匹配识别实现),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先看一幅图:

这本是一幅2448*2048(W*H)的图像,而我只截取了其下半截,这里边有近似圆的东西(岳云的铜锤),我们怎么找到它呢?是的,眼睛已经搞定,但是计算机还搞不定,我们如何让视觉与计算心照不宣

首先,使用我们的找圆工具学习(learning):

a,截取感兴趣区域;b,使用找圆工具找到圆心和半径以及其他。

第二幅图怎么变成黑白图了?是的,图像进行了二值化,大于灰度100,全为255白,否则,为0黑。然后,把我们的找圆工具拖上去,调整,穿越点全部跳出来了。(线工具的功劳!)好,拟合圆,下面显示了结果和使用到的参数:

以上是我们学习(learning)到的条件,够了吗?还缺什么?有什么不足?不知道!好,我们先捋一捋如何匹配:

1,整图以灰度100为门槛,二值化。2,让找圆工具在二值化整图中从左到右,从上到下依次比对穿越点及其拟合得到的半径。

3,直到比对成功。是的,最关键是第二步,找圆工具画500万次,拟合圆计算500万次,我的个神啊!测试后,电脑不动了,显然是挂了。我们能否只比对圆上线段内白(起点,终点)外黑?或者部分线段?或者部分计算?不需要画出找圆工具?是的,是这样,改进第二步如下:

a,因为有半径,所以要避开w-2*半径,h-2*半径区域。

b,因为计算机查找的速度远远大于计算的速度,所以要利用圆上线段(线图像起终点)相对圆心是固定不变的特性。

c,舍去圆上0246区域,只使用1357区域的圆上线图像。(64(8*8)条线图像,考察32(4*8)条)

d,不再二值化整图中画找圆工具。

e,取1357区域的10条连续线图像计算其穿越点与圆心关系,限定3个单位误差。

测试后效果出来了,大概2s,为了进一步扩大战果:再改进如下:

a,1357区域只考察16(4*4)条线图像,四个区域,每个区域8条线图像只取4条。

b,因为圆上有缺口,即线图像无穿越点,返回(0,0),在16(4*4)条线图像中要排除掉。

c,不足16条线,任意两条线的终点为黑,圆心为白,优先筛选。其次找5条连续线图像计算其穿越点与圆心关系,限定2.5个单位误差。

d,找出缺口方向。

实现后测试,进入500ms级。另外发现,图像二值化后,门槛值20失效了。现在回头,就知道我们 来时学习(learning)到了什么条件。更新outer是需要的线图像终点,更新inner是需要的线图像起始点,更新关键点是第一线图像终点及最后一个线图像终点,关键缺口方向在64个穿越点中找出。下面贴出结果和代码:

第一步,加载关键点:

 int binthreshold = Convert.ToInt32(textBoxBIN.Text);
            //此处判断黑白              
            if (((int)圆半径) == 0) return;
            string str1 = textBox1关键匹配点.Lines[0];
            char[] separator = { ',' };
            string[] splitstr1 = new string[2];
            splitstr1 = str1.Split(separator);

            Point temp1 = new Point((Convert.ToInt16(splitstr1[0])),
                    (Convert.ToInt16(splitstr1[1])));

            str1 = textBox1关键匹配点.Lines[1];//
            splitstr1 = str1.Split(separator);
            Point temp2 = new Point((Convert.ToInt16(splitstr1[0])),
                      (Convert.ToInt16(splitstr1[1])));

第二步:整图二值化:

  textBox3.Text = DateTime.Now.ToString();
            /
            globclonebuff = new byte[2048 * 2448];
            for (int i = 0; i < 2048; i++)
                for (int j = 0; j < 2448; j++)
                {
                    int instead = i * 2448 + j;

                    globclonebuff[instead] = (glob_buffer8[instead] >= (byte)binthreshold ? (byte)255 : (byte)0);

                }

      DateTime dt=DateTime.Now;
            textBox1.Text = dt.ToString();

            PointF recordPt = new PointF();
            int thres = Convert.ToInt32(tbThresforCirle.Text);
            int CirR = (int)(gaugeCir.m_cirRoi.m_RoiCircle.m_Radius + gaugeCir.m_cirRoi.m_RoiCircle.m_tolerance +
                15 + 2); 

if (圆内点.Count == 0) return;

第三步:循环中优先考察关键点和圆心匹配:

 for (int h = CirR; h < 2048 - CirR; h++)//活动范围0+r,2048-r//
            {
                for (int w = CirR; w < 2448 - CirR; w++)
                {//拖动circlecaliper,重置他的位置
                    gaugeCir.m_cirRoi.m_RoiCircle.Drag(new PointF(w, h));//此处默认为255白
                      Point outpoint1 = new Point(); Point outpoint2 = new Point();
                    outpoint1.X = temp1.X - (int)(圆心x + 0.5) + w;
                    outpoint1.Y = temp1.Y - (int)(圆心y + 0.5) + h;
                    outpoint2.X = temp2.X - (int)(圆心x + 0.5) + w;
                    outpoint2.Y = temp2.Y - (int)(圆心y + 0.5) + h;
                   // int getval1 = (int)(globclonebuff[outpoint1.X + outpoint1.Y * 2448]) / 255;
                    int getval1 = (int)globclonebuff[outpoint1.X + outpoint1.Y * 2448] == 0 ? 0 : 1;
                   // int getval2 = (int)(globclonebuff[outpoint2.X + outpoint2.Y * 2448]) / 255;
                    int getval2 = (int)globclonebuff[outpoint2.X + outpoint2.Y * 2448] == 0 ? 0 : 1;
                   // int getval3 = Math.Abs((int)(globclonebuff[w + h * 2448]) / 255 - 1);//为255白=1
                    int getval3 = (int)globclonebuff[w + h * 2448] == 0 ? 1 : 0;
                    if (gb_dirCirle == getval1 &&//默认dir=0为黑
                        gb_dirCirle == getval2 && gb_dirCirle == getval3)//请考虑方向变化后dir
                    {

第四步:考察连续5个穿越点与圆心关系:

                       int jishuqi = 0;//圆内点和圆外点一一对应,为一线图像
                        PointF[] 圆内点1 = 圆内点.ToArray();//更新inner
                        PointF[] 圆外点1 = 圆外点.ToArray();//更新outer
                        // 求新内外点(ref 圆内点1, ref 圆外点1, w, h);
                        int telen = 圆内点1.GetLength(0);
                        for (int i = 0; i < telen; i++)
                        {
                            圆内点1[i].X = (float)(圆内点1[i].X - 圆心x + w);
                            圆内点1[i].Y = (float)(圆内点1[i].Y - 圆心y + h);
                            圆外点1[i].X = (float)(圆外点1[i].X - 圆心x + w);
                            圆外点1[i].Y = (float)(圆外点1[i].Y - 圆心y + h);
                        }
                        //直接调用函数ver2第三步
                       
                        PointF[] BackResult = new PointF[telen];// 
                      
                        for (int i = 0; i < telen; i++)
                        {
                            PointF startxy = 圆内点1[i];
                            PointF endxy = 圆外点1[i];
                            if (startxy.X < 0 || startxy.X > 2448 - 1 ||
                               startxy.Y < 0 || startxy.Y > 2048 - 1 ||
                               endxy.X < 0 || endxy.X > 2448 - 1 ||
                               endxy.Y < 0 || endxy.Y > 2048 - 1) continue;
                            BackResult[i] = gaugeCir.DdaFindPtImprove(ref globclonebuff, 圆内点1[i], 圆外点1[i],
                                                                     //thres, gb_dirCirle, new Size(2448, 2048));
                                                                     //binthreshold
                                                                     binthreshold, gb_dirCirle, new Size(2448, 2048));
                            //if (BackResult[i].X != 0 && BackResult[i].Y != 0)
                            //{
                                //jishuqi++;
                            float deltaX = (BackResult[i].X - w);
                            float deltaY=(BackResult[i].Y - h);
                            if (Math.Abs(Math.Sqrt(deltaX * deltaX +
                                       deltaY * deltaY) - 圆半径) < 2.5)
                                {
                                    jishuqi++; if (jishuqi >= 5) break;
                                }
                                else { i = telen; }
                          //  }
                        }
                        if (jishuqi >= 5) //1357应该有32个样本点,此处使用16//考察5个201903291031
                        {
                            globMatchCirPt.X = w;
                            globMatchCirPt.Y = h;
                            h = 2048; w = 2448;
                        }
                    }
                }} textBox2.Text = (DateTime.Now-dt).ToString();
            gaugeCir.m_cirRoi.m_RoiCircle.Drag(new PointF((float)圆心x, (float)圆心y));//此处默认为255白
            pictureBox1.Invalidate();

Ok,结束,以下是在core m-5y10c的结果:

找圆工具以点带面进行匹配尝试,还不成熟,才实现一个月,肯定有不足,望指正;其实找线工具也可以匹配,有兴趣可以一试。

(待续..........................)

我的邮箱liuganggang_1978@163.com;734523623@qq.com

这篇关于机器视觉入门之路(六十,神奇的线图像第五变,找圆工具匹配识别实现)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/155802

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount