Python手势识别与控制

2023-10-30

代码地址如下:
http://www.demodashi.com/demo/12968.html

Python手势识别与控制

概述

本文中的手势识别与控制功能主要采用 OpenCV 库实现, OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库, 可以运行在Linux, Windows, Android和Mac-OS操作系统上. 它轻量级而且高效---由一系列 C 函数和少量 C++ 类构成, 同时提供了Python, Ruby, MATLAB等语言的接口, 实现了图像处理和计算机视觉方面的很多通用算法.

本文主要使用了OpenCV的视频采集, 图像色域转换, 颜色通道分割, 高斯滤波, OSTU自动阈值, 凸点检测, 边缘检测, 余弦定理计算手势等功能.

准备工作

安装 Python-OpenCV

pip install opencv-python -i https://mirrors.ustc.edu.cn/pypi/web/simple

利用 -i 为pip指令镜像源, 这里使用电子科技大学的源, 速度比官方源更快.

安装 Numpy 科学计算库

pip install numpy -i https://mirrors.ustc.edu.cn/pypi/web/simple

安装 PyAutogui

pip install pyautogui -i https://mirrors.ustc.edu.cn/pypi/web/simple

图像的基本操作

import numpy as np
import cv2

imname =  "6358772.jpg"

# 读入图像
'''
使用函数 cv2.imread() 读入图像。这幅图像应该在此程序的工作路径,或者给函数提供完整路径.
警告:就算图像的路径是错的,OpenCV 也不会提醒你的,但是当你使用命令print(img)时得到的结果是None。
'''
img = cv2.imread(imname, cv2.IMREAD_COLOR)
'''
imread函数的第一个参数是要打开的图像的名称(带路径)
第二个参数是告诉函数应该如何读取这幅图片. 其中
    cv2.IMREAD_COLOR 表示读入一副彩色图像, alpha 通道被忽略, 默认值
    cv2.IMREAD_ANYCOLOR 表示读入一副彩色图像
    cv2.IMREAD_GRAYSCALE 表示读入一副灰度图像
    cv2.IMREAD_UNCHANGED 表示读入一幅图像,并且包括图像的 alpha 通道
'''

# 显示图像
'''
使用函数 cv2.imshow() 显示图像。窗口会自动调整为图像大小。第一个参数是窗口的名字,
其次才是我们的图像。你可以创建多个窗口,只要你喜欢,但是必须给他们不同的名字.
'''
cv2.imshow("image", img) # "image" 参数为图像显示窗口的标题, img是待显示的图像数据
cv2.waitKey(0) #等待键盘输入,参数表示等待时间,单位毫秒.0表示无限期等待
cv2.destroyAllWindows() # 销毁所有cv创建的窗口
# 也可以销毁指定窗口:
#cv2.destroyWindow("image") # 删除窗口标题为"image"的窗口

# 保存图像
'''
使用函数 cv2.imwrite() 来保存一个图像。首先需要一个文件名,之后才是你要保存的图像。
保存的图片的格式由后缀名决定.
'''
#cv2.imwrite(imname + "01.png", img) 
cv2.imwrite(imname + "01.jpg", img)

摄像头数据采集

我们经常需要使用摄像头捕获实时图像。OpenCV 为这中应用提供了一个非常简单的接口。让我们使用摄像头来捕获一段视频,并把它转换成灰度视频显示出来。从这个简单的任务开始吧。
为了获取视频,你应该创建一个 VideoCapture 对象。他的参数可以是设备的索引号,或者是一个视频文件。设备索引号就是在指定要使用的摄像头。一般的笔记本电脑都有内置摄像头。所以参数就是 0。你可以通过设置成 1 或者其他的来选择别的摄像头。之后,你就可以一帧一帧的捕获视频了。但是最后,别忘了停止捕获视频。

cap.read() 返回一个布尔值(True/False)。如果帧读取的是正确的,就是 True。所以最后你可以通过检查他的返回值来查看视频文件是否已经到了结尾。有时 cap 可能不能成功的初始化摄像头设备。这种情况下上面的代码会报错。你可以使用cap.isOpened(),来检查是否成功初始化了。如果返回值是True,那就没有问题。否则就要使用函数 cap.open()。

class  Capture(object):

