128105浏览
查看: 128105|回复: 0

【行空板Python入门教程】第十一课:屏幕变色龙

[复制链接]
本帖最后由 木子呢 于 2022-6-17 17:00 编辑

屏幕变色龙

变色龙是一种善变的树栖爬行类动物,在经过几千万年的衍化后,为了逃避天敌的侵犯和接近自己的猎物,它们形成了一种生物本能,常在不经意间改变身体颜色,从而让自己融入周围的环境之中。

然而,如此炫酷的技能,常常只能在故事中听到,那么有何方法让我们能身临其境地感受一下呢?

在这节课上,就让我们利用行空板的屏幕结合检测颜色的小工具来模拟呈现一个变色龙的效果吧!

【行空板Python入门教程】第十一课:屏幕变色龙图30
任务目标

借助颜色传感器来检测环境色,使屏幕上变色龙角色显示成相应检测到的颜色。
【行空板Python入门教程】第十一课:屏幕变色龙图25
知识点

  • 认识颜色传感器
  • 了解图像识别和图像的基本属性
  • 了解图像处理的一些类型
  • 认识opencv库
  • 学习使用opencv库进行图像处理的方法
  • 学习使用Pinpong库检测颜色的方法

材料清单

硬件清单:
【行空板Python入门教程】第十一课:屏幕变色龙图26

软件使用:Mind+编程软件x1

知识储备

1、什么是颜色传感器

颜色传感器是一种传感装置,能够识别物体的颜色。传感器发射光线在物体表面,根据反射光计算颜色的成分(红R,绿G,蓝B),然后输出RGB的值。传感器周围自带四个高亮LED,可以让传感器在低环境光的情况下依然能够正常使用。

Tips:使用时,将颜色传感器连接到IIC接口。取色时,注意将颜色传感器放在物体上方3-10mm处。

【行空板Python入门教程】第十一课:屏幕变色龙图1

2、什么是图像识别

(1)图像识别的概念

图像识别,是指利用计算机对数字图像进行处理、分析和理解,以识别各种不同模式的目标和对象的技术。

(2)图像识别的案例分析

本项目是常见的图像识别案例之一,下面让我们来看看它是如何实现的:

目的:将原图中“龙”的颜色(蓝),变成设定的背景图颜色(如某色rgb值为238 130 238)

画图实现步骤:

Step1:找出原图中的蓝色主体部分。

Step2:用画笔将蓝色主体部分绘制成该颜色。

计算机图像处理实现步骤:

Step1:检测出原图中的蓝色部分。方法是用HSV颜色空间得到蓝色掩膜图(图1)。

Step2:将背景图中要显示的图像抠出来。方法是用图1与背景图作掩膜运算,得到图2。

Step3:将图1按位取反,得到图3。

Step4:将原图与图3做掩膜运算,得到图4。

Step5:将图2与图4做按位或运算,得到图5(最终效果)。

Tips:具体的运算方法后续再介绍。
【行空板Python入门教程】第十一课:屏幕变色龙图27

(3)图像的基本属性

图像有一些基本属性,比如像素、尺寸、颜色等。计算机通过读取数据,可以得到图像的基本属性。

A、像素

像素,也叫像素点或像元,是最基本的构图元素。如下图,如果把图放的足够大,就能看到一个个像马赛克一样的小色块,这就是像素点。每个像素点为一种颜色,多个像素点在一起组成了丰富多彩的图片。

【行空板Python入门教程】第十一课:屏幕变色龙图2

B、尺寸

图片尺寸可以理解为图片横向和纵向的像素点数量。比如一张图片由100×100个像点组成,那么这张图片的尺寸就是100x100。

C、颜色

图像都是有颜色的,在计算机中,一般用颜色空间(也称色彩空间)来表示图像的颜色,比如常用的RGB、HSV颜色空间。颜色空间通过一组数字表示颜色,在不同的应用背景,有不同种类的颜色空间定义。

比如,在显示器中采用RGB颜色空间,这是基于物体发光定义的(RGB正好对应光的三原色:红Red、绿Green、蓝Blue);工业印刷中常用CMY颜色空间,这是基于光反射定义的(CMY对应了绘画中的三原色:青Cyan、品红Magenta、黄Yellow);HSV颜色空间是根据颜色的直观特性创建的(HSV对应为:色调Hue、饱和度Saturation、亮度Value)。

RGB颜色空间如下图所示,是一个包含Red、Green、Blue的三维空间。在图像识别中,我们可以使用一组向量来表示颜色,比如用(0,0,0)表示黑色、(255,255,255)表示白色。其中,0-255表示色彩空间被量化成256个数,最低亮度值为0,最高亮度值为255。在这个色彩空间中,有256*256*256种颜色。

【行空板Python入门教程】第十一课:屏幕变色龙图3

HSV颜色空间如下图所示,是一个包含色调Hue、饱和度Saturation、亮度Value的倒圆锥体模型。人的视觉系统对亮度的敏感度要强于色彩值,HSV颜色空间就是根据人眼的生理特征而创建的颜色模型。色调H取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°;饱和度S取值范围为0.0~1.0,从圆心开始往外延伸;亮度V取值范围为0.0(黑色)~1.0(白色),从圆锥的顶部向底部延伸。

【行空板Python入门教程】第十一课:屏幕变色龙图4

