IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 如何使用 OpenCV 开发虚拟键盘 -> 正文阅读

[人工智能]如何使用 OpenCV 开发虚拟键盘

介绍

OpenCV 是最流行的计算机视觉任务库,它是用于机器学习、图像处理等的跨平台开源库,用于开发实时计算机视觉应用程序。

CVzone 是一个计算机视觉包,它使用 OpenCV 和 Media Pipe 库作为其核心,使我们易于运行,例如手部跟踪、人脸检测、面部标志检测、姿势估计等,以及图像处理和其他计算机视觉相关的应用程序。

使用 OpenCV 实现虚拟键盘

让我们创建一个虚拟键盘。

首先,让我们安装所需的模块。

pip?install?numpy

pip?install?opencv-python

pip?install?cvzone

pip?install?pynput

使用 OpenCV 为虚拟键盘导入库

现在让我们导入所需的模块

import?cv2
import?cvzone
from?cvzone.HandTrackingModule?import?HandDetector
from?time?import?sleep
import?numpy?as?np
from?pynput.keyboard?import?Controller

这里我们从 cvzone.HandTrackingModule 导入 HandDetector 模块,然后为了使虚拟键盘工作,我们需要从 pynput.keyboard 导入Controller。

cap?=?cv2.VideoCapture(0,?cv2.CAP_DSHOW)
cap.set(3,?1280)
cap.set(4,?720)

现在让我们从 cv2.Videocapture 获取实时输入

detector?=?HandDetector(detectionCon=0.8)
keyboard_keys?=?[["Q",?"W",?"E",?"R",?"T",?"Y",?"U",?"I",?"O",?"P"],
??????????????????["A",?"S",?"D",?"F",?"G",?"H",?"J",?"K",?"L",?";"],
??????????????????["Z",?"X",?"C",?"V",?"B",?"N",?"M",?",",?".",?"/"]]
final_text?=?""

我们以 0.8 的检测置信度初始化 HandDetector 并将其分配给检测器。

然后我们根据键盘的布局创建一个列表数组,并定义一个空字符串来存储键入的键。

定义绘制函数

keyboard?=?Controller()
def?draw(img,?buttonList):
????for?button?in?buttonList:
????????x,?y?=?button.pos
????????w,?h?=?button.size
????????cvzone.cornerRect(img,?(button.pos[0],?button.pos[1],
???????????????????????????????????????????????????button.size[0],button.size[0]),?20?,rt=0)
????????cv2.rectangle(img,?button.pos,?(int(x?+?w),?int(y?+?h)),?(255,?144,?30),?cv2.FILLED)
????????cv2.putText(img,?button.text,?(x?+?20,?y?+?65),
????????????????????cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)
????return?img

初始化键盘控制器,并定义一个名为draw()的函数,它接受两个参数,即图像和按钮列表并返回图像。在draw()函数内部,我们使用 cvzone 的cornerRect函数在每个键的角落绘制矩形边缘。这是为了让我们的键盘布局看起来更好看。就像下面的图片。

fbae7ea2f2bae2fd145638e43131a4c3.png

你也可以尝试更改不同的颜色。

class?Button():
????def?__init__(self,?pos,?text,?size=[85,?85]):
????????self.pos?=?pos
????????self.size?=?size
????????self.text?=?text

然后我们定义一个名为 Button() 的类,并提供位置、文本和大小作为输入,以便我们可以按照明确定义的顺序排列键盘按键。

buttonList?=?[]
#?mybutton?=?Button([100,?100],?"Q")
for?k?in?range(len(keyboard_keys)):
????for?x,?key?in?enumerate(keyboard_keys[k]):
????????buttonList.append(Button([100?*?x?+?25,?100?*?k?+?50],?key))

上面的循环将遍历键盘按键和 Button 对象,我们在其中给出位置和文本作为输入附加在一个名为 button list 的列表中。稍后我们可以将这个列表传递给 draw 函数以在我们的实时框架之上进行绘制。

使用 OpenCV 的虚拟键盘主程序

重要的部分来了。

while?True:
????success,?img?=?cap.read()
????img?=?detector.findHands(img)
????lmList,?bboxInfo?=?detector.findPosition(img)
????img?=?draw(img,?buttonList)??#?change?the?draw?funtion?to?transparent_layout?for?transparent?keys
????if?lmList:
????????for?button?in?buttonList:
????????????x,?y?=?button.pos
????????????w,?h?=?button.size

if?x?<?lmList[8][0]<x+w?and?y?<?lmList[8][1]?<?y+h:
cv2.rectangle(img,?button.pos,?(x?+?w,?y?+?h),
(0,?255,?255),?cv2.FILLED)
cv2.putText(img,?button.text,?(x?+?20,?y?+?65),
cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)
l,?_,?_?=?detector.findDistance(8,12,?img,?draw=False)
print(l)

