[实操]利用python识别特定内容

这是一个关于如何识别特定内容的教程,是通过opencv-python库将内容识别出来。

实现步骤

  1. 搭建环境(conda

  2. 实例:识别盲道

  3. 修改代码,增加识别它物的能力

一、搭建环境

本次教程我们使用conda,来部署python环境。

Conda 是一个开源的包管理系统和环境管理系统,用于安装多个版本的软件包及其依赖项,并在它们之间轻松切换。Conda 最初是为 Python 相关的项目设计的,但现在已经支持多种语言,包括 R、Julia、Node.js 和其他科学计算工具。

Conda 的主要特点:

  1. 跨平台:Conda 可以在 Windows、macOS 和 Linux 上运行。

  2. 环境管理:用户可以创建独立的环境来隔离不同的项目或实验,每个环境都可以有自己的软件包集合和 Python 版本。

  3. 包管理:Conda 有一个庞大的软件包仓库(Anaconda Repository),其中包含了数千个预先编译好的科学计算和数据科学相关的软件包。

  4. 命令行工具:Conda 提供了一系列命令行工具来简化安装、更新、卸载和管理软件包的过程。

  5. 兼容性:除了管理 conda 包之外,Conda 还可以安装普通的 Python 软件包(通过 pip)。

但是这次我们用到的库并不多,所以我们不用标准的anaconda(1.01GB),而是用小巧的miniconda,先从网上下载下来,这里用清华镜像:

Windows https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py39_24.5.0-0-Windows-x86_64.exe

macos arm https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py39_24.5.0-0-MacOSX-arm64.pkg

macos X_86 https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py39_24.5.0-0-MacOSX-x86_64.pkg

下载完毕后安装即可。

接着,就是搭建python环境了。

Windows

在搜索框搜索miniconda,应该会跳出一个带有miniconda名字的命令行应用

e078fada608f419b909db19314eb92bc.png

打开它,然后我们需要创建一个3.10版本的python环境

conda create -n ColorDetection python=3.10.0

这样就可以创建一个环境了,中途遇到是否继续[y/n],输入y再回车就行,在安装好后,我们输入以下命令来启动这个环境

conda activate ColorDetection

Macos

打开自带的终端,再输入上面Windows的命令就行。

安装第三方库

这次我们需要numpy和opencv-python

可以使用pip安装

pip3 install numpy opencv-python

实例:识别盲道

在说如何识别特定颜色前,我们先来举一个例子,就是识别盲道,本实例针对传统、普遍的黄色盲道展开。

首先,先下载示例图片:https://tse3-mm.cn.bing.net/th/id/OIP-C.MjmVaLe5KcBb-AOCPD6b0gHaJ4?rs=1&pid=ImgDetMain

如果下载不了的话,可以在网上(bing)搜“盲道”,找一张。

接着,就是编写代码了,打开你们的ide,创建一个名为“ColorDetection”的文件(项目),并在其中新建一个名为“BlindLaneDetection”的python文件,我们将在这个python文件中编写识别盲道的示例代码。

首先是导入numpy库和opencv-python库,在一些ide中,你可能需要手动启用我们刚刚搭建的conda环境。

import cv2
import numpy as np

接着是导入我们下载的示例图片

frame = cv2.imread('your_image_path')

其中frame的意思是我们将这个图片当作一帧来处理,frame也是opencv中常被命名的变量。

cv2.imread是opencv-python的一个读取图片的类。

请将“your_image_path”替换成你的示例图片的位置。

然后是将读取到的图片转换为hsv色彩格式

一、HSV颜色系统简介 HSV是一种在人们生活中甚至更常用的颜色系统,在电视遥控器上、在画画的调色板中、在你用爱某艺视频调整亮度时都很常见,因为它更符合人们描述颜色的方式——是什么颜色、颜色有多深、颜色有多亮。 H——Hue即色相,就是我们平时所说的红、绿,如果你分的更细的话可能还会有洋红、草绿等等;在HSV模型中,用度数来描述色相,其中红色对应0度,绿色对应120度,蓝色对应240度。

d394ae0a1585f080f31fcb4bad6165e4.jpeg

S——Saturation即饱和度,色彩的深浅度(0-100%) ,对于一种颜色比如红色,我们可以用浅红——大红——深红——红得发紫等等语言来描述它(请原谅一个纯理科生的匮乏的颜色系统),对应在画水彩的时候即一种颜料加上不同分量的水形成不同的饱和度。 V——Value即色调,纯度,色彩的亮度(0-100%) ,这个在调整屏幕亮度的时候比较常见。

eba196cf1d78635b92690626bfd80ac0.jpeg

注:在模型2中: H是色彩点在对应圆形切面上与红色半径(对于H=0度)所形成的圆心角。 V是色彩点所在圆形切面到圆锥顶点的距离。在顶面上V=1 顶点V=0 S是色彩点到所在圆形切面圆心的距离与该圆半径的比例值,在圆锥表面上S=1,在圆心处S=0

 

摘自:OpenCV学习笔记——HSV颜色空间超极详解&inRange函数用法及实战_hsv值是什么-CSDN博客

frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

这里将frame增加了一个后缀_hsv表示以hsv为颜色空间的图片

cv2.cvtColor()是opencv一个转换图片色彩空间的类

cv2.cvtColor(input_image, flag)

参数描述返回值
input_image需要转换的图片颜色空间转换后的图片矩阵
flag转换的类型颜色空间转换后的图片矩阵

两个参数分别表示原始图像和转换方式

继续创建掩膜

掩膜   数字图像处理中的掩膜概念是借鉴于PCB制版的过程,在半导体制作中,许多芯片工艺步骤采用光刻技术,用于这些步骤的图形“底片”称为掩膜,其作用是:在硅片上选定的区域中对一个不透明的图形模板掩盖,继而下面的腐蚀或扩散只影响选定区域以外的区域。   图像掩膜与其类似,用选定的图像、图形或物体,对处理的图像进行遮挡,来控制图像处理区域或处理过程。   数字图像处理中,掩膜为―维矩阵数组有时也用多值图像,图像掩膜主要用于:   ①提取感兴趣区,用预先制作的感兴趣区掩膜与待处理图像相乘.得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。   ②屏蔽作用,用掩膜对图像上某些区域作屏蔽使其不参加处理或不参加处理参数的计算.或仅对屏蔽区作处理或统计。   ③结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩膜相似的结构特征。   ④特殊形状图像的制作。

mask = cv2.inRange(frame_hsv, np.array([17, 117, 238]), np.array([19, 158, 255]))
  1. cv2.inRange() 是OpenCV中的一个函数,用于根据指定的阈值范围对图像进行阈值操作。这个函数会返回一个二值图像(黑白图像),其中满足颜色范围条件的像素被标记为白色(通常值为255),不满足条件的像素则被标记为黑色(值为0)。

  2. np.array([17, 117, 238])np.array([19, 158, 255]) 定义了HSV色彩空间中的下限和上限。这意味着代码将会选取那些H(色调)在17到19之间、S(饱和度)在117到158之间、V(明度/亮度)在238到255之间的像素作为目标颜色区域。

接下来就可以调用

cv2.imshow('Filtered Image1', mask)

来显示创建的掩膜。

82219afc4bff400aba16c762cad00c34.png

可以看到盲道的主要部分已经被区分出来了,接下来给出这部分的完整代码

import cv2
import numpy as np
​
frame = cv2.imread('images/test_photo.jpg')
​
frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.imshow("Original image", frame_hsv)
​
# 定义黄色的HSV范围
lower_yellow = np.array([17, 117, 238])
upper_yellow = np.array([19, 158, 255])
​
# 根据HSV范围创建掩膜
mask = cv2.inRange(frame_hsv, lower_yellow, upper_yellow) #lower_yellow, upper_yellow是为了代码的美观而定义的
cv2.imshow('Filtered Image1', mask)

不过我么看到,虽然区别出来的图像具备盲道的很多纹理,看起来非常逼真,但是在计算机看来,那些纹理(黑色部分)就不是盲道,所以我们就需要对其进行膨胀操作,通俗的来讲,就是填满那些纹路。将其变成几何图形。

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
mask = cv2.dilate(mask, kernel, iterations=5)

cv2.getStructuringElement()

cv2.getStructuringElement() 是一个用于生成结构元素的函数。结构元素是用来与原图像进行数学形态学操作(如膨胀、腐蚀等)的核。在这个例子中,创建的是一个矩形的结构元素。

  • 参数:

    • cv2.MORPH_RECT: 指定结构元素的形状为矩形。

    • (3, 3): 结构元素的大小,即宽度和高度。

cv2.dilate()

cv2.dilate() 函数用于执行二值图像的膨胀操作。膨胀是一种形态学变换,可以用来扩大图像中的白色区域(前景)。这通常用于连接相邻的物体、填充小洞或者扩大边界。

  • 参数:

    • mask: 这是输入的二值图像,即要进行膨胀操作的对象。

    • kernel: 用于膨胀操作的结构元素。

    • iterations=5: 膨胀操作重复执行的次数。迭代次数越多,膨胀的效果越明显。

同样我们可以加上

cv2.imshow('Filtered Image2', mask)

来查看效果

eb32ef1e470447b7a4f0bd8039cb3e94.png

可以看到,程序已经识别出了盲道(膨胀后)

下面是识别盲道的完整示例代码:

import cv2
import numpy as np
​
frame = cv2.imread('images/test_photo.jpg')
​
frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.imshow("Original image", frame_hsv)
​
# 定义黄色的HSV范围
lower_yellow = np.array([17, 117, 238])
upper_yellow = np.array([19, 158, 255])
​
# 根据HSV范围创建掩膜
mask = cv2.inRange(frame_hsv, lower_yellow, upper_yellow)
cv2.imshow('Filtered Image1', mask)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
mask = cv2.dilate(mask, kernel, iterations=5)
cv2.imshow('Filtered Image2', mask)

三、拓展:识别他物

体验了识别盲道后,相信这一部分会很轻松!

还是上面的代码:

import cv2
import numpy as np
​
frame = cv2.imread('images/test_photo.jpg')
​
frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.imshow("Original image", frame_hsv)
​
# 定义黄色的HSV范围
lower_yellow = np.array([17, 117, 238])
upper_yellow = np.array([19, 158, 255])
​
# 根据HSV范围创建掩膜
mask = cv2.inRange(frame_hsv, lower_yellow, upper_yellow)
cv2.imshow('Filtered Image1', mask)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
mask = cv2.dilate(mask, kernel, iterations=5)
cv2.imshow('Filtered Image2', mask)

只不过我们可以修改代码,让代码可以识别特定颜色。

我们先放一放上面这段代码,想想如何快速获得hsv的颜色信息呢?

为此我们可以为此新建一个程序color_selection.py

import cv2
​
# 读取图像
image = cv2.imread('your_image_path(替换为你图片的路径)')
​
# 将图像从BGR颜色空间转换为HSV颜色空间
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
​
# 获取鼠标点击事件
def mouse_callback(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        # 获取点击位置的HSV值
        hsv_value = hsv[y, x]
        print(hsv_value)
​
# 创建一个窗口并绑定鼠标回调函数
cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_callback)
​
# 显示图像
cv2.imshow('image', image)
​
# 等待按键,然后关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

其中定义(使用)了一个名为mouse_callback的函数,event == cv2.EVENT_LBUTTONDOWN可以检测鼠标左键是否按下,hsv_value = hsv[y, x]可以获取鼠标所指位置的hsv颜色。

运行程序,可以发现程序可以正常返回所需的值,然后我们只需要修改lower_yellowupper_yellow(因为此时已经不只检测黄色可以考虑将变量改为lower_colorupper_color)的值就可以了比如:

import cv2
import numpy as np
​
frame = cv2.imread('images/test_photo.jpg')
​
frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.imshow("Original image", frame_hsv)
​
# 定义黄色的HSV范围
​
lower_yellow = np.array([16, 88, 168]) #注意此处的更改
upper_yellow = np.array([17, 98, 190]) #注意此处的更改
​
# 根据HSV范围创建掩膜
​
mask = cv2.inRange(frame_hsv, lower_yellow, upper_yellow)
cv2.imshow('Filtered Image1', mask)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
mask = cv2.dilate(mask, kernel, iterations=5)
cv2.imshow('Filtered Image2', mask)

可以检测示例图片中的墙壁(不太准,大家可自行修改)

我们可以将这个程序与前面的ColorDetection.py结合,实现类似指哪打哪的功能。

在编写具体程序前,我们需要考虑一个问题,就是一次提取只能提取一种hsv颜色,那如何取到最高值和最小值呢?

笔者觉得5次可以

所以我们让color_selection.py检测按了多少次鼠标

首先在mouse_callback定义一个计数器c,检测按了多少次,并且在大小大于4时返回,在每次获取颜色后加1

i = 0
...
if i > 4:
    ...
...
i += 1
def mouse_callback(event, x, y, flags, param):
    i = 0
    if i > 4:
        pass
    if event == cv2.EVENT_LBUTTONDOWN:
        # 获取点击位置的HSV值
        hsv_value = hsv[y, x]
        i += 1

接着定义lower_h, upper_h, lower_s, upper_s, lower_v, upper_v,分别代表h, s, v的最大值和最小值(h, s, v介绍看前文)

lower_h = 300
upper_h = 0
lower_s = 300
upper_s = 0
lower_v = 300
upper_v = 0

接着通过类似打擂台的方式赋值最终的lower_h, upper_h, lower_s, upper_s, lower_v, upper_v

if hsv_value[0] < lower_h:
    lower_h = hsv_value[0]
if hsv_value[0] > upper_h:
    upper_h = hsv_value[0]
if hsv_value[1] < lower_s:
    lower_s = hsv_value[1]
if hsv_value[1] > upper_s:
    upper_s = hsv_value[1]
if hsv_value[2] < lower_v:
    lower_v = hsv_value[2]
if hsv_value[2] > upper_v:
    upper_v = hsv_value[2]

if i > 4:下输出返回值

if i > 4:
    return lower_h, upper_h, lower_s, upper_s, lower_v, upper_v

完整代码

def mouse_callback(event, x, y, flags, param):
    i = 0
    lower_h = 300
    upper_h = 0
    lower_s = 300
    upper_s = 0
    lower_v = 300
    upper_v = 0
    if i > 4:
        return lower_h, upper_h, lower_s, upper_s, lower_v, upper_v
    if event == cv2.EVENT_LBUTTONDOWN:
        # 获取点击位置的HSV值
        hsv_value = hsv[y, x]
        if hsv_value[0] < lower_h:
            lower_h = hsv_value[0]
        if hsv_value[0] > upper_h:
            upper_h = hsv_value[0]
        if hsv_value[1] < lower_s:
            lower_s = hsv_value[1]
        if hsv_value[1] > upper_s:
            upper_s = hsv_value[1]
        if hsv_value[2] < lower_v:
            lower_v = hsv_value[2]
        if hsv_value[2] > upper_v:
            upper_v = hsv_value[2]
        print("Lower H: ", lower_h)
        print("Upper H: ", upper_h)
        print("Lower S: ", lower_s)
        print("Upper S: ", upper_s)
        print("Lower V: ", lower_v)
        print("Upper V: ", upper_v)
        i += 1

不过将lower_h, upper_h, lower_s, upper_s, lower_v, upper_v在函数内定义的话,因为外部无法访问函数内的变量,所以可以定义全局变量,再在函数内调用(global)

import cv2
import numpy as np
​
# 读取图像
frame = cv2.imread('images/test_photo.jpg')
​
# 将图像从BGR颜色空间转换为HSV颜色空间
frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
​
lower_h = 300
upper_h = 0
lower_s = 300
upper_s = 0
lower_v = 300
upper_v = 0
​
# 获取鼠标点击事件
def mouse_callback(event, x, y, flags, param):
    i = 0
    global lower_h, upper_h, lower_s, upper_s, lower_v, upper_v #global就是让全局变量能在函数内使用(全局)的方法
    if event == cv2.EVENT_LBUTTONDOWN:
        # 获取点击位置的HSV值
        hsv_value = frame_hsv[y, x]
        if hsv_value[0] < lower_h:
            lower_h = hsv_value[0]
        if hsv_value[0] > upper_h:
            upper_h = hsv_value[0]
        if hsv_value[1] < lower_s:
            lower_s = hsv_value[1]
        if hsv_value[1] > upper_s:
            upper_s = hsv_value[1]
        if hsv_value[2] < lower_v:
            lower_v = hsv_value[2]
        if hsv_value[2] > upper_v:
            upper_v = hsv_value[2]
        # print("Lower H: ", lower_h)
        # print("Upper H: ", upper_h)
        # print("Lower S: ", lower_s)
        # print("Upper S: ", upper_s)
        # print("Lower V: ", lower_v)
        # print("Upper V: ", upper_v)
        i += 1
​
# 创建一个窗口并绑定鼠标回调函数
cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_callback)
​
# 显示图像
cv2.imshow('image', frame)
​
# 等待按键,然后关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
print(lower_h) #测试用,后续可删