Tips:RGB颜色空间和HSV颜色空间是可以相互转换的。

3、图像处理

图像处理是图像识别过程中重要一环,一张图像可能包括海量的不明确的信息,图像处理的目的是消除图像中无关的信息,恢复有用的真实信息,增强有效信息的可检测性,最大限度地简化数据。比如,在下面图片中,通过增强图片亮度,图像更清晰了。

【行空板Python入门教程】第十一课:屏幕变色龙图5

图像的处理有很多种,这里我们只简单介绍一些常见的。

(1)图像灰度化

图像灰度化指以黑色为基准色,用不同亮度的黑色来显示图像,通常为从0%(白色)到100%(黑色)的亮度值。图像灰度化可以将彩色图转换为灰度图。

【行空板Python入门教程】第十一课:屏幕变色龙图6

在RGB模型中,R=G=B时表示为灰度颜色,其中R=G=B的值叫灰度值。在下图中,立方体中的虚线即为R=G=B时的灰度颜色。R=G=B=0时,灰度值为0,颜色为黑色;R=G=B=255时,灰度值为255,颜色为白色。

【行空板Python入门教程】第十一课:屏幕变色龙图7

(2)图像二值化

图像二值化是一种特殊的灰度化,就是将灰度值设置为0或255,也就是整个图像非黑即白。图像二值化的目的是尽可能的去除干扰信息,获取目标信息。一般会先将图片灰度化,再进行二值化。

图像二值化最常使用的方法是设定一个全局的阈值 T ,用 T 将图像分割为两类像素:大于 T 的像素群和小于 T 的像素群,然后将两类像素群分别设定为白色或黑色。这种方法称为固定阈值法。

设定不同的阈值对二值化的结果影响很大,比如在下图中,阈值不同时,图片细节有明显的不同。

【行空板Python入门教程】第十一课:屏幕变色龙图8

(3)图像的按位逻辑运算

图像的按位逻辑运算就是将两幅图的每个像素进行按位逻辑运算,简称位运算。

常见的位运算有4种:按位与、按位或、按位异或、按位取反

A、按位与运算

类比电路,与运算即:两个逻辑值都是真时,结果才为真。用 and 表示按位与运算,1表示真,0表示假。

【行空板Python入门教程】第十一课:屏幕变色龙图9

按位与运算是将数值转换成二进制值之后,在对应的位置上进行与运算。用表格说明如下。

【行空板Python入门教程】第十一课:屏幕变色龙图10

按位与运算特点:

将任何数值N(范围0-255)与数值0(二进制为0000 0000)进行按位与运算,都会得到数值0。

将任何数值N(范围0-255)与数值255(二进制为1111 1111)进行按位与运算,都会得到数值本身。

B、按位或运算

类比电路,或运算即:两个逻辑值只要有一个为真时,结果就为真。用 or 表示按位或运算。

【行空板Python入门教程】第十一课:屏幕变色龙图11

按位或运算是将数值转换成二进制值之后,在对应的位置上进行或运算。同样用表格说明。

【行空板Python入门教程】第十一课:屏幕变色龙图12

C、按位非运算

非运算是取反操作,类比电路,即:当输入为真时,结果为假;当输入为假时,结果为真。用 not 表示按位非运算。

【行空板Python入门教程】第十一课:屏幕变色龙图13

按位非运算是将数值转换成二进制值之后,在对应的位置上进行非运算。同样用表格说明。

【行空板Python入门教程】第十一课:屏幕变色龙图14

D、按位异或运算

异或运算也叫半加运算,类比电路,即:两个逻辑值相反时,结果才为真。用 xor 表示按位异或运算。

【行空板Python入门教程】第十一课:屏幕变色龙图15

按位异或运算是将数值转换成二进制值之后,在对应的位置上进行异或运算。同样用表格说明。

【行空板Python入门教程】第十一课:屏幕变色龙图16

彩图、二值化图等都可以进行位运算,实际就是将两张图的每个像素进行位运算,得出每个像素的结果,显示最终图片。在彩图中,每个像素以(R,G,B)值表示,位运算时,先将R、G、B值转换为二进制值,然后做位运算。比如,像素1(0,198,219)与像素2(198,219,1)进行按位异或运算时,先将所有数值转换成二进制数,如下表。

【行空板Python入门教程】第十一课:屏幕变色龙图17

然后将像素1与像素2的二进制值按位异或,结果如下。

【行空板Python入门教程】第十一课:屏幕变色龙图18

将结果转换为十进制,为(198,29,219),表示像素1(0,198,219)与像素2(198,219,1)的异或结果是(198,29,219)。当两张彩图做位运算时,实际就是对每一个像素做位运算,得出每个像素的结果,显示最终图片。

灰度图和二值化图的按位运算也是同理。需要注意的是,必须是尺寸一致的图像才能进行位运算。如果两张图片尺寸不一致,可以先剪裁成同一尺寸,再做位运算。

(4)图像掩膜

简单来说,掩膜是用一幅二值化图片对另外一幅图片进行局部的遮挡,一般将二值化图称为掩模图像。

比如下图中,用左边的二值化图对中间的彩图进行掩模,掩模的结果如右图所示。

【行空板Python入门教程】第十一课:屏幕变色龙图19

(5)图像的色彩空间转换