if?l?<?25:
keyboard.press(button.text)
cv2.rectangle(img,?button.pos,?(x?+?w,?y?+?h),
(0,?255,?0),?cv2.FILLED)
cv2.putText(img,?button.text,?(x?+?20,?y?+?65),
cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)
final_text?+=?button.text
sleep(0.20)

cv2.rectangle(img,?(25,350),?(700,?450),
(255,?255,?255),?cv2.FILLED)
cv2.putText(img,?final_text,?(60,?425),
cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)

#?cv2.rectangle(img,?(100,100),?(200,200),
#?(100,?255,?0),?cv2.FILLED)
#?cv2.putText(img,?'Q',?(120,180),?cv2.FONT_HERSHEY_PLAIN,?5,
#?(0,?0,?0),?5)

#?img?=?mybutton.draw(img)
cv2.imshow("output",?img)
cv2.waitKey(1)

在 while 循环中,首先我们读取实时输入帧并将其存储在一个名为img的变量中。然后我们将该图像传递给*检测器.findHands()*以便在帧中找到手。然后在该图像中,我们需要找到检测到的手的位置和边界框信息。

在这里我们可以找到我们的食指和中指的顶点之间的距离,如果两者之间的距离小于某个阈值,那么我们就可以输入我们所指示的字母。

一旦我们获得了位置,我们就会遍历整个位置列表。从该列表中,我们找到按钮位置和按钮大小,然后根据明确定义的方式将其绘制在框架上。

c1b9bd31f364e0b0f6a0e0660b1b8ead.png

图 1:手地标模型

之后,我们需要找到食指和中指的顶点之间的距离。在上图中,你可以看到我们需要的最高点是点 8 和点 12。因此,我们需要在距离查找函数中传递 8, 12 以获得它们之间的距离。

在上面的代码中,你可以看到 detector.findDistance(),我们通过了 8、12 和图像来查找距离,并将绘制标志设置为 false,这样我们就不需要两点之间的任何线。

如果点之间的距离非常小,我们将使用 press() 函数来按下按键。在上面的代码keyboard.press() 中,我们传递button.text以显示按下的键。最后,我们在键盘布局下方绘制一个小的白色矩形框,以显示按下的键。

一旦你执行了整个代码,它看起来像这样。

2ef7f4bd182782f8b068dd5a67382a8c.png

将食指和中指靠近特定字母的顶部后,你可以键入该字母。

f59cdfe271d822da40879257161a8961.png

如果你需要更自定义的键盘布局,我们可以使键盘布局透明。我们只需要添加一个透明布局函数并将*draw()函数替换为transparent_layout()*函数即可。

让我们定义transparent_layout()函数。下面是函数的代码,它采用与draw()函数相同的输入。在这里,我们将 numpy 的zero_like()函数分配给 名为imgNew的变量,并对其执行所需的操作,例如获得角矩形、为每个键创建矩形框并将文本放入框内。之后,我们将该图像复制到一个新变量并创建一个imgNew掩码,然后我们使用 OpenCV 的*addWeighted()*函数将掩码放置在实际图像的顶部。因此,这使键盘布局透明。

自定义键盘

def?transparent_layout(img,?buttonList):
????imgNew?=?np.zeros_like(img,?np.uint8)
????for?button?in?buttonList:
????????x,?y?=?button.pos
????????cvzone.cornerRect(imgNew,?(button.pos[0],?button.pos[1],
???????????????????????????????????????????????????button.size[0],button.size[0]),?20?,rt=0)
????????cv2.rectangle(imgNew,?button.pos,?(x?+?button.size[0],?y?+?button.size[1]),
???????????????????????????????????(255,?144,?30),?cv2.FILLED)
????????cv2.putText(imgNew,?button.text,?(x?+?20,?y?+?65),
????????????????????cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)
????????out?=?img.copy()
????????alpaha?=?0.5
????????mask?=?imgNew.astype(bool)
????????print(mask.shape)
????????out[mask]?=?cv2.addWeighted(img,?alpaha,?imgNew,?1-alpaha,?0)[mask]?
????????return?out

一旦将while 循环中的*draw()函数替换为transparent_layout()*函数,它将如下所示。(下图)

ac2b894f4e35179f231a7473f9df3cce.png

使用 OpenCV 的虚拟键盘的完整代码

下面是完整的代码

import?cv2
import?cvzone
from?cvzone.HandTrackingModule?import?HandDetector
from?time?import?sleep
import?numpy?as?np
from?pynput.keyboard?import?Controller

cap?=?cv2.VideoCapture(0,?cv2.CAP_DSHOW)
cap.set(3,?1280)
cap.set(4,?720)

