一种简单视觉处理

背景

网友说他有个芯片的图,识别不出管脚的位置

俺就写了一个代码,识别管脚的位置,先看结果。

代码

识别图片,并显示结果,对于结果位置使用红色标出

            PT pt = new PT();pt.Find(bmp);Bitmap bmp_tmp = new Bitmap(bmp);Graphics g = Graphics.FromImage(bmp_tmp);StringBuilder sb = new StringBuilder();foreach (PtRec r in pt.Result){g.DrawRectangle(Pens.Red, new Rectangle(r.x1, r.y1, r.x2- r.x1+1, r.y2 - r.y1+1));sb.AppendLine(((r.x1 + r.x2) / 2).ToString() + "," + ((r.y1 + r.y2) / 2).ToString() + " Score:" + (r.v * 100).ToString("0.0"));}  g.Dispose(); pictureBox1.Image = bmp_tmp;textBox1.Text = sb.ToString();

识别的处理在class PT中

        public void Find(Bitmap bmp)
        {
            Result.Clear();
            Bmp2Array(bmp);
            Proc();
        }

Bmp2Array 将图片转化为灰度二维数组

Proc 计算管脚的位置

        private void Proc()
        {
            x_a = new int[Width * Height];
            y_a = new int[Width * Height];
            for (int y = step_len + 1; y < Height - step_len - 1; y++)
                for (int x = step_len + 1; x < Width - step_len - 1; x++)
                {
                    if (array[y, x] < max_gv)
                    {
                        PtRec r = new PtRec() { x1 = x, y1 = y, x2 = x, y2 = y, cnt = 0 };
                        Fill(x, y, r);
                        r.Check();
                        if (r.v>0.6)
                          Result.Add(r); 
                    }
                }
        }

使用Fill计出所有的区域,然后计算区域的符合度,v>0.6 添加到结果中。

r.Check 是计算符合度的函数

        public void Check()
        {
            int w = x2 - x1+1;
            int h = y2 - y1 + 1;
            int v1 = cnt * 100 / (w * h);
            int v2 = w * h;
            int v1_std = 80;
            int v2_std = 288;
            v = get_v(v1, v1_std) * get_v(v2, v2_std);
        }
        public float get_v(int v, int v_std)
        {
            if (v * v_std == 0)
                return 0;
            if (v < v_std)
                return 1.0F *v / v_std;
            else
                return 1.0F * v_std / v;
        }

这里有2个参数 ,v1_std = 80 和 v2_std = 288 对于不同大小的图像可以修改这里。

或者只用v1_std = 80 这个参数,就和图像大小无关了。不过另外需要加一个过滤,把特别小的和特别大的区域过滤掉,例如过滤掉

  • 宽度 小于 图片宽度 1%的区域
  • 高度 小于 图片宽度 1%的区域
  • 宽度 大于 图片宽度 15%的区域
  • 高度 大于 图片宽度 15%的区域

主要的计算在private void Fill(int x, int y, PtRec r) 中

       private void Fill(int x, int y, PtRec r)
        {
            c_a_last = 0;
            c_a = 1;
            x_a[0] = x;
            y_a[0] = y;
            int xi, yi;
            while (c_a > c_a_last)
            {
                int c = c_a;
                for (int i = c_a_last; i < c_a; i++)
                {
                    foreach (Point pt in step)
                    {
                        xi = x_a[i] + pt.X;
                        yi = y_a[i] + pt.Y;
                        if (xi < 0)
                            continue;
                        if (yi < 0)
                            continue;
                        if (xi >= Width)
                            continue;
                        if (yi >= Height)
                            continue;
                        if (array[yi, xi] < max_gv)
                        {
                            if (yi < r.y1)
                                r.y1 = yi;
                            if (yi > r.y2)
                                r.y2 = yi;
                            if (xi < r.x1)
                                r.x1 = xi;
                            if (xi > r.x2)
                                r.x2 = xi;
                            array[yi, xi] = 255;
                            r.cnt = r.cnt + 1;
                            x_a[c] = xi;
                            y_a[c] = yi;
                            c++;
                        }
                    }
                }
                c_a_last = c_a;
                c_a = c;
            }
        }