'''
Capture object
:param deviceID: device ID of your capture device, defaults to 0
:type deviceID: :obj:`int`
Example
>>> import pygr
>>> cap = pygr.Capture()
'''

def  __init__(self, deviceID=0): # ID为0, 表示从默认的摄像头读取视频数据
    self.deviceID = deviceID
    self.capture = cv2.VideoCapture(self.deviceID) # 

def  read(self):
    _, frame =  self.capture.read() # 调用默认摄像头捕获一帧图像
    frame = cv2.bilateralFilter(frame, 5, 50, 100) # 对捕获到的图像进行双边滤波
    image = Image.fromarray(frame) # 转换图像数据格式
    return image

视频数据的处理

为了更准确的识别视频数据中包含的手势信息, 需要对视频数据进行预处理, 包括背景减除, 人体皮肤侦测.

背景减除

在很多基础应用中背景检出都是一个非常重要的步骤。例如顾客统计,使用一个静态摄像头来记录进入和离开房间的人数,或者是交通摄像头,需要提取交通工具的信息等。在所有的这些例子中,首先要将人或车单独提取出来。
技术上来说,我们需要从静止的背景中提取移动的前景。如果你有一张背景(仅有背景不含前景)图像,比如没有顾客的房间,没有交通工具的道路等,那就好办了。我们只需要在新的图像中减去背景就可以得到前景对象了。
但是在大多数情况下,我们没有这样的(背景)图像,所以我们需要从我们有的图像中提取背景。如果图像中的交通工具还有影子的话,那这个工作就更难了,因为影子也在移动,仅仅使用减法会把影子也当成前景。真是一件很复杂的事情。为了实现这个目的科学家们已经提出了几种算法。OpenCV 中已经包含了其中三种比较容易使用的方法: BackgroundSubtractorMOG , BackgroundSubtractorMOG2 , BackgroundSubtractorGMG。这里我们使用的是 BackgroundSubtractorMOG2 .

BackgroundSubtractorMOG 和 BackgroundSubtractorMOG2

*** BackgroundSubtractorMOG2*** 是一个以混合高斯模型为基础的前景/背景分割算法。它是 P.KadewTraKuPong和 R.Bowden 在 2001 年提出的。它使用 K(K=3 或 5)个高斯分布混合对背景像素进行建模。使用这些颜色(在整个视频中)存在时间的长短作为混合的权重。背景的颜色一般持续的时间最长,而且更加静止。一个像素怎么会有分布呢?在 x,y 平面上一个像素就是一个像素没有分布,但是我们现在讲的背景建模是基于时间序列的,因此每一个像素点所在的位置在整个时间序列中就会有很多值,从而构成一个分布。
在编写代码时,我们需要使用函数:*** cv2.createBackgroundSubtractorMOG() *** 创建一个背景对象。这个函数有些可选参数,比如要进行建模场景的时间长度,高斯混合成分的数量,阈值等。将他们全部设置为默认值。然后在整个视频中我们是需要使用 backgroundsubtractor.apply() 就可以得到前景的掩模了。

BackgroundSubtractorMOG2 也是以高斯混合模型为基础的背景/前景分割算法。它是以 2004 年和 2006 年 Z.Zivkovic 的两篇文章为基础的。这个算法的一个特点是它为每一个像素选择一个合适数目的高斯分布。(上一个方法中我们使用是 K 高斯分布)。这样就会对由于亮度等发生变化引起的场景变化产生更好的适应。
和前面一样我们需要创建一个背景对象。但在这里我们我们可以选择是否检测阴影。如果 detectShadows = True(默认值),它就会检测并将影子标记出来,但是这样做会降低处理速度。影子会被标记为灰色。

我们这里使用的就是 BackgroundSubtractorMOG2 算法, 详细代码如下:

# 移除视频数据的背景噪声
def _remove_background(frame):
    fgbg = cv2.createBackgroundSubtractorMOG2() # 利用BackgroundSubtractorMOG2算法消除背景
    # fgmask = bgModel.apply(frame)
    fgmask = fgbg.apply(frame)
    # kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
    # res = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)

    kernel = np.ones((3, 3), np.uint8)
    fgmask = cv2.erode(fgmask, kernel, iterations=1)
    res = cv2.bitwise_and(frame, frame, mask=fgmask)
    return res