在图像的基本属性中,我们介绍了RGB颜色空间和HSV颜色空间,有的颜色空间是可以相互转换的,常用的转换有两种:BGR ↔Gray 和 BGR ↔HSV。在按颜色分割图像时,通常使用HSV颜色空间。

比如,在下图中,通过指定HSV颜色空间中的绿色,可以获取图1中绿色图案的轮廓,并将图像其他部分处理为黑色。我们将图2作为掩模图像,与图1做掩模运算,即可获得图3,分割出图1中的绿色部分。

【行空板Python入门教程】第十一课:屏幕变色龙图20

下图可以用于快速查找HSV颜色。横轴表示色调H,取值范围0-180,一般用色调H的值就可以确定一种颜色范围,比如H在50-80之间为绿色。通过指定色调H的范围,就能使用掩模的方法,分割出图像的指定颜色。

【行空板Python入门教程】第十一课:屏幕变色龙图21

4、什么是opencv库


Opencv的全称是Open source Computer Vision Library,它是一个开源的跨平台计算机视觉库,常用于图像处理和计算机视觉领域,可以运行在Linux、Windows、Android和Mac OS上。

Opencv由一系列 C 函数和少量 C++ 类构成,因此,它轻量且高效,并且提供了Python、Ruby、MATLAB等语言的接口,在Python中使用时,我们需要通过“import cv2”的方式来导入它,其中,cv2是opencv的C++命名空间名称,使用它来表示调用的是C++开发的opencv的接口。

5、Opencv库常见函数

Opencv库中的函数有很多,我们只使用其中的一部分。

(1)“imread()”函数读取指定图片

Opencv库中的“imread()”函数可以用于读取指定图片,使用时需要先导入opencv库。

  1. import cv2 # 导入opencv库sample = cv2.imread("img/sample.png")#读取img文件夹下sample.png图片,并命名为sample
复制代码

其中,“img/sample.png”指的是img文件夹下的sample.png这张图片。

Tips:通过“imread()”函数读取到的图像是以RGB为颜色空间的,且以BGR顺序排列。

(2)“namedWindow()”函数创建窗口

Opencv库中的“namedWindow()”函数可以用于创建一个图像窗口,并命名窗口和设定默认属性。

  1. cv2.namedWindow('winname',cv2.WND_PROP_FULLSCREEN) # Set the windows to be full screen.# 构建一个窗口,名称为winname,属性为可以全屏
复制代码

其中,“winname”指的是图像窗口的名称,“cv2.WND_PROP_FULLSCREEN”指窗口可以全屏的属性。

(3)“setWindowProperty()”函数设置图像窗口

Opencv库中的“setWindowProperty()”函数可以给指定的图像窗口设置一些特性。

  1. cv2.setWindowProperty('winname',cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN) # Set the windows to be full screen. # 设置窗口全屏
复制代码

其中,“winname”指的是图像窗口的名称,“cv2.WND_PROP_FULLSCREEN”指的是可以全屏的属性,“cv2.WINDOW_FULLSCREEN”指设置窗口全屏。

(4)“imshow()”函数显示图像

Opencv库中的“imshow()”函数可以用来在指定窗口上显示图像。

  1. sample = cv2.imread("img/sample.png")#读取img文件夹下sample.png图片,并命名为sample
  2. cv2.imshow('winname', sample) # 在winname窗口上显示图像sample
复制代码

其中,“winname”指的是要显示图像的窗口名称,“sample”指的是具体的图像。

(5)“waitKey()”函数等待键盘输入

Opencv库中的“waitKey()”函数本身表示等待键盘输入,能用来刷新图像,在括号中可以输入频率时间,单位是ms,表示在指定的时间内等待用户按键触发,不输入则默认为0,无限等待,显示当前的图像。

  1. cv2.waitKey()#刷新图像(等待用户按键触发,不写入参数默认为0,表示无限等待,显示最初的图像)
复制代码

(6)“destroyAllWindows()”函数关闭所有图像窗口

Opencv库中的“destroyAllWindows()”函数能用来关闭所有图像窗口,通常用于结束之时。

  1. cv2.destroyAllWindows() # 关闭所有窗口
复制代码

(7)“cvtColor()”函数转化图像的颜色空间

通过“imread()”函数读取到的图像是RGB颜色空间的,并且是以BGR顺序排列的,因此,为了便于按颜色分割图像,我们需要将它转换为HSV色彩空间,这里可以通过Opencv库中的“cvtColor()”函数来实现。

  1. sample = cv2.imread("img/sample.png")#读取img文件夹下sample.png图片,并命名为sample
  2. hsv = cv2.cvtColor(sample,cv2.COLOR_BGR2HSV)#将图像sample转换为HSV色彩空间并命名为hsv
复制代码

其中,sample指的是通过“imread()”函数读取到的以RGB为色彩空间的原图,“cv2.COLOR_BGR2HSV”指的是色彩空间的转换方式为BGR→HSV,hsv是一个变量,用于存储转换后的HSV色彩空间的图片。

(8)“inRange()”函数进行色彩阈值化处理

色彩阈值化处理是指从图像中找出一种指定颜色的轮廓,要想将图像上的颜色分割出来,我们需要先确定好该颜色。