接下来就简单了,只需要粘贴入ColorDetection.py就行了,完整代码

import cv2
import numpy as np
​
# 读取图像
frame = cv2.imread('images/test_photo.jpg')
​
# 将图像从BGR颜色空间转换为HSV颜色空间
frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
​
lower_h = 300
upper_h = 0
lower_s = 300
upper_s = 0
lower_v = 300
upper_v = 0
​
# 获取鼠标点击事件
def mouse_callback(event, x, y, flags, param):
    i = 0
    global lower_h, upper_h, lower_s, upper_s, lower_v, upper_v
    if i > 4:
        return
    if event == cv2.EVENT_LBUTTONDOWN:
        # 获取点击位置的HSV值
        hsv_value = frame_hsv[y, x]
        if hsv_value[0] < lower_h:
            lower_h = hsv_value[0]
        if hsv_value[0] > upper_h:
            upper_h = hsv_value[0]
        if hsv_value[1] < lower_s:
            lower_s = hsv_value[1]
        if hsv_value[1] > upper_s:
            upper_s = hsv_value[1]
        if hsv_value[2] < lower_v:
            lower_v = hsv_value[2]
        if hsv_value[2] > upper_v:
            upper_v = hsv_value[2]
        # print("Lower H: ", lower_h)
        # print("Upper H: ", upper_h)
        # print("Lower S: ", lower_s)
        # print("Upper S: ", upper_s)
        # print("Lower V: ", lower_v)
        # print("Upper V: ", upper_v)
        i += 1