全部代码如下:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ImgPT
{public class PT{public void Find(Bitmap bmp){Result.Clear();Bmp2Array(bmp);Proc();}private void Proc(){x_a = new int[Width * Height];y_a = new int[Width * Height];for (int y = step_len + 1; y < Height - step_len - 1; y++)for (int x = step_len + 1; x < Width - step_len - 1; x++){if (array[y, x] < max_gv){PtRec r = new PtRec() { x1 = x, y1 = y, x2 = x, y2 = y, cnt = 0 };Fill(x, y, r);r.Check();if (r.v>0.6)Result.Add(r); }}}public int[] x_a;public int[] y_a;public int c_a_last;public int c_a;private void Fill(int x, int y, PtRec r){c_a_last = 0;c_a = 1;x_a[0] = x;y_a[0] = y;int xi, yi;while (c_a > c_a_last){int c = c_a;for (int i = c_a_last; i < c_a; i++){foreach (Point pt in step){xi = x_a[i] + pt.X;yi = y_a[i] + pt.Y;if (xi < 0)continue;if (yi < 0)continue;if (xi >= Width)continue;if (yi >= Height)continue;if (array[yi, xi] < max_gv){if (yi < r.y1)r.y1 = yi;if (yi > r.y2)r.y2 = yi;if (xi < r.x1)r.x1 = xi;if (xi > r.x2)r.x2 = xi;array[yi, xi] = 255;r.cnt = r.cnt + 1;x_a[c] = xi;y_a[c] = yi;c++;}}}c_a_last = c_a;c_a = c;}}private static int max_gv = 128;private static int step_len =2;private static List<Point> step = make_step();private static List<Point> make_step(){List<Point> list = new List<Point>();for (int y = -step_len; y <= step_len; y++)for (int x = -step_len; x <= step_len; x++){if ((y == 0) && (x == 0))continue;list.Add(new Point(x, y));}return list;}private void Bmp2Array(Bitmap v){Width = v.Width;Height = v.Height;array = new int[Height, Width];Bitmap bmp = new Bitmap(v.Width, v.Height, PixelFormat.Format24bppRgb);Graphics g = Graphics.FromImage(bmp);g.DrawImage(v, 0, 0);g.Dispose();BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);int len = bmpdata.Stride;byte[] buff = new byte[len];int idx = 0;byte blue, green, red, gv;for (int y = 0; y < Height; y++){IntPtr p = bmpdata.Scan0 + len * y;System.Runtime.InteropServices.Marshal.Copy(p, buff, 0, len);for (int x = 0; x < Width; x++){idx = x * 3;blue = buff[idx];green = buff[idx + 1];red = buff[idx + 2];gv = (byte)(0.229 * red + 0.587 * green + 0.144 * blue);array[y, x] = gv;}}bmp.UnlockBits(bmpdata);bmp.Dispose();}private int Width;private int Height;private int[,] array;public List<PtRec> Result = new List<PtRec>();}public class PtRec{public int x1;public int y1;public int x2;public int y2;public int cnt = 0;public float v = 0;public void Check(){int w = x2 - x1+1;int h = y2 - y1 + 1;int v1 = cnt * 100 / (w * h);int v2 = w * h;int v1_std = 80;int v2_std = 288;v = get_v(v1, v1_std) * get_v(v2, v2_std);}public float get_v(int v, int v_std){if (v * v_std == 0)return 0;if (v < v_std)return 1.0F *v / v_std;elsereturn 1.0F * v_std / v;}}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPT-4、Claude 3 Opus 和 Gemini 1.0 Ultra 挑战控制工程的新领域

介绍 论文地址&#xff1a;https://arxiv.org/abs/2404.03647 近年来&#xff0c;GPT-4、Claude 3 Opus 和 Gemini 1.0 Ultra 等大规模语言模型&#xff08;LLM&#xff09;迅速发展&#xff0c;展示了它们解决复杂问题的能力。LLM 的这些发展在多个领域都有潜在的应用前景。…

Adobe After Effects的插件--------CC Ball Action