Opencv库中的“inRange()”函数可以对HSV颜色空间的图像进行进行色彩阈值化处理。

  1. l = 50
  2. u = 80
  3. sample = cv2.imread("img/sample.png")#读取img文件夹下sample.png图片,并命名为sample
  4. hsv = cv2.cvtColor(sample,cv2.COLOR_BGR2HSV) # 将图像sample的色彩空间转换为HSV
  5. lower = np.array([l,90,90]) # 设阈值,下限值
  6. upper = np.array([u,255,255]) # 设阈值,上限值
  7. mask = cv2.inRange(hsv, lower, upper) # 去除背景部分,将图像hsv中低于lower或高于upper的图像值变为0,在lower~upper中间的值变为255
复制代码

其中,l的值50和u的值80分别对应色调H的范围;“lower”和“upper”分别是以此构成的两个颜色值,从下图中可以看出通过它们确定的颜色范围为绿色区域;hsv是以HSV为颜色空间的图像;mask是一个变量,用来存储经过色彩阈值化处理的图像。


(9)图像的按位逻辑运算

常见的4种图像按位逻辑运算在opencv库中可分别通过“cv2.bitwise_and()”、“cv2.bitwise_or()”、“cv2.bitwise_xor()”、“cv2.bitwise_not()”四个函数来实现。

【行空板Python入门教程】第十一课:屏幕变色龙图22

A、“cv2.bitwise_and()”函数进行按位与运算

  1. color =  np.zeros((320, 240, 3),dtype=np.uint8) # 创建一个三维零矩阵,类型为uint8
  2. color[:,:,0] = 12 # B # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  3. color[:,:,1] = 12 # G # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  4. color[:,:,2] = 12 # R # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  5. mask = cv2.inRange(hsv, lower, upper) # 色彩阈值化所得图
  6. B2 = cv2. bitwise_and(color,color, mask=mask)  # 按位与运算
复制代码

其中,“color”指的是原图,“mask”是另一张图,B2是先将两张原图进行与运算,再将得到的图与mask图进行与运算,最终得到的图。

B、“cv2.bitwise_or()”函数进行按位或运算

  1. color =  np.zeros((320, 240, 3),dtype=np.uint8) # 创建一个三维零矩阵,类型为uint8
  2. color[:,:,0] = 12 # B # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  3. color[:,:,1] = 12 # G # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  4. color[:,:,2] = 12 # R # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  5. mask = cv2.inRange(hsv, lower, upper) # 色彩阈值化所得图
  6. B3 = cv2.bitwise_or(color,mask) # 按位与运算
复制代码

其中,“color”指的是原图,“mask”是另一张图,B3是将两张图进行按位或运算后得到的图。

C、“cv2.bitwise_not()”函数进行按位取反运算

  1. color =  np.zeros((320, 240, 3),dtype=np.uint8) # 创建一个三维零矩阵,类型为uint8
  2. color[:,:,0] = 12 # B # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  3. color[:,:,1] = 12 # G # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  4. color[:,:,2] = 12 # R # 遍历所有行,遍历所有列,赋值蓝色通道的值为12
  5. mask = cv2.inRange(hsv, lower, upper) # 色彩阈值化所得图
  6. B4 = cv2.bitwise_not(object_mask)
复制代码

其中,“color”指的是原图,“mask”是另一张图,B4是将两张图进行按位取反运算后得到的图。

6、numpy库zero()函数创建零矩阵

Numpy是Python中的一个科学计算库。其中的array()函数我们已经学过,它可以用来创建一个数组(二维矩阵),除此之外,它还有很多别的函数。

(1)zero()函数创建一个多维零矩阵

  1. numpy中的zero()函数可以用来创建一个多维零矩阵,使用时,我们需要先导入该库。
  2. import numpy as np
  3. color =  np.zeros((320, 240, 3),dtype=np.uint8) # 创建一个三维零矩阵,类型为uint8
复制代码

其中,“320”指的是第一维度,“240”指的是行数,“3”指的是列数,uint8是8位无符号整形,表示范围为[0,255]的整数,它专门用于存储各种图像的矩阵类型,要想将当前的矩阵作为图像类型来进行各种操作,就要将数据类型定义为uint8。

7、Pinpong库获取颜色值

pinpong.libs.dfrobot_tcs34725包中的TCS34725模块是专门针对TCS34725颜色传感器封装的Python库,可以用来获取颜色值,使用时,需要先导入该模块,实例化TCS34725类。

(1)begin()方法确认初始化连接是否成功

TCS34725类中的begin()方法可以用来检测判断该颜色传感器是否连接成功,如果成功连接,则会返回True,否则返回False。

  1. from pinpong.libs.dfrobot_tcs34725 import TCS34725 # 导入pinpong.libs.dfrobot_tcs34725 包中 TCS34725模块
  2. tcs = TCS34725() # 实例化TCS34725类,创建tcs对象(颜色传感器)
  3. if tcs.begin(): # 初始化颜色传感器,如果读取到则返回True
  4. print("Found sensor") # 打印“检测到传感器”
复制代码

(2)get_rgbc()方法检测颜色值

TCS34725类中的get_rgbc()可以用来检测rgbc颜色值,获取到数据后,优先返回r(red)的值,随后是g(green),接着是b(blue),最后是c(clear),同时,这里检测到的r、g、b三个数值需要先经过数据转换方能成为表示颜色的r、g、b值。

  1. r1,g1,b1,c1 = tcs.get_rgbc() # 获取rgbc数据
  2. # 数据转换
  3. if c1:
  4. r1 /= c1
  5. g1 /= c1
  6. b1 /= c1
  7. r1 *= 256
  8. g1 *= 256
  9. b1 *= 256