# 视频数据的人体皮肤检测
def _bodyskin_detetc(frame):
    # 肤色检测: YCrCb之Cr分量 + OTSU二值化
    ycrcb = cv2.cvtColor(frame, cv2.COLOR_BGR2YCrCb) # 分解为YUV图像,得到CR分量
    (_, cr, _) = cv2.split(ycrcb)
    cr1 = cv2.GaussianBlur(cr, (5, 5), 0) # 高斯滤波
    _, skin = cv2.threshold(cr1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)  # OTSU图像二值化
    return skin

手势检测与识别

利用opencv提供的 convexityDefects 凹点检测函数检测图像凹陷的点, 然后利用, 然后根据凹陷点中的 (开始点, 结束点, 远点)的坐标, 利用余弦定理计算两根手指之间的夹角, 其必为锐角, 根据锐角的个数判别手势.
其中,锐角个数为0 ,表示 手势是 拳头,
锐角个数为0 ,表示 手势是 拳头,
锐角个数为1 ,表示 手势是 剪刀
锐角个数为2 ,表示 手势是 ,
锐角个数为3 ,表示 手势是 ,
锐角个数为4 ,表示 手势是

凹陷点计算

对象上的任何凹陷都被成为凸缺陷。OpenCV 中有一个函数 cv.convexityDefect() 可以帮助我们找到凸缺
陷. 函数调用如下. 如果要查找凸缺陷,在使用函数 cv2.convexHull 找凸包时,参数returnPoints一定要是 False.

hull = cv2.convexHull(cnt, returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)

它会返回一个数组,其中每一行包含的值是 [起点,终点,最远的点,到最远点的近似距离]。

# 检测图像中的凸点(手指)个数
def _get_contours(array):
        # 利用findContours检测图像中的轮廓, 其中返回值contours包含了图像中所有轮廓的坐标点
        _, contours, _ = cv2.findContours(array, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    return contours

# 根据图像中凹凸点中的 (开始点, 结束点, 远点)的坐标, 利用余弦定理计算两根手指之间的夹角, 其必为锐角, 根据锐角的个数判别手势.
def _get_defects_count(array, contour, defects, verbose = False):
    ndefects = 0
  
    for i in range(defects.shape[0]):
        s,e,f,_ = defects[i,0]
        beg     = tuple(contour[s][0])
        end     = tuple(contour[e][0])
        far     = tuple(contour[f][0])
        a       = _get_eucledian_distance(beg, end)
        b       = _get_eucledian_distance(beg, far)
        c       = _get_eucledian_distance(end, far)
        angle   = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) # * 57
            
        if angle <= math.pi/2 :#90:
            ndefects = ndefects + 1

            if verbose:
                cv2.circle(array, far, 3, _COLOR_RED, -1)

        if verbose:
            cv2.line(array, beg, end, _COLOR_RED, 1)

    return array, ndefects

def grdetect(array, verbose = False):
    event      = Event(Event.NONE)
    copy       = array.copy()
    array = _remove_background(array) # 移除背景, add by wnavy
    thresh = _bodyskin_detetc(array)

    contours   = _get_contours(thresh.copy()) # 计算图像的轮廓
    largecont  = max(contours, key = lambda contour: cv2.contourArea(contour))

    hull           = cv2.convexHull(largecont, returnPoints = False) # 计算轮廓的凸点
    defects        = cv2.convexityDefects(largecont, hull) # 计算轮廓的凹点
        
    if defects is not None:
        # 利用凹陷点坐标, 根据余弦定理计算图像中锐角个数
        copy, ndefects = _get_defects_count(copy, largecont, defects, verbose = verbose)

        # 根据锐角个数判断手势, 会有一定的误差
        if   ndefects == 0:
            event.setType(Event.ZERO)
        elif ndefects == 1:
            event.setType(Event.TWO)
        elif ndefects == 2:
            event.setType(Event.THREE)
        elif ndefects == 3:
            event.setType(Event.FOUR)
        elif ndefects == 4:
            event.setType(Event.FIVE)

        return event

手势控制