​
# 创建一个窗口并绑定鼠标回调函数
cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_callback)
​
# 显示图像
cv2.imshow('image', frame)
​
# 等待按键,然后关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
​
lower_yellow = np.array([lower_h, lower_s, lower_v])
upper_yellow = np.array([upper_h, upper_s, upper_v])
​
mask = cv2.inRange(frame_hsv, lower_yellow, upper_yellow)
cv2.imshow('Filtered Image1', mask)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
mask = cv2.dilate(mask, kernel, iterations=5)
cv2.imshow('Filtered Image2', mask)
​
cv2.waitKey(0)
cv2.destroyAllWindows()

提示:在选择完颜色后需要先关闭颜色选择窗口,才能显示区分内容

盲道识别示例

 

 

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以为您提供一个大数据实操题目,您可以使用Python来完成。 题目描述: 某电商公司的订单数据存储在一个大型文本文件中,每一行代表一个订单,包含订单号、购买商品名称、购买数量、购买时间等信息。现在需要你编写一个Python程序,根据用户输入的关键字,在文本文件中查找包含关键字的订单,并输出相关信息。 具体要求: 1. 实现一个函数,输入参数为关键字和订单数据文件的路径,输出结果为包含关键字的订单信息列表。 2. 订单数据文件的格式如下: 订单号,商品名称,购买数量,购买时间 例如: 20210101001,手机,1,2021-01-01 10:10:10 20210101002,电脑,2,2021-01-02 10:10:10 20210101003,平板电脑,1,2021-01-03 10:10:10 3. 关键字可以是订单号、商品名称、购买数量、购买时间中的任意一个或多个。 4. 输出结果为包含关键字的订单信息列表,每个订单信息包括订单号、商品名称、购买数量、购买时间等信息。 5. 如果没有匹配的订单信息,输出提示信息:未找到符合条件的订单信息。 6. 代码需要具有一定的容错性,能够处理文件不存在、文件格式错误等异常情况。 示例输入: find_orders('手机', 'order.txt') 示例输出: [['20210101001', '手机', '1', '2021-01-01 10:10:10']] 提示: 您可以使用Python内置的文件读写函数,例如open()函数和readlines()函数,来读取订单数据文件中的数据。您可以使用字符串的split()函数,来将每一行订单数据分割成订单号、商品名称、购买数量、购买时间等信息。您可以使用Python内置的列表和字符串函数,例如append()函数和find()函数,来实现订单信息的查找和筛选。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMicheal

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值