复制代码

其中,r1,g1,b1, 分别是三个用来存储r、g、b值的变量,c1是clear,指过滤掉红外光的原始光,计算r、g、b占c的比例,按比例映射到256后即为对应的颜色值。

动手实践

任务描述1:终端输入颜色值控制变色效果手动输入RGB的值,将其所代表的颜色显示在图片中的角色上,实现变色龙效果。

1、硬件搭建
通过USB连接线将行空板连接到计算机

2、程序编写
STEP1:创建与保存项目文件

启动Mind+,另存项目并命名为“011、屏幕变色龙”。

STEP2:创建与保存Python文件

创建一个Python程序文件“main1.py”,双击打开。

STEP3:导入图片文件夹

在项目文件夹中导入背景图文件夹。(下载链接见附录1)

Step4:程序编写

  • 导入所需功能库

在这个任务中,我们需要使用opencv库来处理图像,numpy库处理数据,time库设定延时,因此,我们需要先导入相应的库。

  1. import cv2 # 导入opencv库
  2. import numpy as np # 导入numpy库
  3. import time
复制代码

(2)读取图像、创建图像窗口并设置全屏

变色龙的效果是基于图片处理得到的,因此在这里,我们需要读取该图片,创建一个用于显示图像的窗口,并设置其为全屏模式以便将变色龙显示在屏幕上。

  1. sample = cv2.imread("img/sample.png") # 读取img文件夹下sample.png图片,并命名为sample
  2. cv2.namedWindow('winname',cv2.WND_PROP_FULLSCREEN) # Set the windows to be full screen.# 构建一个窗口,名称为winname,默认属性为可以全屏
  3. cv2.setWindowProperty('winname',cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) # Set the windows to be full screen. # 设置winname窗口全屏
复制代码

(3)设定色调H的上下限

要想使图像中的变色龙角色自由变换颜色,我们需要先找出图像中“龙”的部分,在这张图像中,背景为白色,“龙”为蓝色,因此,我们可通过指定色调H的范围来圈出变色龙角色。

  1. '''用HSV颜色空间实现图像掩模'''
  2. # 定义蓝色掩模,指定色调H的范围,l为上限,u为下限(原图中变色龙的部分为蓝色)
  3. l = 100
  4. u = 140
复制代码

(4)定义函数,获取掩膜图像

接下来,我们需获取一张掩膜图像,这里,我们可将获取掩膜图像的步骤整理为函数,方便后续调用。

  1. # 把获取掩膜图像的步骤整理为函数,方便后续调用
  2. # 定义函数--获取掩膜图像
  3. def get_hsv_mask(img, l, u): # 定义函数get_hsv_mask,传入参数img,l,u
  4.     hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) # 将图像img的BGR颜色空间转换为HSV颜色空间,并命名新图像为hsv
  5.     lower = np.array([l,90,90]) # 设阈值,下限值
  6.     upper = np.array([u,255,255]) # 设阈值,上限值
  7.     mask = cv2.inRange(hsv, lower, upper) # 去除背景部分,将图像hsv中低于lower或高于upper的图像值变为0,在lower~upper中间的值变为255
  8.     return mask  # 返回掩膜图像---黑白图---黑底白龙
复制代码

(5)定义函数,显示指定颜色的变色龙图像

之后,我们定义一个函数,来将变色龙图片中“龙”的部分,显示为指定的颜色。为此,我们将分多步进行。首先,我们创建一个3维零矩阵以表示一张新的图像,并将指定的rgb颜色值赋给它,形成彩图。之后,我们通过色彩阈值化处理获取一张原图的掩膜图像。接着,将自定义的彩图先与自身做按位与运算,再将结果与掩膜图像做与运算。然后,我们再将原来的掩模图按位取反,得到新的掩膜图像。随后,我们使原图先与自身做按位与运算,再将结果与新的掩模图进行与运算。之后,将得到的图与之前自定义的彩图进行或运算,得到的图即为变色后的效果图。最后,我们将图像显示在窗口上。

  1. # 定义函数--显示指定颜色的变色龙图像
  2. def brg(r,g,b):
  3.     # RGB background
  4.     color =  np.zeros((320, 240, 3),dtype=np.uint8) # 创建一个三维零矩阵,类型为uint8
  5.     color[:,:,0] = b # B # 遍历所有行,遍历所有列,赋值蓝色通道为b的值
  6.     color[:,:,1] = g # G # 遍历所有行,遍历所有列,赋值绿色通道为g的值
  7.     color[:,:,2] = r # R # 遍历所有行,遍历所有列,赋值红色通道为r的值
  8.     '''通过色彩阈值化处理获取变色龙图案轮廓---获取掩膜图像(黑底白龙)'''
  9.     # 获取掩模图像--黑底白龙(图1)
  10.     object_mask = get_hsv_mask(sample,l,u)
  11.     '''黑色为(0,0,0),某值与0做与运算仍为0,白色为(255,255,255),某值与它做与运算仍为该值自身'''
  12.     # 先将color图与自身做与运算,再将得到的结果(依旧为color图)与掩膜图像(图1)做与运算,得到黑底color龙(图2)
  13.     background_masked = cv2.bitwise_and(color,color, mask=object_mask)
  14.     # 将原来的掩膜图(黑底白龙图1)按位取反,得到白底黑龙图,作为新的掩膜图(图3)
  15.     object_mask_not = cv2.bitwise_not(object_mask)
  16.     # 将原图与自身先做与运算,再将得到的结果(依旧为原图,白底蓝龙)与图3(白底黑龙)进行与运算(掩膜运算),得到白底黑龙图(图4)
  17.     object_masked = cv2.bitwise_and(sample,sample, mask=object_mask_not)
  18.     # 图2(黑底color龙)与图4(白底黑龙)进行按位或运算,得白底color龙(图5--最终结果图),并命名为final_output
  19.     final_output = cv2.bitwise_or(background_masked,object_masked)
  20.     # 显示图像并保持
  21.     cv2.imshow('winname', final_output) # 在winname窗口上显示图像final_output
  22.     cv2.waitKey() # 刷新图像(等待用户按键触发,不写入参数默认为0,表示无限等待,显示最初的图像)