只要能够检测到手势, 相应的控制就简单很多了, 这里主要模拟手势控制web页面滚动, 手势 表示向下滚动, 手势 表示向上滚动. 只要明白了手势识别的核心原理, 更复杂的手势控制就完全看个人想象, 比如网络上有很多人实现 手势控制chrome浏览器中的那只小恐龙, 我也尝试过, 但是控制起来难度太大了, 还有的是实现手势播放, 切换歌曲. 只要有python, 这一切都很简单.

# imports - app imports
import pygr
import cv2
import time
from base import Keycode, Event
import pyautogui


if __name__ == '__main__':
    pad = pygr.PyGR(size = (480, 320), verbose = True)
    #pad = pygr.PyGR(size = (480, 320))
    pad.show()
    while cv2.waitKey(10) not in [Keycode.ESCAPE, Keycode.Q, Keycode.q]:
        event = pad.get_event()
        print("Event:", event.type, "Tip:", event.tip)
        if event.type == Event.FIVE : # 手势五, 向下滚动
            pyautogui.scroll(-30) # scroll down 10 "clicks"
        elif event.type == Event.FOUR :# 手势四, 向上滚动
            pyautogui.scroll(30) # scroll up 10 "clicks"
        time.sleep(0.1)

补充说明

为了demo简洁明了, 本文中省去了代码里的无关细节和调试部分, 比如程序运行时的实时识别和标记窗口部分的代码没有介绍, 但是代码中都有详细注释. 另外,对于不想研究细节只想 拿来主义 的同学, 只需要仿照上面 main中引入相关模块, 然后创建并运行PyGR模块, 不需要任何多余的操作.

运行方法

python main.py

程序运行截图

手势识别

运行截图

手势控制

运行截图

项目内文件截图

项目内文件截图

Python手势识别与控制