detector?=?HandDetector(detectionCon=0.8)
keyboard_keys?=?[["Q",?"W",?"E",?"R",?"T",?"Y",?"U",?"I",?"O",?"P"],
??????????????????["A",?"S",?"D",?"F",?"G",?"H",?"J",?"K",?"L",?";"],
??????????????????["Z",?"X",?"C",?"V",?"B",?"N",?"M",?",",?".",?"/"]]

final_text?=?""

keyboard?=?Controller()


def?draw(img,?buttonList):
????for?button?in?buttonList:
????????x,?y?=?button.pos
????????w,?h?=?button.size
????????cvzone.cornerRect(img,?(button.pos[0],?button.pos[1],
???????????????????????????????????????????????????button.size[0],button.size[0]),?20?,rt=0)
????????cv2.rectangle(img,?button.pos,?(int(x?+?w),?int(y?+?h)),?(255,?144,?30),?cv2.FILLED)
????????cv2.putText(img,?button.text,?(x?+?20,?y?+?65),
????????????????????cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)
????return?img


def?transparent_layout(img,?buttonList):
????imgNew?=?np.zeros_like(img,?np.uint8)
????for?button?in?buttonList:
????????x,?y?=?button.pos
????????cvzone.cornerRect(imgNew,?(button.pos[0],?button.pos[1],
???????????????????????????????????????????????????button.size[0],button.size[0]),?20?,rt=0)
????????cv2.rectangle(imgNew,?button.pos,?(x?+?button.size[0],?y?+?button.size[1]),
???????????????????????????????????(255,?144,?30),?cv2.FILLED)
????????cv2.putText(imgNew,?button.text,?(x?+?20,?y?+?65),
????????????????????cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)

????out?=?img.copy()
????alpaha?=?0.5
????mask?=?imgNew.astype(bool)
????print(mask.shape)
????out[mask]?=?cv2.addWeighted(img,?alpaha,?imgNew,?1-alpaha,?0)[mask]
????return?out


class?Button():
????def?__init__(self,?pos,?text,?size=[85,?85]):
????????self.pos?=?pos
????????self.size?=?size
????????self.text?=?text


buttonList?=?[]
#?mybutton?=?Button([100,?100],?"Q")
for?k?in?range(len(keyboard_keys)):
????for?x,?key?in?enumerate(keyboard_keys[k]):
????????buttonList.append(Button([100?*?x?+?25,?100?*?k?+?50],?key))


while?True:
????success,?img?=?cap.read()
????img?=?detector.findHands(img)
????lmList,?bboxInfo?=?detector.findPosition(img)
????img?=?draw(img,?buttonList)??#?change?the?draw?funtion?to?transparent_layout?for?transparent?keys

????if?lmList:
????????for?button?in?buttonList:
????????????x,?y?=?button.pos
????????????w,?h?=?button.size

????????????if?x?<?lmList[8][0]<x+w?and?y?<?lmList[8][1]?<?y+h:
????????????????cv2.rectangle(img,?button.pos,?(x?+?w,?y?+?h),
??????????????????????????????(0,?255,?255),?cv2.FILLED)
????????????????cv2.putText(img,?button.text,?(x?+?20,?y?+?65),
????????????????????????????cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)
????????????????l,?_,?_?=?detector.findDistance(8,12,?img,?draw=False)
????????????????print(l)

????????????????if?l?<?25:
????????????????????keyboard.press(button.text)
????????????????????cv2.rectangle(img,?button.pos,?(x?+?w,?y?+?h),
??????????????????????????????????(0,?255,?0),?cv2.FILLED)
????????????????????cv2.putText(img,?button.text,?(x?+?20,?y?+?65),
????????????????????????????????cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)
????????????????????final_text?+=?button.text
????????????????????sleep(0.20)

????cv2.rectangle(img,?(25,350),?(700,?450),
??????????????????(255,?255,?255),?cv2.FILLED)
????cv2.putText(img,?final_text,?(60,?425),
????????????????cv2.FONT_HERSHEY_PLAIN,?4,?(0,?0,?0),?4)

????#?cv2.rectangle(img,?(100,100),?(200,200),
????#???????????????(100,?255,?0),?cv2.FILLED)
????#?cv2.putText(img,?'Q',?(120,180),?cv2.FONT_HERSHEY_PLAIN,?5,
????#?????????????(0,?0,?0),?5)

????#?img?=?mybutton.draw(img)
????cv2.imshow("output",?img)
????cv2.waitKey(1)

结论

这是虚拟键盘的实现,如果你想完善它,你也可以试着添加按键声音,然后我们还可以让键盘布局在框架内移动。

☆ END ☆

如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文。

扫描二维码添加小编↓

1f85548615fb955b3919b689f47916d7.png

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-12-02 16:45:14  更:2021-12-02 16:45:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 2:43:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码