复制代码

(6)键盘输入颜色

最后,我们设定通过键盘在终端中输入颜色值,再调用上述函数来实现变色龙效果。

  1. '''用户在终端手动输入颜色值,映射到变色龙身上'''
  2. r,g,b=map(int,input('输入r,g,b空格隔开:').split()) # 接收多个用户输入值并取整,输入时中间用一个空格分隔开
  3.    
  4. brg(r,g,b) # 调用brg函数,显示指定颜色的变色龙图像,指定的颜色值由键盘输入
  5. cv2.destroyAllWindows() # 关闭所有窗口
复制代码

Tips:完整示例程序如下:
  1. import cv2 # 导入opencv库
  2. import numpy as np # 导入numpy库
  3. import time
  4. sample = cv2.imread("img/sample.png") # 读取img文件夹下sample.png图片,并命名为sample
  5. cv2.namedWindow('winname',cv2.WND_PROP_FULLSCREEN) # Set the windows to be full screen.# 构建一个窗口,名称为winname,默认属性为可以全屏
  6. cv2.setWindowProperty('winname',cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) # Set the windows to be full screen. # 设置winname窗口全屏
  7. '''用HSV颜色空间实现图像掩模'''
  8. # 定义蓝色掩模,指定色调H的范围,l为上限,u为下限(原图中变色龙的部分为蓝色)
  9. l = 100
  10. u = 140
  11. # 把获取掩膜图像的步骤整理为函数,方便后续调用
  12. # 定义函数--获取掩膜图像
  13. def get_hsv_mask(img, l, u): # 定义函数get_hsv_mask,传入参数img,l,u
  14.     hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) # 将图像img的BGR颜色空间转换为HSV颜色空间,并命名新图像为hsv
  15.     lower = np.array([l,90,90]) # 设阈值,下限值
  16.     upper = np.array([u,255,255]) # 设阈值,上限值
  17.     mask = cv2.inRange(hsv, lower, upper) # 去除背景部分,将图像hsv中低于lower或高于upper的图像值变为0,在lower~upper中间的值变为255
  18.     return mask  # 返回掩膜图像---黑白图---黑底白龙
  19. # 定义函数--显示指定颜色的变色龙图像
  20. def brg(r,g,b):
  21.     # RGB background
  22.     color =  np.zeros((320, 240, 3),dtype=np.uint8) # 创建一个三维零矩阵,类型为uint8
  23.     color[:,:,0] = b # B # 遍历所有行,遍历所有列,赋值蓝色通道为b的值
  24.     color[:,:,1] = g # G # 遍历所有行,遍历所有列,赋值绿色通道为g的值
  25.     color[:,:,2] = r # R # 遍历所有行,遍历所有列,赋值红色通道为r的值
  26.     '''通过色彩阈值化处理获取变色龙图案轮廓---获取掩膜图像(黑底白龙)'''
  27.     # 获取掩模图像--黑底白龙(图1)
  28.     object_mask = get_hsv_mask(sample,l,u)
  29.     '''黑色为(0,0,0),某值与0做与运算仍为0,白色为(255,255,255),某值与它做与运算仍为该值自身'''
  30.     # 先将color图与自身做与运算,再将得到的结果(依旧为color图)与掩膜图像(图1)做与运算,得到黑底color龙(图2)
  31.     background_masked = cv2.bitwise_and(color,color, mask=object_mask)
  32.     # 将原来的掩膜图(黑底白龙图1)按位取反,得到白底黑龙图,作为新图(图3)
  33.     object_mask_not = cv2.bitwise_not(object_mask)
  34.     # 将原图与自身先做与运算,再将得到的结果(依旧为原图,白底蓝龙)与图3(白底黑龙)进行与运算(掩膜运算),得到白底黑龙图(图4)
  35.     object_masked = cv2.bitwise_and(sample,sample, mask=object_mask_not)
  36.     # 图2(黑底color龙)与图4(白底黑龙)进行按位或运算,得白底color龙(图5--最终结果图),并命名为final_output
  37.     final_output = cv2.bitwise_or(background_masked,object_masked)
  38.     # 显示图像并保持
  39.     cv2.imshow('winname', final_output) # 在winname窗口上显示图像final_output
  40.     cv2.waitKey() # 刷新图像(等待用户按键触发,不写入参数默认为0,表示无限等待,显示最初的图像)
  41. '''用户在终端手动输入颜色值,映射到变色龙身上'''
  42. r,g,b=map(int,input('输入r,g,b空格隔开:').split()) # 接收多个用户输入值并取整,输入时中间用一个空格分隔开
  43.    
  44. brg(r,g,b) # 调用brg函数,显示指定颜色的变色龙图像,指定的颜色值由键盘输入
  45. cv2.destroyAllWindows() # 关闭所有窗口