代码地址如下:
http://www.demodashi.com/demo/12968.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python手势识别与控制 的相关文章

  • pywinauto 32位用户警告

    我正在尝试使用 pywinauto 在每次更新类文件时自动启动和停止 TomCat 但是 当我尝试运行它时 它会给出以下警告 UserWarning 32 bit application should be automated using
  • CVXPY 二次规划; ArpackNoConvergence 错误

    我尝试使用 Python 包 CVXPY 来解决第一种形式的凸二次规划问题 https www cvxpy org examples basic quadratic program html https www cvxpy org exam
  • 只使用 Django 的某些部分?

    我喜欢 Django 但对于一个特定的应用程序 我只想使用它的一部分 但我对 Django 的内部工作原理还不够熟悉 所以也许有人可以指出我必须做什么的正确方向查看 具体来说 我想使用 模型和数据库抽象 The 缓存API http doc
  • 如何为 Intellij/PyCharm 设置 PYTHONSTARTUP 脚本

    我尝试添加PYTHONSTARTUP环境变量 我还尝试了自定义启动脚本 但更令人惊讶的是 这also没有工作 npa别名无法识别 出于一点绝望 我什至尝试添加到interpreter options 那什么也没做 实际上是什么Interpr
  • scipy.misc.imshow RuntimeError('无法执行图像视图')

    我正在测试scipy misc imshow https docs scipy org doc scipy 0 15 1 reference generated scipy misc imshow html我得到了运行时错误 无法执行图像查
  • Spyder 导入模块出错

    我正在尝试在 Spyder 中使用 sklearn 一开始 当我尝试导入它时 我收到 ImportError No module named sklearn 然后我用 PYTHONPATH 管理器设置 PATH 然后使用工具菜单中的 更新模
  • turtle.Screen().screensize() 未输出正确的屏幕尺寸[重复]

    这个问题在这里已经有答案了 我编写了一些代码来在屏幕周围随机放置点 但是 它并没有覆盖整个屏幕 import turtle import random t turtle Turtle color red green blue pink ye
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • 使用 3d 对象作为 3d 散点图中的标记 - Python

    使用下面的代码 我尝试模拟一个用罐头制成的碗 我希望每个标记都是一个罐头 最好的方法是什么 我真的很感激任何建议 谢谢 import pylab import numpy as np from math import pi sin cos
  • Python,多线程,获取网页,下载网页

    我想在一个站点批量下载网页 我的 urls txt 文件中有 5000000 个 url 链接 大约有300M 如何让多线程链接这些网址并下载这些网页 或者如何批量下载这些网页 我的想法 with open urls txt r as f
  • 如何在交互式绘图(Python)中获得鼠标指向的(x,y)位置?

    我使用 ipython 笔记本 带有魔法 matplotlib nbagg 我正在审查matplotlib widget Cursor但仅查看光标widgets Cursor http matplotlib org 1 4 3 exampl
  • 如何绘制多类分类器的精度和召回率?

    我正在使用 scikit learn 我想绘制精度和召回曲线 我正在使用的分类器是RandomForestClassifier scikit learn 文档中的所有资源都使用二元分类 另外 我可以绘制多类的 ROC 曲线吗 另外 我只找到
  • PyCharm - 如何挂起所有线程

    我们使用 PyCharm 5 0 1 进行多线程调试 当它在断点处停止时 只有特定线程停止 而所有其他线程继续 这使得 冻结时刻 和检查参数值以及其他线程的当前状态变得困难 当其中一个线程在断点处停止时 是否可以挂起所有线程 这在最新的 P
  • Scrapy的redirect_urls异常.KeyError

    我是 Scrapy 和 Python 的新手 最近推出了我的第一个蜘蛛 有一个功能似乎以前有效 但现在它只适用于我试图废弃的一些网站 代码行是 item url direct response request meta redirect u
  • 使用 statsmodels.formula.api 中的 ols - 如何删除常数项?

    我正在遵循第一个例子statsmodels教程 http statsmodels sourceforge net devel http statsmodels sourceforge net devel 如何指定在 ols 中不使用常数项进
  • Python 中的十进制到二进制半精度 IEEE 754

    我只能使用以下命令将十进制转换为二进制单精度 IEEE754struct pack模块 或者使用相反的方法 float16 或 float32 numpy frombuffer 是否可以使用 Numpy 将十进制转换为二进制半精度浮点数 我
  • 如何使用 pygame.mixer 重复音乐?

    我创建了以下使用 pygame mixer 播放 mp3 音乐的代码 然而 音乐不会重复 有什么想法可以让音乐重复播放吗 这是代码 playlist list playlist append put music here mp3 playl
  • 如何可视化多维数据上的 kmeans 聚类

    我在 mnist 数据集上使用 kmeans 聚类算法 并希望可视化聚类后的图 到目前为止我做了这个 from mnist import MNIST mndata MNIST Datasets X train y train mndata
  • 在Python中从CSV文件中获取随机行并找到相应的单词,就像测验一样

    抱歉标题含糊不清 想不出更好的表达方式 我有一个包含德语 英语单词的 CSV 文件 如下所示 Ja Yes Nein No Katze Cat 我希望我的 python 脚本从 CSV 文件中打印一个随机的德语单词 并要求他们输入英语单词
  • django admin 中内联模型的分页器

    我有这个简单的 django 模型 由一个传感器和特定传感器的值组成 每个日射强度计的值数量很多 gt 30k 是否可以以某种方式分页PyranometerValues在特定日期或一般情况下将分页器应用于管理内联视图 class Pyran