CC Ball Action是粒子效果器,其将2D图层变为一个个由3D小球构成的图层。它是AE内置的3D插件。 使用条件 使用该插件的图层需是2D图层。 我们以一张图片素材为例: 给图片图层添加CC Ball Action效果控件,然后新建一个摄像机(利用摄像机旋转、平移、推拉工具,方便在各个角…

探究Python中的函数与模块

一、引言 随着程序的复杂度增加&#xff0c;代码的组织与重用性就显得尤为重要。为了编写更加结构化、易于维护的代码&#xff0c;函数和模块的使用是必不可少的。 函数是Python中最基本的代码组织形式&#xff0c;通过将代码封装成函数&#xff0c;我们可以实现代码的重用、…

C++不同数据类型连接成一个字符串

在C中数据连接的方式使用号进行连接。 1.都是字符型时直接使用连接几个字符串&#xff1b; 2.不是字符类型时&#xff0c;要用to_string函数转换后再连接。

【C语言】浮点型数据在内存中的储存

浮点型数据在内存中的储存 文章目录 浮点型数据在内存中的储存引例概念提出浮点型数据储存规定对于有效数字M的特别规定对于指数E的特别规定指数E的储存指数E的读取 利用规则解释原因 在之前学习过整形数据在内存中的储存后&#xff0c;浮点型数据在内存中的储存又会怎样呢&…

android 实现简易音乐播放器

音乐App 源代码 &#xff1a; 简易音乐APP源代码 1、简介 一个简易的音乐APP&#xff0c;主要练习对四大组件的应用。感兴趣的可以看看。 播放界面如下&#xff1a; 歌曲列表界面如下&#xff1a; 项目结构如下&#xff1a; 接下来将对代码做详细介绍&#xff1a; 2、Musi…

Leetcode876. 链表的中间结点(双指针)

题目描述 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例&#xff1a; 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释&#xff1a;链表只有一个中…

【蓝桥杯冲刺省一,省一看这些就够了-C++版本】蓝桥杯C++STL及相关练习题

蓝桥杯历年省赛真题 点击链接免费加入题单 STL map及其函数 map<key,value> 提供一对一的数据处理能力&#xff0c;由于这个特性&#xff0c;它完成有可能在我们处理一对一数据的时候&#xff0c;在编程上提供快速通道。map 中的第一个值称为关键字(key)&#xff0c;…

python 多进程 多线程 程序

这个纯粹为了增加理解&#xff0c;将很多比较好的资料进行归纳总结。 1、理论汇总 并发和并行 image.png 多进程和多线程 同步和异步 同步&#xff1a;所谓同步&#xff0c;就是在发出一个功能调用时&#xff0c;在没有得到结果之前&#xff0c;该调用就不会返回。 异步…

C语言刷题日记(附详解)(2)

一、有理数加法 输入格式&#xff1a; 输入在一行中按照a1/b1 a2/b2的格式给出两个分数形式的有理数&#xff0c;其中分子和分母全是整形范围内的正整数。 输出格式&#xff1a; 在一行中按照a/b的格式输出两个有理数的和。注意必须是该有理数的最简分数形式&#xff0c;若…

​14:00面试,14:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

Linux系统下的容器安全:深入解析与最佳实践

在云计算和微服务架构的推动下&#xff0c;容器技术因其高效、可移植和灵活的特点&#xff0c;已经成为现代软件开发和部署的首选方案。然而&#xff0c;容器的广泛应用也带来了新的安全挑战&#xff0c;尤其是在Linux系统下&#xff0c;容器安全的实现和维护变得尤为重要。本文…

如何使用python脚本爬取微信公众号文章?

1、什么是爬虫&#xff1f; 在座的各位可能经常听到一个词&#xff0c;叫“爬虫”&#xff0c;这是一种能够悄无声息地将网站数据下载至本地设备的程序。利用爬虫&#xff0c;您无需亲自访问特定网站&#xff0c;逐个点击并手动下载所需数据。相反&#xff0c;爬虫能够全自动地…

STM32——PWM波形输出

一、IC和OC 可以看到&#xff1a;定时器除了基本的定时中断功能&#xff0c;输入捕获、输出比较均是STM32定时器的功能 输入捕获IC&#xff08;Input Capture&#xff09; 输入捕获是一种用于测量外部信号脉冲宽度或频率的技术。它通过定时器模块捕获外部信号的特定事件&…

2024年AI编程新手必备工具,快速提升技能!

在当今这个技术日新月异的时代&#xff0c;AI编程已成为一个越来越重要的领域&#xff0c;吸引着众多新手和希望提升自己的中级开发者进入。 对于这些渴望在AI领域快速成长的人来说&#xff0c;选择合适的编程工具是至关重要的。 接下来&#xff0c;我们将深入探讨几款市场上…

Aria2安装和使用-Mac版

起因是需要网盘下载&#xff0c;无奈限速很烦&#xff0c;查找很多方案后&#xff0c;最终决定使用Aria2 Tampermonkey。 其中Aria2是一款开源轻量的下载软件&#xff0c;简单来说就是可以通过URL直接下载。 Tampermonkey则是一款插件&#xff0c;我这里是.crx结尾的谷歌插件…

抢单源码修正版,带教程,自动抓取订单,十几种语言可自动切换

亚马逊抢单源码自动抓取订单任务邀请英文,西班牙语可自动切换语言亲测修正版。带完整开源的前后台。 西班牙,英文&#xff0c;巴西&#xff0c;中文&#xff0c;德国&#xff0c;拉法兰西&#xff0c;荷兰&#xff0c;缅甸&#xff0c;Sverige&#xff0c;日本&#xff0c;Trk…

专利权和版权有什么区别?

专利权和版权有什么区别&#xff1f;

SD差点挂掉,后备军们兴奋入场,AI生图应用正在爆发?

前后不到一个月&#xff0c;两个开源生图模型相继上线。 首先是由称得上 SD 原班人马的黑森林实验室推出的 FLUX.1。黑森林实验室由 Stable Diffusion 的核心开发者 Robin Rombach 领衔创立&#xff0c;团队成员基本上都是 Stable Diffusion 3 的作者&#xff0c;其中三名元老…

内存管理篇-04伙伴系统

本小节有几个重要的知识点&#xff1a; 伙伴系统的思想伙伴系统的实现伙伴系统分配器&#xff1a;内存块的申请、释放过程伙伴算法和阶数 1.伙伴系统的思想 针对某个某个zone分区&#xff0c;&#xff08;1&#xff09;把物理地址相连的空闲页连接起来合成一个物理块&#xf…