复制代码

3、程序运行
STEP1:远程连接行空板,运行程序并观察效果

观察Mind+终端,可以看到有颜色rgb值的输入提示,这里,我们随意输入一组颜色值“238 130 238”,随后按下回车键,

【行空板Python入门教程】第十一课:屏幕变色龙图23

再观察行空板,可以发现板子上“龙”的主体部分变为了相应颜色。

【行空板Python入门教程】第十一课:屏幕变色龙图28

Tips:这里,若想再次输入颜色值体验不同的效果,需要重新运行程序。

任务描述2:传感器采集颜色控制变色效果
在上个任务中,我们通过输入指定rgb颜色值的方法来控制“龙”变化的颜色,并显示在屏幕上,接下来,我们将通过传感器来采集颜色值,再反映到变色龙身上。

1、硬件搭建
STEP1:将颜色传感器接入行空板的I2C引脚

【行空板Python入门教程】第十一课:屏幕变色龙图24

2、程序编写
STEP1:创建与保存项目文件

新建一个Python程序文件“main2.py”,双击打开。

Step2:程序编写

在这个任务中,我们将原先由键盘输入颜色值更改为通过颜色传感器实时检测,因此在编程时,我们只需做一些调整即可。

(1)补充导入Pinpong库颜色传感器模块

  1. from pinpong.board import Board,Pin # 导入pinpong.board包中Board,Pin模块
  2. from pinpong.extension.unihiker import * # 导入pinpong.extension.unihiker包中所有模块
  3. from pinpong.libs.dfrobot_tcs34725 import TCS34725 # 导入pinpong.libs.dfrobot_tcs34725 包中 TCS34725模块
复制代码

(2)补充初始化行空板、创建颜色传感器对象
  1. Board().begin() # 板子初始化
  2. tcs = TCS34725() # 实例化TCS34725类,创建tcs对象(颜色传感器)
复制代码

(3)补充初始化颜色传感器确认是否连接成功

  1. # 初始化颜色传感器确认是否连接成功
  2. while True:
  3.     if tcs.begin(): # 初始化颜色传感器,如果读取到则返回True
  4.         print("Found sensor") # 打印“检测到传感器”
  5.         break # 跳出循环
  6.     else: # 否则
  7.         print("No TCS34725 found ... check your connections") # 打印“未找到该颜色传感器,请检查连接”
  8.         time.sleep(1)
复制代码

(4)补充定义函数,通过颜色传感器获取rgb值

  1. # 定义函数--从传感器获取rgb颜色值
  2. def get_RGB(tcs):
  3.     r1,g1,b1,c1 = tcs.get_rgbc() # 获取rgbc数据
  4.     # 数据转换
  5.     if c1:
  6.         r1 /= c1
  7.         g1 /= c1
  8.         b1 /= c1
  9.         r1 *= 256
  10.         g1 *= 256
  11.         b1 *= 256
  12.     return r1,g1,b1 # 返回数r、g、b的值
复制代码

(5)实时检测颜色值并变色

最后,我们在循环中调用传感器检测颜色的函数和显示变色效果的函数,以便能实时获取颜色值并在图像窗口上显示变色效果,并且,我们设置按下按键b来停止程序。

  1. while True:
  2.     r1,g1,b1 =get_RGB(tcs) # 调用get_RGB()函数通过传感器检测获取颜色的rgb值
  3.     brg(r1,g1,b1) # 调用brg函数,显示指定颜色的变色龙图像,指定的颜色值由上述传感器获取
  4.     print((b1,g1,r1)) # 打印颜色值
  5.     # 按b键停止程序
  6.     if cv2.waitKey(10) & 0xFF == ord('b'):
  7.         break
  8. cv2.destroyAllWindows() # 关闭所有窗口
复制代码