随机推荐

  • 转载:开源mes系统_基于SpringBoot 开源框架,设计MES系统源码分享(代码标准规范)

    Hutool 是一个小而全的Java工具类库 通过静态方法封装 降低相关API的学习成本 提高工作效率 使Java拥有函数式语言般的优雅 让Java语言也可以 甜甜的 请求参数每张表的分页查询参数 严格按照一张表对应一个请求参数对象进行开发
  • NTSC、PAL、SECAM彩色电视制式

    NTSC PAL和SECAM是世界上最主要的三大电视制式 并且这三种制式间不能兼容 例如PAL的视频不能在NTSC制式的电视上播放 下图是三种制式在世界上的使用分布图 NTSC制式 NTSC制式 简称N制 是1952年12月由美国国家电视标
  • 老公老婆

    1 老公 你要努力挣钱 钱这个东西 不能少得来让我们整日为生计发愁 最好也不能多得来需要别的女人帮着花 2 请给我关爱 信任 尊重和自由 3 你要加强锻炼 强健身体 好在我们共同返家的夜晚 一口气抱我上到五楼的家门 我渴望每天都能做你的新娘
  • 21天Python进阶学习挑战赛

    21天Python进阶学习挑战赛活动详情 1 活动介绍 2 作者介绍 3 专栏介绍 4 学习计划 1 活动介绍 CSDN与每一位学习者同行 平台优质专栏作者带队精准学习 精选高质量专栏学习资料活动期内限时免费学习 此刻开启学习打卡之路 收获
  • LETTERS

    http poj org problem id 1154 Description A single player game is played on a rectangular board divided in R rows and C c
  • 大数据从0到1的完美落地之sqoop命令执行

    Sqoop命令执行 常见命令执行参数 通过Sqoop加不同参数可以执行导入导出 通过sqoop help 可以查看常见的命令行 常见Sqoop参数 root qianfeng01 sqoop 1 4 7 sqoop help codegen
  • 前端面试 - 项目流程

    目录 1 项目流程 2 项目角色 3 完整项目流程 4 项目沟通 5 PM想在开发过程中增加需求 该怎么办 6 项目即将延期了 该怎么办 7 你将如何保证项目质量 1 项目流程 1 项目分多人 多角色参与 2 项目分多阶段 3 项目需要计划
  • commons-pool2源码走读(四) 对象池实现GenericObjectPool

    commons pool2源码走读 四 对象池实现GenericObjectPool
  • Springboot实现短信验证登陆

    1 导入依赖
  • 商品评论表设计

    总共5张表 设计如下 create sequence SEQ TRADESCORE AUTOINC minvalue 1 maxvalue 9999999999999 start with 1 increment by 1 nocache
  • ListView获取当前最顶部的item

    ListView获取当前最顶部的item 1 private void setupContactsListView 2 lst addessbook setOnScrollListener new OnScrollListener 3 Ov
  • Python手册(Scientific Computing)--SymPy

    SymPy Symbol Python的简称 是一个用于符号数学的Python库 它旨在成为一个功能齐全的计算机代数系统 CAS 同时保持代码尽可能简单 以便易于理解和易于扩展 SymPy完全用Python编写 不依赖于外部库 Introd
  • PowerDesigner 模型类型介绍

    目录 PowerDesigner 提供了两种方式组织模型 分别是Categories和Model types 1 Categories方式是从企业架构建模角度出发 主要包含业务层 信息层 应用层 技术层 需求与规划层 1 1 业务层主要用于
  • tmux系列:2、tmux会话

    tmux系列 2 tmux会话 文章目录 tmux系列 2 tmux会话 1 前言 2 创建会话 3 状态栏 4 命令和标志 5 命令提示符 6 附加和分离 7 会话清单 8 完全杀死tmux 9 总结一下 1 前言 其实最开始时候我用tm
  • less两种转换方式

    一 浏览器端转换 link导入 less文件
  • 深聊全链路压测之:第二十二讲

    解决 GoReplay 动态数据关联 1 引言 2 中间件 2 1 什么是中间件 2 2 如何使用中间件 3 关联 3 1 什么是关联 3 2 关联回放实现 4 总结 1 引言 第二十讲 我们聊的是GoReplay平台的搭建 在私下里 不少
  • 使用html表单制作简单网页(加表单详细知识点)

    表单也是html非常重要的一块 常用于输入信息 进行信息的收集和提交 属性 action 信息提交地址 method 提交方式 get 信息拼接在地址中 不安全 post 信息打包发送 安全 select 下拉菜单 option 下拉菜单中
  • 无法获取 java Console 对象

    在eclipse环境中调用System console 获取Console对象 打印返回对象为空 反复试验都是相同结果 Console con System console if con null System out println co
  • 分布式系统:数据分区

    数据分区 每一条数据只属于某个特定分区 一个大数据集可以分散在更多的磁盘上 查询负载也随之分布到更多的处理器上 每个节点对自己所在分区可以独立执行查询操作 因此可以提高查询的吞吐量 通常一个节点负责几个分区 采用数据分区的主要目标是提高可扩
  • Python手势识别与控制

    代码地址如下 http www demodashi com demo 12968 html Python手势识别与控制 概述 本文中的手势识别与控制功能主要采用 OpenCV 库实现 OpenCV是一个基于BSD许可 开源 发行的跨平台计算