当前位置: 首页 > article >正文

opencv简单图形数组识别

使用opencv的数组排列做一些简单图形得判断(不使用轮廓命令),比如矩形,圆形,三角形,横线,竖线;
首先我们考虑从图像生成的数组进行判断,将图片转化成灰度,然后从图像不等于255的点是否连续出现入手,创建一个图片75x50(横75高50,小一点图片方便看数据),选择1px的画笔,否则容易出现误差

image2 = cv2.imread("yuan.jpg", 0) 
print("image2",image2) 

用这两句命令即可打印出图片的数组,但是显示不完全,加上下面的命令使数据显示完整

import cv2
import numpy as np

np.set_printoptions(threshold=np.inf)
image2 = cv2.imread("yuan.jpg", 0) 
pixel_matrix = np.array(image2)
cv2.imshow("flower", image2)
cv2.waitKey() 
cv2.destroyAllWindows()
print("image2",pixel_matrix) 

得到数组:
在这里插入图片描述
由此发现,我们得到的数组并不像预想的精确,该是一个黑色像素的地方可能连接出现好几个接近255的值,可能会影响判断。
此处也要考虑线所占的像素数,我们先预知线段的粗细,也就是每个点所占的像素点,在win自带的画图软件中,线段粗细是会显示几个像素点的(鼠标停留一下),可选择1px,这样比较不会影响识别结果,那如果我们不是自己画线段,无法预知线段的粗细,我们可以在代码里加上一句(只是线段,其他形状容易产生误差),

for i in range(0, image2.shape[0]): 
    a = 0
    for j in range(0, image2.shape[1]):
       if image2[i][j] != 255
           a = a + 1
           print(a) #如果线段的点占8px,这里会输出81,因为这里的break是跳出j的循环,也就是一旦进入if,这一横排就不再扫描了,而粗线横竖都占8px,所以向下还会扫到一次直到8break
    if a>10:
     print("heng")
     break

这是灰度图的数组,下面我们来看二值图像的显示数组,二值图像(Binary Image)是一种特殊类型的图像,其中每个像素只有两种可能的灰度值,通常是0和255。这两个值分别代表黑色和白色,因此二值图像也被称为黑白图像或单色图像。在二值图像中,不存在灰度的中间值,只有纯黑和纯白两种颜色,使得图像具有明显的对比效果。
cv2.threshold这个命令有两个返回值1,实际使用的阈值(通常大于240就会被赋值255,但实际情况也可能被调整),2,二值化后图像,_, binary表示省略第一个返回值,第二个赋给binary
cv2.THRESH_BINARY_INV:阈值处理的模式。THRESH_BINARY_INV 表示反向二值化,即大于阈值(阈值一般为240)的像素设为0,小于等于阈值的像素设为255

_, binary = cv2.threshold(image2, 240, 255, cv2.THRESH_BINARY_INV)
print("binary",binary)

输出结果可以看出,经过二值反向变化,数组清晰很多,圆的顶点并非一个点而是一个线段,中部一行会只有两个点是255
在这里插入图片描述
下面我们可以根据输出数值找到各个轮廓的特征,加以判断
先将每一行255的点的个数找出来压在一个列表

list=[]
for i in range(0, binary.shape[0]):
    a = 0

    for j in range(0, binary.shape[1]):
       if binary[i][j] == 255:
           a = a + 1
    list.append(a)    
print(list)

对比几个轮廓的区别:(我这里是75x50,线条都是1px)
三角:

[0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

圆形:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

横线:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

竖线:

[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

矩形:

[0, 0, 0, 0, 0, 0, 0, 0, 38, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

识别图片的代码如下:

if sum(1 for x in list if x != 0) == 1:  #如果是横线则列表里只有一个数字遍历列表 my_list 中的每个元素 x。如果元素 x 不等于 0(即 x != 0),则生成一个 1print("heng")
s=sum(1 for x in list if x == 2) #如果是矩形算出列表里多少个2
print(sum(1 for x in list if x == 2))
for i in range(0,len(list)):
    if list[i] == 1 and list[i + 1] == 1: #竖线的话会连续出现1
        print("shu")
        break
    elif list[i] == 2 and list[i - 1] == 1: #三角形12连续出现
        print("Triangle")
        break
    elif list[i]==2 and list[i-1]==list[i+s] and list[i-1]-list[i]>3:  #矩形连续2的两头的数字相等,s为2的个数也就是连续出现2的左边的数字
        print("Rectangle")
        break
    elif list[i]==2 and list[i-1]-list[i]<3:
        print("Circle")
        break

http://www.kler.cn/a/612085.html

相关文章:

  • React 中如何使用ref来访问 DOM 元素或组件实例,有哪些注意事项?
  • Cudann 11.8同时安装tensorflow, pytorch
  • Kafka 的延迟队列、死信队列和重试队列
  • Android设计模式之观察者模式
  • Android 项目缓存问题,某些依赖中的类会报错:Cannot resolve symbol
  • 若依专题——基础应用篇
  • Scala简介与基础
  • 远程办公新体验:用触屏手机流畅操作电脑桌面
  • SpringBoot动态配置数据源的几种实现方式
  • Spring事务与数据库事务的关系
  • 常见邮件协议
  • Oracle Database In-Memory 23ai 新特性
  • 【C++接入大模型】WinHTTP类封装:实现对话式大模型接口访问
  • 适合DBA的brew上手指南
  • (C语言)网络编程之TCP(含三次握手和四次挥手详解)
  • 适配器模式及其典型应用
  • Vue-create-vue-开发流程-项目结构-API风格-ElementPlus-入门准备工作
  • 【保姆级别教程】VMware虚拟机安装Mac OS15苹果系统附带【VMware TooLS安装】【解锁虚拟机】和【Mac OS与真机共享文件夹】手把手教程
  • 分布式共识算法解密:从Paxos到Raft的演进之路
  • 使用string和string_view(一)——C风格字符串、字符串字面量和std::string