Tips:完整示例程序如下:

  1. import cv2 # 导入opencv库
  2. import numpy as np # 导入numpy库
  3. import time
  4. from pinpong.board import Board,Pin # 导入pinpong.board包中Board,Pin模块
  5. from pinpong.extension.unihiker import * # 导入pinpong.extension.unihiker包中所有模块
  6. from pinpong.libs.dfrobot_tcs34725 import TCS34725 # 导入pinpong.libs.dfrobot_tcs34725 包中 TCS34725模块
  7. sample = cv2.imread("img/sample.png") # 读取img文件夹下sample.png图片,并命名为sample
  8. cv2.namedWindow('winname',cv2.WND_PROP_FULLSCREEN) # Set the windows to be full screen.# 构建一个窗口,名称为winname,默认属性为可以全屏
  9. cv2.setWindowProperty('winname',cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) # Set the windows to be full screen. # 设置winname窗口全屏
  10. Board().begin() # 板子初始化
  11. tcs = TCS34725() # 实例化TCS34725类,创建tcs对象(颜色传感器)
  12. # 初始化颜色传感器确认是否连接成功
  13. while True:
  14.     if tcs.begin(): # 初始化颜色传感器,如果读取到则返回True
  15.         print("Found sensor") # 打印“检测到传感器”
  16.         break # 跳出循环
  17.     else: # 否则
  18.         print("No TCS34725 found ... check your connections") # 打印“未找到该颜色传感器,请检查连接”
  19.         time.sleep(1)
  20. # 定义函数--从传感器获取rgb颜色值
  21. def get_RGB(tcs):
  22.     r1,g1,b1,c1 = tcs.get_rgbc() # 获取rgbc数据
  23.     # 数据转换
  24.     if c1:
  25.         r1 /= c1
  26.         g1 /= c1
  27.         b1 /= c1
  28.         r1 *= 256
  29.         g1 *= 256
  30.         b1 *= 256
  31.     return r1,g1,b1 # 返回数r、g、b的值
  32. '''用HSV颜色空间实现图像掩模'''
  33. # 定义蓝色掩模,指定色调H的范围,l为上限,u为下限(原图中变色龙的部分为蓝色)
  34. l = 100
  35. u = 140
  36. # 把获取掩膜图像的步骤整理为函数,方便后续调用
  37. # 定义函数--获取掩膜图像
  38. def get_hsv_mask(img, l, u): # 定义函数get_hsv_mask,传入参数img,l,u
  39.     hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) # 将图像img的BGR颜色空间转换为HSV颜色空间,并命名新图像为hsv
  40.     lower = np.array([l,90,90]) # 设阈值,下限值
  41.     upper = np.array([u,255,255]) # 设阈值,上限值
  42.     mask = cv2.inRange(hsv, lower, upper)  # 去除背景部分,将图像hsv中低于lower或高于upper的图像值变为0,在lower~upper中间的值变为255
  43.     return mask # 返回掩膜图像---黑白图---黑底白龙
  44. # 定义函数--显示指定颜色的变色龙图像
  45. def brg(r,g,b):
  46.     # RGB background
  47.     color =  np.zeros((320, 240, 3),dtype=np.uint8) # 创建一个三维零矩阵,类型为uint8
  48.     color[:,:,0] = b # B # 遍历所有行,遍历所有列,赋值蓝色通道为b的值
  49.     color[:,:,1] = g # G # 遍历所有行,遍历所有列,赋值绿色通道为g的值
  50.     color[:,:,2] = r # R # 遍历所有行,遍历所有列,赋值红色通道为r的值
  51.     '''通过色彩阈值化处理获取变色龙图案轮廓---获取掩膜图像(黑底白龙)'''
  52.     # 获取掩模图像--黑底白龙(图1)
  53.     object_mask = get_hsv_mask(sample,l,u)
  54.     '''黑色为(0,0,0),某值与0做与运算仍为0,白色为(255,255,255),某值与它做与运算仍为该值自身'''
  55.     # 先将color图与自身做与运算,再将得到的结果(依旧为color图)与掩膜图像(图1)做与运算,得到黑底color龙(图2)
  56.     background_masked = cv2. bitwise_and(color,color, mask=object_mask)
  57.     # 将原来的掩膜图(黑底白龙图1)按位取反,得到白底黑龙图,作为新图(图3)
  58.     object_mask_not = cv2.bitwise_not(object_mask)
  59.     # 将原图与自身先做与运算,再将得到的结果(依旧为原图,白底蓝龙)与图3(白底黑龙)进行与运算(掩膜运算),得到白底黑龙图(图4)
  60.     object_masked = cv2. bitwise_and(sample,sample, mask=object_mask_not)
  61.     # 图2(黑底color龙)与图4(白底黑龙)进行按位或运算,得白底color龙(图5--最终结果图),并命名为final_output
  62.     final_output = cv2.bitwise_or(background_masked,object_masked)
  63.     # 显示图像
  64.     cv2.imshow('winname', final_output) # 在winname窗口上显示图像final_output
  65.     #cv2.waitKey(5)  # 每5ms刷新图像
  66.    
  67.    
  68. while True:
  69.     r1,g1,b1 =get_RGB(tcs) # 调用get_RGB()函数通过传感器检测获取颜色的rgb值
  70.     brg(r1,g1,b1) # 调用brg函数,显示指定颜色的变色龙图像,指定的颜色值由上述传感器获取
  71.     print((b1,g1,r1)) # 打印颜色值
  72.     # 按b键停止程序
  73.     if cv2.waitKey(10) & 0xFF == ord('b'):
  74.         break
  75. cv2.destroyAllWindows() # 关闭所有窗口
复制代码

3、程序运行
STEP1:远程连接行空板,运行程序

STEP2:利用传感器检测颜色

将颜色传感器靠近不同颜色的物体,可以发现板子上的“龙”也很快变成了它的颜色。

Tips:将传感器放置于被测物体正面,间距控制在3~10mm之间。

【行空板Python入门教程】第十一课:屏幕变色龙图29

挑战自我任务一中,在显示了一次变色效果后,要想体验其他颜色值的效果,我们需要再次运行程序,重新输入rgb值,想一想,是不是可以优化程序,添加一个按钮控制,每次按下板载a,就重新开始呢?

附录
附录1:变色龙图片链接

链接:https://pan.baidu.com/s/1Et2u5Vkp3Av6v1lfroWHkA?pwd=yohz


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail