视频通话数十亿无互联网
通过蜂窝电话呼叫进行可靠的视频通话和屏幕共享
图片来自 iStockphoto,授权给 P.K. Mishra
本博客中表达的观点和意见纯属我个人的观点和意见,并不代表我现在或过去雇主的官方立场。
上个周末,我看到一篇新闻文章提到数百万印度学生被困在家里,既不能上网,也不能接受在线教育。事实上,超过一半的世界人口仍然没有任何互联网连接。虽然这种数字鸿沟已经在美国显现出来,特别是在冠状病毒疫情封锁期间的儿童教育方面,但亚洲和非洲的问题要严重得多,那里只有不到五分之一的人连接到互联网。
由于在全球范围内实施封锁,许多成人和儿童被排除在在线教育和远程保健之外。
WhatsApp 视频通话
尽管上面提到了五分之一的统计数据,但实际上问题更严重。即使对那些能上网的人来说,价格也很高,而且带宽有限。例如,在与我在印度的父母交谈时,他们经常在配额期之前用完分配给他们的 4 GB,此后带宽被节流:停滞的帧、断断续续的音频、令人痛苦的延迟和最终的断开,以及随后的重试是正常现象,但仍然可以说比正常的电话交谈好得多,因为我可以“看到”它们。
当安德鲁·斯图亚特解释说视频通话更有利于人们的心理健康时,我明白了。但是,视频通话通常需要 2 Mbps 的速度提升和 2 Mbps 的速度下降,就像 Zoom 的情况一样,许多人都无法享受这一特权。
为了解决这个问题,我提出了一种新的方法,这种方法基于这样一种认识,即如果我们愿意放弃一些面部和屏幕的现实主义或逼真的渲染,那么可以为超低带宽导出一个全新的面部和屏幕表示世界,并具有可接受的体验质量。
本文探讨了这样的表示和方法,它们将所需的带宽从正常的 2 Mbps 降低到 1.5 Kbps,允许视频与电话音频一起编码,而音频质量的下降最小。所提出的解决方案可以主要实现为软件,而不需要改变底层基础设施。这反过来会更便宜,并允许目前因支付能力而被边缘化的人接入互联网。
移动电话与互联网
如果你确信手机通话比 VoIP 通话更可靠、更快捷、更好,你可以跳过这一部分
从轶事经验来看,很明显,蜂窝电话呼叫在许多属性上通常比视频呼叫更可靠,例如延迟、掉线、易于使用、呼叫质量变化最小以及长途选项。
像 Google Meet、Discord、Gotomeeting、Amazon Chime 和潜在的脸书这样的视频电话提供商使用一种叫做 WebRTC 的协议,这种协议可以实现两方或多方之间的实时通信。WebRTC 还依赖于一种称为用户数据报协议的互联网协议,该协议提供了快速的数据包传递,但提供的保证较差,导致一些数据包要么没有到达,要么没有按顺序到达,从而导致帧丢失和抖动(对等点之间数据包流的延迟变化)。较新的机器学习技术,如在 Google Duo 中使用 WaveNetEq,提高了音频质量,但视频质量变化仍未解决。
另一方面,虽然蜂窝电话呼叫也越来越多地基于分组,但工程师们已经找到了通过不断确保严格的质量标准和巧妙的带宽管理来提高分组交换手机网络效率的方法。蜂窝电话工作良好的另一个原因是音频所需的带宽比视频低得多。此外,编码标准已经发展了几十年,允许人脑填补空白。我将最终证明,互联网视频通话的许多目标,如双向视频通话、多方视频广播和直播事件、屏幕共享、体验质量的 A/B 测试(QoE)⁷)也可以通过蜂窝电话实现。然而,在本文的其余部分,我们将只关注双向视频通话,以便做好准备。
架构:电话视频
教育视频的主要目标是获得最小的视频表示,优先考虑信息传输(例如白板、草图),其次是人类动作(例如指点、书写)和表情(例如嘴唇、眉毛),,同时排除干扰元素,例如背景、面部的无表情元素,以及恼人的视频呼叫元素,例如定格、可变帧速率等。另一个架构目标是优先考虑具有低延迟和低抖动(平滑和一致)以及高音频质量的可靠帧速率。
可用于视频通话的绝对最差(最低)带宽的信封背面计算
在任何电话呼叫中,人类对延迟的容忍度最多为 200 毫秒。对于电话呼叫,所有的数据包都无关紧要,因为编码方案非常复杂,即使一些数据包丢失,呼叫者仍然可以听到。复杂的方案可以处理基于可用带宽自适应调整的多种传输速率。因此,自适应多码率编解码器 (AMR)大行其道。AMR 编解码器使用八种源编解码器,比特率分别为 12.2、10.2、7.95、7.40、6.70、5.90、5.15 和 4.75 Kbps。对于我们的分析,我们选择 7.95 Kbps 作为最差情况分析。假设帧率为每秒 24 帧,视频压缩比为 100 (H.264 有损视频压缩可高达 200),**我们得到一个大约 1kb/帧的未压缩目标作为信封背面计算。假设音频传输速率为 7.5 kbps,其中 3.2 kbps 分配给双向视频传输,4.75 kbps 分配给音频传输。**如果我们要达到这个最坏情况的设计目标,我们肯定可以做得更好。
视频捕捉
第一步是拍摄视频。对于我的原型,我以每秒 24 帧的速度捕捉了 640x480 帧大小的视频,因为这个频率对于获得美学电影般的运动特征来说已经足够好了。
接近真实的视频表现
我尝试了不同的视频格式,但我决定采用二值图像(每个像素不是黑就是白)格式,使用简单的全局阈值来获得下面的视频。还有其他可用的二级阈值技术,如自适应均值阈值和自适应高斯阈值,后者噪声较小,但我喜欢将高级视频处理推迟到分割之后,因为我认为最好优先处理某些区域(如面部、白板),而不是全局方法。如果神经计算在发送方是不可能的,那么一个简单的全局阈值可能会起作用。
使用 OpenCV 以 24fps 的简单二值阈值视频
我还试验了 ASCII 渲染格式,如下图所示。
使用 iDevelop Github 提供的 HTML5 getUserMedia API 的 Ascii 视频表示:【https://github.com/idevelop/ascii-camera
此外,我尝试了神经风格转移技术,使用基于 paper⁶的示例代码和由 Justin Johnson 、 Alexandre Alahi 、李飞飞提供的 Github 代码,但最终我出于完全实用的原因决定追求二值图像。
视频语义分割
这里的核心思想是,我们可以使用深度学习来分割和优先考虑一帧的特定区域。在这种情况下,我按优先级降序排列了以下部分:白板、手、脸、躯干和背景。
一帧原始图像
分段训练样本
我使用 Superannotate 来注释我的视频,并结合 OpenCV 和达芬奇解析 16 来增强分割的视频帧。
基于片段的视频增强
下一步是移除背景,然后是曝光、阴影和对比度增强。然而,确切的参数高度依赖于照明和曝光,因此我为我的训练样本开发了一些启发法。
我决定应用 S 曲线增强的试探法,而不是涉及曝光、阴影和对比度增强的多个步骤。
s 曲线增强,通过调整帧的色调属性来增加对比度
在 RGB 图像的色调直方图中,左下象限表示阴影,而右上象限表示高光。一个简单的试探是将阴影区域中的色调减少大约一个标准偏差,并将高亮区域中的色调增加大约两个标准偏差。
设置阈值
在设置二值图像的阈值时,我应用了将它设置在分布峰值的启发式方法。这种启发法似乎至少适用于夜间照明。
简单全局阈值和人工智能分割阈值。请注意白板的背景移除和清晰度
总体而言,基于分割视频帧的局部视频预处理提供了具有更高清晰度的二值图像。
矢量化
下一步是将二值像素化图像转换成矢量图像。由于基于矢量的图像不是由特定数量的点组成的,因此它们不仅可以在不损失任何质量的情况下缩放到更大的尺寸,还可以显著减少图像的占用空间。
左边是原始像素帧,右边是矢量帧
放大脸部:左边是原始像素帧,右边是矢量帧
放大白板:左边是原始像素框架,右边是矢量框架
编码
编码是压缩数据以适应可用的通信带宽以及满足延迟要求所必需的。大多数视频编码标准是基于离散余弦变换(DCT)的。像 H.264 标准这样的转换可以将视频压缩 200 倍,但是 H.264 不仅计算量很大,而且是为“自然”渲染而构建的。出于这个原因,我决定探索视频编码器优化我们的具体用途。视频压缩技术包括空间压缩和时间压缩,空间压缩利用单个帧内的冗余,时间压缩利用帧间的冗余,例如运动冗余。目前,我正在尝试不同的编码技术,以获得体验质量和压缩之间的平衡。这项研究包括基于二级位图(像素)的帧以及基于矢量的帧。流行的二值位图图像压缩方法有游程编码,熵编码如算术编码,以及二值图像的 JBIG2 标准。接下来,我将研究利用运动冗余。
解码和渲染
在接收端解码压缩流视频后,需要在智能手机或电视等大屏幕上呈现视频。矢量表示很容易缩放,并且很适合表示白板信息,但是它们会导致不真实的人脸渲染,这对于我们的目的来说可能很好。但是,我们需要测试体验的质量来证实这一点。另一方面,基于位图的表示在缩放时会导致像素化。应该注意的是,有一些简单的算法可以用于增强这些帧,例如最近邻增强、双三次增强、锐化和去除伪像。
总之,我从 640 x 480 的 RGB 图像(~ 1mb/帧)开始,并将其转换为二值图像(~ 38kb/帧)。矢量化进一步将帧大小减少到大约 10kb/帧。虽然这比我们之前讨论的 1kb/帧的最坏情况目标还远,但我相信有机会达到该目标。通过使用利用冗余的定制压缩技术(例如没有背景)或通过极端矢量化中的进一步机会(例如具有线条画),这是可能的。
研究挑战和后续步骤
基于发送端或接收端的可用计算以及可用的通信带宽,有许多方法值得研究。
基于发送方或接收方可用计算的潜在方法
视频优化
研究领域包括优化空间频率周围的视频编码,以更好地解释人类 actions⁴和面部表情,如面部动作编码 Systems⁵.
小说表述
ASCII、3D 化身和其他人类可理解的表示法等简单表示法值得研究。基于端到端人工智能的方法,如使用自动编码器可以用来生成紧凑的中间表示,尽管中间潜在空间编码不能被人类理解。在所有方法中,我最看好自动编码器和相关技术。另一种方法是面部动作编码系统 (FACS),其中中间表示由控制不同肌肉和运动的动作单元(au)组成。这样的 FACS 中间表示实际上可以以大约 44 个 AUs 编码面部和位置,3 个用于 XYZ 平移,3 个用于角度,导致每帧 50 个浮点或 200 个字节,这在压缩后可以低得多,几乎肯定比 1kb/帧的目标低得多。这种编码可用于在接收者端呈现化身。后两种方法在发送方和接收方都需要大量的计算。
音频编码
这是我认为最大的挑战。在呼叫的任何一端都有大量的音频编码标准,如增强语音服务、可变速率多模式宽带、多速率宽带、增强可变速率编解码器、GSM 增强全速率等。当一个呼叫从一个国家的一个运营商发起,并在另一个国家的另一个运营商结束时,流式音频的质量会因使用的编码和连接质量的不同而有很大差异。面临的挑战是将视频与音频一起编码,以便视频可以被可靠地解码并在传输中“幸存”。
新型应用的框架
有许多新颖的应用,例如使用矢量图形动画的交互式教学方法,甚至极简主义的增强现实以及视频和音频呼叫。
来源维基百科:https://en . Wikipedia . org/wiki/File:Completing _ the _ square . gif
**用户:**打造安卓 app 做试点。
如果您能提供一些反馈,或者将这篇文章转发给可能拥有资源和人才来开发完整解决方案和可在发展中国家部署用于教育目的的 Android 应用程序的个人或公司,我将不胜感激。在过去的周末,我一直在处理这个问题,对我来说,快速开发一个解决方案是不切实际的。我提前感谢你的帮助!
[1]劳伦·e·谢尔曼;米纳斯·米奇扬;帕特里夏·格林菲尔德; 文字、音频、视频、当面交流对朋友间粘合的影响 。网络心理学:网络空间心理社会研究杂志,2013,7 (2),第 3 条。
[2]加西亚,b;GallegoGortázar,f;Bertolino,a ., 理解和评估 WebRTC 应用程序的体验质量。计算 2018,101,1–23。
[3]帕布罗·巴雷拉,软件工程师,谷歌研究院和弗洛里安·斯廷伯格,研究工程师,DeepMind, 用 WaveNetEQ *,*2020 年 4 月 1 日,谷歌 AI 博客。
[4]Steven m . Thurman Emily d . Grossman,诊断空间频率和人类辨别行动的效率,2010 年 11 月 16 日,Springer,注意力、知觉和心理物理学。
[5]保罗·艾克曼,面部动作编码系统,1978 年。
[6] 贾斯廷·约翰逊,亚历山大阿拉希,李菲菲,实时风格传递和超分辨率的感知损失,2016 年,欧洲计算机视觉大会。
[7]朱莉(诺瓦克)贝克利,安迪·海因斯,,马修·沃德罗普,托比·毛,马丁·廷利,[大规模流媒体实验的数据压缩](http://Data Compression for Large-Scale Streaming Experimentation),2019 年 12 月 2 日,科技博客。
使用 Fast.ai 和 OpenCV 进行视频面部表情和意识检测
从实时视频或视频文件中检测面部表情和意识
这背后的灵感?联邦调查局特工通过我的网络摄像头监视我,但被深度学习取代:)
实时视频分类器演示
介绍
本教程的目标?使用 fast.ai 库训练面部表情分类模型,从网络摄像头或视频文件中读取面部表情,最后,添加面部地标来跟踪你的眼睛以确定意识!(TL;博士完整的工作代码在这里【https://github.com/jy6zheng/FacialExpressionRecognition
我写这篇教程的主要原因是,在做这个项目时,一个很大的挑战是弄清楚如何使用我训练过的分类器,并使它有效地处理实时视频和视频文件。额外的眼部标记功能是基于我发现非常有用的本教程:https://www . pyimagesearch . com/2017/05/08/sledy-detection-opencv/
培养
第一步是用卷积神经网络训练图像分类模型。我使用的数据来自https://www . ka ggle . com/jonathanoheix/face-expression-recognition-dataset
我使用了构建在 PyTorch 之上的 fast.ai 库来训练我的分类模型。该模型使用 resnet34 预训练权重和训练数据集进行训练,并导出为. pkl 文件。关于一步一步的指导,请查看我的知识库中的 google colab 笔记本,它包含了训练你的模型的所有代码:https://github.com/jy6zheng/FacialExpressionRecognition
最大的挑战是首先找到一个公共数据集,然后清理数据。最初,当我使用 Kaggle 数据集时,我只能训练到 0.328191 的错误率,这意味着它只有大约 68%的时间是正确的(根本不是很好)。当我绘制产生最高损失的图像时,我很快意识到大量数据被错误地标记(左边是模型预测的表达,右边是标记的情绪)。
坐在最后一排左三的女孩看起来显然不开心
数据清洗后,错误率下降了 16%以上。现在分类器有大约 84%的准确率,这意味着它正确地识别了 84%的面部图像。仍有一些不正确和不完整的数据,因此还有进一步改进的空间。
正如你所看到的,中性和悲伤的脸最容易混淆
在实况视频上使用训练模型
现在,是时候将我们的分类器用于现场视频流了。首先,最好创建一个虚拟环境,这样这个项目就有自己的依赖项,并且不会干扰任何其他项目。然后,下载所需的包和库。创建一个名为 liveVideoFrame.py 的文件(或您想命名的任何名称),并导入以下内容:
from scipy.spatial
import distance as dist
import numpy as np
import cv2
from imutils import face_utils
from imutils.video import VideoStream
from fastai.vision import *
import imutils
import argparse
import time
import dlib
我想选择将预测保存在一个. csv 文件中,并保存带标记的视频,所以我添加了参数解析。我还导出了经过训练的分类模型,并将其移动到我的工作目录中。
ap = argparse.ArgumentParser()
ap.add_argument("--save", dest="save", action = "store_true")
ap.add_argument("--no-save", dest="save", action = "store_false")
ap.set_defaults(save = False)
ap.add_argument("--savedata", dest="savedata", action = "store_true")
ap.add_argument("--no-savedata", dest="savedata", action = "store_false")
ap.set_defaults(savedata = False)
args = vars(ap.parse_args())path = '/Users/joycezheng/FacialRecognitionVideo/' #change this depending on the path of your exported model
learn = load_learner(path, 'export.pkl')
太好了!现在是时候开始我们的视频流了。我使用 imutils.video 的 VideoStream,因为我发现它比 cv2.VideoCapture 工作得更快。**注意:**对于内置的网络摄像头,视频流的来源是 0,如果您使用不同的相机,如插件,它会有所不同。
haar 级联分类器用于识别视频帧中的正面人脸。我们有一个名为 data 的数组来存储我们的预测。timer 和 time_value 用于标记数据中每个预测的时间,以便在. csv 文件中预测以 1 递增。
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
vs = VideoStream(src=0).start()
start = time.perf_counter()
data = []
time_value = 0
if args["save"]:
out = cv2.VideoWriter(path + "liveoutput.avi", cv2.VideoWriter_fourcc('M','J','P','G'), 10, (450,253))
现在,我们将实现一个 while 循环,从视频流中读取每一帧:
- 因为图像分类器是在灰度图像上训练的,所以每一帧都被转换成灰度图像
- 级联分类器用于在帧中寻找人脸。我将 minneighbors 参数设置为 5,因为我发现它在实时视频上效果最好。对于录制的视频文件,我将其设置为较高的值,因为每一帧中肯定会有一张脸
- 由于我们的分类器是在没有太多背景的特写人脸上训练的,因此灰度图像随后被裁剪为具有 0.3 缓冲的人脸
- 然后,在每一帧上绘制并显示文本和边界框
- 然后使用 out.write(frame)将每一帧保存到视频编写器中
while True:
frame = vs.read()
frame = imutils.resize(frame, width=450)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
face_coord = face_cascade.detectMultiScale(gray, 1.1, 5, minSize=(30, 30))
for coords in face_coord:
X, Y, w, h = coords
H, W, _ = frame.shape
X_1, X_2 = (max(0, X - int(w * 0.3)), min(X + int(1.3 * w), W))
Y_1, Y_2 = (max(0, Y - int(0.3 * h)), min(Y + int(1.3 * h), H))
img_cp = gray[Y_1:Y_2, X_1:X_2].copy()
prediction, idx, probability = learn.predict(Image(pil2tensor(img_cp, np.float32).div_(225)))
cv2.rectangle(
img=frame,
pt1=(X_1, Y_1),
pt2=(X_2, Y_2),
color=(128, 128, 0),
thickness=2,
)
cv2.putText(frame, str(prediction), (10, frame.shape[0] - 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (225, 255, 255), 2) cv2.imshow("frame", frame) if args["save"]:
out.write(frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
breakvs.stop()
if args["save"]:
print("done saving video")
out.release()
cv2.destroyAllWindows()
现在,我们有了 fast.ai 学习模型,它可以与 imutils 和 OpenCV 合作,从直播视频中预测人脸!
接下来,是时候确定面部的意识了。函数 eye_aspect_ratio 根据眼睛的坐标计算眼睛的纵横比。从 dlib 预训练的面部标志检测器中找到每只眼睛的位置和坐标。函数 data_time 用于每隔 1 秒在数据数组中追加预测。
EYE_AR_THRESH = 0.20
EYE_AR_CONSEC_FRAMES = 10COUNTER = 0def eye_aspect_ratio(eye):
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
C = dist.euclidean(eye[0], eye[3])
ear = (A + B) / (2.0 * C)
return eardef data_time(time_value, prediction, probability, ear):
current_time = int(time.perf_counter()-start)
if current_time != time_value:
data.append([current_time, prediction, probability, ear])
time_value = current_time
return time_valuepredictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
在遍历面坐标的 for 循环中,添加以下代码块。使用 dlib 面部标志检测器检测眼睛,并将其绘制到帧上。当两只眼睛之间的平均计算眼睛纵横比小于超过十个连续帧的阈值(您可以根据自己的喜好修改该阈值)时,则该面部被标记为分心。
rect = dlib.rectangle(X, Y, X+w, Y+h)
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
leftEye = shape[lStart:lEnd]
rightEye = shape[rStart:rEnd]
leftEAR = eye_aspect_ratio(leftEye)
rightEAR = eye_aspect_ratio(rightEye)
ear = (leftEAR + rightEAR) / 2.0
leftEyeHull = cv2.convexHull(leftEye)
rightEyeHull = cv2.convexHull(rightEye)
cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)
if ear < EYE_AR_THRESH:
COUNTER += 1
if COUNTER >= EYE_AR_CONSEC_FRAMES:
cv2.putText(frame, "Distracted", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
else:
COUNTER = 0
cv2.putText(frame, "Eye Ratio: {:.2f}".format(ear), (250, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
time_value = data_time(time_value, prediction, probability, ear)
最后,在代码的底部,我们可以将数据保存为数据帧,然后保存为. csv 文件。
if args["savedata"]:
df = pd.DataFrame(data, columns = ['Time (seconds)', 'Expression', 'Probability', 'EAR'])
df.to_csv(path+'/exportlive.csv')
print("data saved to exportlive.csv")
您可以通过运行以下命令在命令行中测试代码:
python liveVideoFrameRead.py --save --savedata
完整的代码在这里:
对视频文件使用训练模型
我对视频文件使用了与实况视频非常相似的方法。主要区别在于预测每隔一定数量的帧发生一次,这可以使用命令行参数— frame-step 来修改。完整代码如下:
就是这样!你现在可以从视频文件和网络摄像头中预测面部表情。
谢谢你看了这个:),如果有什么改进或者问题请告诉我。完整的工作代码在这里:https://github.com/jy6zheng/FacialExpressionRecognition
使用深度学习和 PyTorch (-lightning)的视频预测
卷积 LSTM 模型的简单实现
托马斯·威廉在 Unsplash拍摄的照片
在本指南中,我将向您展示如何使用一个自动编码器 (seq2seq)架构对卷积长短期记忆(ConvLSTM)进行编码,该架构使用 MovingMNIST 数据集进行帧预测(但也可以轻松集成自定义数据集)。
这种方法最初用于 2015 年NIPS的降水预报,此后通过 PredRNN、PredRNN++和 Eidetic 3D LSTM 等方法得到了广泛的扩展…
我们还使用了 pytorch-lightning 框架,这对于删除大量样板代码非常有用,并且可以轻松集成 16 位训练和多 GPU 训练。
开始之前,我们将简要概述一下我们正在使用的库:
python=3.6.8 torch=1.1.0 torchvision=0.3.0 pytorch-lightning=0.7.1 matplotlib=3.1.3 tensorboard=1.15.0a20190708
1.数据加载器
从以下 repotychovdo/moving NIST下载数据加载器脚本。
该数据集最初是由开发并在此处描述的,它包含 10000 个序列,每个序列长度为 20,帧大小为 64 x 64,显示 2 个数字在不同轨迹上移动(并重叠)。
需要预先注意的是手指轨迹固有的随机性。我们确实期望这将成为我们将要描述的模型的一个主要障碍,并且我们也注意到更新的方法,例如变化的自动编码器,对于这种类型的任务可能是一个更有效的模型。
2.模型架构
我们将使用的特定模型类型称为 seq2seq 模型,通常用于 NLP 或时序任务(它实际上是在 2016 年的谷歌翻译引擎中实现的)。
关于 seq2seq 的原论文有 Sutskever 等人,2014 和 Cho 等人,2014 。
在其最简单的配置中,seq2seq 模型将一系列项目作为输入(例如单词、单词嵌入、字母等。)并输出另一个项目序列。对于机器翻译,输入可以是西班牙语单词序列,输出是英语翻译。
我们可以将 seq2seq 模型分成三个部分,分别是
a)编码器(编码输入列表)
b)编码器嵌入向量(整个输入序列的最终嵌入)
c)解码器(将嵌入向量解码成输出序列)
对于我们的机器翻译示例,这意味着:
- 编码器通过顺序处理每个单词,将西班牙语序列作为输入
- 编码器输出一个嵌入向量作为我们输入的最终表示
- 解码器将嵌入向量作为输入,然后输出英语翻译序列
希望 a)部分和 c)部分对你来说比较清楚。就 seq2seq 模型的直觉而言,可以说最棘手的部分是编码器嵌入向量。你如何准确定义这个向量?
2.1 认识 RNN
在你继续前进之前,我强烈推荐以下关于 RNN/LSTM 的精彩博文。密切了解 LSTM 的是大多数 seq2seq 模型的必要先决条件!
以下是常规 LSTM 电池的方程式:
其中∘表示哈达玛乘积。
让我们假设你完全理解什么是 LSTM 细胞,以及细胞状态和隐藏状态是如何工作的。seq2seq 型号中的编码器和解码器通常由 LSTM 单元组成,如下图所示:
分解
- LSTM 编码器由 4 个 LSTM 单元组成,LSTM 解码器由 4 个 LSTM 单元组成。
- 每个输入(单词或单词嵌入)与来自先前 LSTM 单元的隐藏状态(输出)一起被馈送到新的编码器 LSTM 单元
- 来自最终 LSTM 编码器单元的隐藏状态(通常)是编码器嵌入。它也可以是来自所有编码器 LSTM 单元的隐藏状态的整个序列(注意——这与注意不同)
- LSTM 解码器使用编码器状态作为输入,并通过各种 LSTM 单元迭代处理这些状态以产生输出。这可以是单向的或双向的
存在对标准 seq2seq 模型的几个扩展;最引人注目的是注意力模块。
讨论了 seq2seq 模型之后,让我们将注意力转向帧预测任务!
2.2 帧预测
帧预测与 seq2seq 原有的任务如机器翻译有着本质的区别。这是因为编码器和解码器中的 RNN 模块(LSTM)使用全连接层来编码和解码单词嵌入(表示为向量)。
一旦我们处理了帧,我们就有了 2D 张量,为了按顺序编码和解码,我们需要扩展原始的 LSTM seq2seq 模型。
ConvLSTM
这就是卷积 LSTM(convltm)的用武之地。在 2015 年的 NIPS 上展示,ConvLSTM 修改了 LSTM 机制的内部工作方式,使用卷积运算而不是简单的矩阵乘法。让我们为 ConvLSTM 单元写出新的方程:
∫表示卷积运算,∘表示阿达玛乘积,如前所述。
你能发现这些方程和常规 LSTM 之间的细微差别吗?我们简单地替换四个门之间的乘法运算
a)权重矩阵和输入 (Wₓ xₜ 与*、Wₓ* 、和
)b)权重矩阵和先前隐藏状态( Wₕ hₜ₋₁ 与 Wₕ 、 Hₜ₋₁ )。
否则,一切照旧。
如果你不想深究上面的方程,首先要注意的是,我们使用卷积(核)来处理我们的输入图像,以获得特征图,而不是从完全连接的层中获得的矢量。
2.2.2 n 步预测
设计帧预测模型(使用 ConvLSTM)时,最困难的事情之一是定义如何产生帧预测。我们在这里列出了两种方法(但也存在其他方法):
- 预测下一帧,并将其反馈到网络中,经过多个 n 步骤,产生 n 帧预测(自回归)
- 通过使 ConvLSTM 层的数量 l 等于 n 步的数量,一次性预测所有未来的时间步。因此,我们可以简单地使用每个解码器 LSTM 单元的输出作为我们的预测。
在本教程中,我们将重点关注数字 1,特别是因为它可以在未来产生任意数量的预测,而不必完全改变架构。此外,如果我们要预测未来的许多步骤,选项 2 在计算上变得越来越昂贵。
2.2.3 ConvLSTM 实施
对于我们的 ConvLSTM 实现,我们使用来自 ndrplz 的 PyTorch 实现
它看起来如下:
希望您可以看到前面定义的方程是如何在上面的代码中编写的。
Seq2Seq 实施
我们使用的具体架构如下:
编码器和解码器
编码器和解码器使用两个 ConvLSTM 单元(encoder_1_convlstm、encoder_2_convlstm、decoder_1_convlstm、decoder_2_convlstm)。
3D CNN
我们的最终 ConvLSTM 单元(decoder_2 convlstm)为每个预测帧(12、10、64、64、64)输出 _nf 特征图。
因为我们本质上是在做回归(预测像素值),所以我们需要将这些特征图转换成实际的预测,类似于您在经典图像分类中所做的。
为了实现这一点,我们实现了一个 3D-CNN 层。3D CNN 层执行以下操作:
- 将作为每个批次和时间步长的输入(nf、宽度、高度)
- 使用 3D 内核迭代所有 n 个预测帧
- 每个图像输出一个通道(1,宽度,高度),即预测的像素值
乙状结肠层
最后,由于我们已经将像素值转换为[0,1],我们使用 sigmoid 函数将我们的 3D CNN 激活转换为[0,1]。
基本上就是这样!
现在我们为 seq2seq 模型定义 python 实现:
3.培养
也许你已经知道 pytorch-lightning 这个优秀的库,它在使用 pytorch 时基本上把所有的锅炉板工程从机器学习中去掉了,比如下面的命令:optimizer.zero_grad()、optimizer.step()。
它还标准化了培训模块,并支持针对 Volta 架构 GPU 卡的轻松多 GPU 功能和混合精度培训。
pytorch-lightning 中有如此多的可用功能,我将尝试演示我创建的工作流,我认为它工作得相当好。
class MovingMNISTLightning
的大多数功能都是不言自明的。以下是整体工作流程:
- 我们实例化我们的类并定义所有相关的参数
- 我们采取训练步骤(针对每一批)
- 创建预测 y_hat
- 计算 MSE 损失—
- 在 tensorboard 中每 250 个全局步长保存一个带有输入和地面实况的预测可视化
- 将每批的学习率和损耗保存到 tensorboard 中
当我们实际运行我们的main.py
脚本时,我们可以定义几个相关的参数。例如,如果我们想要使用 2 个 GPU 运行,混合精度且 batch_size = 16,我们只需键入:
python main.py --n_gpus**=**2 --use_amp**=**True --batch_size**=**16
请随意尝试各种配置!
当我们运行main.py
脚本时,我们会使用多重处理自动启动 tensorboard 会话,在这里您可以迭代跟踪我们模型的性能,还可以看到我们每 250 个全局步长的预测可视化。
感谢阅读这篇文章!我希望你喜欢它!
如果您对上述论文有任何问题或评论,请联系这里或在 Twitter 上。你也可以在我的网页上找到更多的教程https://holmdk.github.io/。
用 5 行代码实现视频分割
视频的语义和实例分割
PixelLib 的第一个版本是为了使用几行代码执行图像分割而构建的。我很兴奋地宣布,新发布的 PixelLib 版本支持五行代码的视频分段。
如果你没有读过关于 PixelLib 图像分割的文章,点击这里。
安装 tensorflow,包括:
- pip3 安装张量流
安装 PixelLib 与:
- pip3 安装 pixellib —升级
视频的语义分割:
基于 pascal voc 模型的视频分割;
我们将在下面解释每一行代码。
import pixellibfrom pixellib.semantic import semantic_segmentationsegment_video = semantic_segmentation()
我们导入了用于执行语义分段的类,并创建了该类的一个实例。
segment_video.load_pascalvoc_model("deeplabv3_xception_tf_dim_ordering_tf_kernels.h5")
我们加载了在 pascal voc 数据集上训练的 xception 模型来执行语义分割,它可以从这里下载。
segment_video.process_video_pascalvoc("video_path", overlay = True, frames_per_second= 15, output_video_name="path_to_output_video")
我们调用函数对视频文件进行分割。
它采用以下参数:-
- video_path :我们要分割的视频文件的路径。
- *每秒帧数:*该参数用于设置保存的视频文件每秒帧数。在这种情况下,它被设置为 15,即保存的视频文件每秒将有 15 帧。
- *输出 _ 视频 _ 名称:保存的分段视频的名称。*输出的视频会保存在你当前的工作目录下。
sample _ video 1
输出视频
这是使用 pascal voc 模型保存的分段视频。
现场摄像机的语义分割。
我们可以使用相同的模型在相机上执行语义分割。这可以通过对用于处理视频文件的代码进行少量修改来实现。
import cv2capture = cv2.VideoCapture(0)
我们导入了 cv2 并包含了捕捉相机帧的代码。
segment_video.process_camera_pascalvoc(capture, overlay = True, frames_per_second= 15, output_video_name="output_video.mp4", show_frames= True,frame_name= "frame")
在执行分割的代码中,我们将视频的文件路径替换为捕获,即我们正在处理摄像机捕获的帧流,而不是视频文件。我们添加了额外的参数来显示相机的帧:
- *显示帧:*该参数处理分段摄像机帧的显示,按 q 退出帧的显示。
- *帧名:*这是显示的摄像机帧的名称。
展示 pixelLib 使用 pascal voc 模型对摄像机输入进行语义分割的输出的演示。
干得好!它能够成功地将我和我面前的塑料瓶分割开来。
视频实例分割:
import pixellib
from pixellib.instance import instance_segmentation segment_video = instance_segmentation()
我们导入类来执行实例分段,并创建了类的一个实例。
segment_video.load_model("mask_rcnn_coco.h5")
我们加载了在 coco 数据集上训练的 maskrcnn 模型来执行实例分割,它可以从这里下载。
segment_video.process_video("video_path", frames_per_second = 20, output_video_name = "output_video.mp4")
我们调用该函数对视频文件执行实例分割。
它采用以下参数:-
- video_path: 这是我们想要分割的视频文件的路径。
- *每秒帧数:*该参数用于设置保存的视频文件每秒帧数。在这种情况下,它被设置为 15,即保存的视频文件每秒将有 15 帧。
- *输出 _ 视频 _ 名称:这是保存的分段视频的名称。*输出的视频将保存在您当前的工作目录中。
样本 _ 视频 2
我们可以通过将参数 show_bboxes 设置为 true 来实现实例分割。
输出视频
现场摄像机的实例分割。
我们可以在摄像机的帧上执行实例分割。这可以通过对用于处理视频文件的代码进行少量修改来实现。
import cv2 capture = cv2.VideoCapture(0)
我们导入了 cv2 并包含了捕捉相机帧的代码。
segment_video.process_camera(capture, show_bboxes = True, frames_per_second = 15, output_video_name = "output_video.mp4", show_frames = True, frame_name = "frame")
在执行分段的代码中,我们替换了要捕获的视频文件路径,也就是说,我们正在处理摄像机捕获的帧流,而不是视频文件。为了显示摄像机画面,我们添加了额外的参数:
- *显示帧:*该参数处理分段摄像机帧的显示,按 q 退出帧显示
- *帧名:*这是显示的摄像机帧的名称。
一个展示 pixelLib 使用 Mask-RCNN 对摄像机输入进行实例分割的输出的演示。
干得好!它能够成功地检测到我和我的手机。
通过以下方式联系我:
推特: @AyoolaOlafenwa
脸书:阿尤拉·奥拉芬娃
Linkedin: 阿尤拉·奥拉芬娃
使用 OpenCV & Flask 在 Web 浏览器中进行视频流传输
借助计算机视觉,从 IP 摄像机或网络摄像头传输实时视频
罗布·萨米恩托在 Unsplash 上的照片
你不厌其烦地在家里、办公室或任何你拥有的地方安装网络摄像头或监控摄像机。显然,你希望能够随时随地观看视频直播。
大多数人使用 IP 摄像机 (网络摄像机)而不是 CCTV (闭路电视)进行监控,因为它们的分辨率更高,布线成本更低。你可以在这里找到这两个系统的详细区别。在本文中,我们将重点关注 IP 摄像机。
IP 摄像机是一种数字视频摄像机,它通过 IP 网络接收控制数据并发送图像数据,不需要本地记录设备。大多数 IP 摄像机都是基于【RTSP】(实时流协议)的,因此在互联网浏览器中“不支持”。****
图片由《RTSP 议定书》作者提供
那么,你如何使用网络浏览器观看直播呢?
在这篇文章中,我们将学习如何使用 计算机视觉 来做到这一点。
计算机视觉是一个跨学科领域,研究如何让计算机从数字图像或视频中获得高层次的理解。
为了实现计算机视觉部分,我们将使用 Python 中的 OpenCV 模块,为了在网络浏览器中显示实时流,我们将使用 Flask 网络框架。在进入编码部分之前,让我们先简单了解一下这些模块。如果你已经熟悉这些模块,你可以直接跳到下一节。
根据维基百科,Flask 是一个用 Python 编写的微型 web 框架。它被归类为微框架,因为它不需要特殊的工具或库。它没有数据库抽象层、表单验证或任何其他组件,而现有的第三方库提供了通用功能。
根据 GeeksForGeeks 的说法,OpenCV 是用于计算机视觉、机器学习和图像处理的巨大开源库,现在它在实时操作中发挥着重要作用,这在当今的系统中非常重要。
步骤 1-安装烧瓶& OpenCV :
您可以使用’ pip install flask '和’pip install opencv-python命令。我使用 PyCharm IDE 开发 flask 应用程序。 要在 PyCharm 中轻松安装库,请遵循以下步骤。
步骤 2- 导入必要的库,初始化 flask app :
我们现在将导入必要的库并初始化我们的 flask 应用程序。
****#Import necessary libraries**
from flask import Flask, render_template, Response
import cv2
**#Initialize the Flask app**
app = Flask(__name__)**
第 3 步-使用 OpenCV 捕获视频:
创建一个 VideoCapture()对象来触发摄像机并读取视频的第一个图像/帧。我们既可以提供视频文件的路径,也可以使用数字来指定使用本地网络摄像头。为了触发网络摄像头,我们传递“0”作为参数。为了捕捉来自 IP 摄像机的实时反馈,我们提供了 RTSP 链接作为参数。要知道你的 IP 摄像机的 RTSP 地址,请浏览这个— 查找 RTSP 地址 。
**camera = cv2.VideoCapture(0)'''
for ip camera use - rtsp://username:password@ip_address:554/user=username_password='password'_channel=channel_number_stream=0.sdp' for local webcam use cv2.VideoCapture(0)
'''**
步骤 4-添加窗口并从相机生成帧:
按作者分类的图像-帧生成功能
gen_frames()函数进入一个循环,在这个循环中,它不断地从摄像机返回帧作为响应块。该函数要求摄像机提供一个帧,然后它将这个帧格式化为一个内容类型为image/jpeg
的响应块,如上所示。代码如下所示:
帧生成函数
第五步-定义网络应用默认页面的应用路径:
路由是指某个 app 的 URL 模式(如 myapp.com/home 或 myapp.com/about)。@app.route("/")
是 Flask 提供的一个 Python 装饰器,用于轻松地将我们应用程序中的 URL 分配给函数。
**@app.route('/')
def index():return render_template('index.html')**
装饰器告诉我们的@app
,每当用户在给定的.route()
访问我们的应用程序域( localhost:5000 用于本地服务器),执行index()
函数。Flask 使用 Jinja 模板库来渲染模板。在我们的应用程序中,我们将使用模板来呈现将在浏览器中显示的 HTML。
步骤 6-定义视频馈送的应用程序路由:
**@app.route('/video_feed')
def video_feed():
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')**
“/video_feed”路由返回流响应。因为这个流返回要在网页中显示的图像,所以这个路由的 URL 在图像标记的“src”属性中(参见下面的“index.html”)。浏览器将通过在其中显示 JPEG 图像流来自动保持图像元素的更新,因为大多数/所有浏览器都支持多部分响应
让我们看看我们的index.html文件:
**<body>
<div class="container">
<div class="row">
<div class="col-lg-8 offset-lg-2">
<h3 class="mt-5">Live Streaming</h3>
**<img src="{{ url_for('video_feed') }}" width="100%">**
</div>
</div>
</div>
</body>**
步骤 7-启动 Flask 服务器:
**if __name__ == "__main__":
app.run(debug=True)**
app.run()被调用,web 应用程序被本地托管在【localhost:5000】上。**
“debug=True”确保我们不需要在每次进行更改时都运行我们的应用程序,我们只需在服务器仍在运行时刷新我们的网页来查看更改。
项目结构:
按作者分类的图像-项目结构
该项目保存在一个名为“相机检测”的文件夹中。我们运行“app.py”文件。在运行这个文件时,我们的应用程序被托管在端口 5000 的本地服务器上。
运行“app.py”后,您只需在 web 浏览器上键入“localhost:5000”即可打开您的 web 应用程序
- app.py —这是我们在上面创建的 Flask 应用程序
- 模板—该文件夹包含我们的“index.html”文件。渲染模板时,这在 Flask 中是强制的。所有 HTML 文件都放在这个文件夹下。
让我们看看运行“app.py”时会发生什么:
作者图片 Flask 应用程序的本地服务器
点击提供的 URL,我们的网络浏览器会打开实时提要。由于我使用了上面的 VideoCapture(0) ,网络摄像头的视频显示在浏览器上:
图片由作者提供-本地网络摄像头在网络浏览器上提供
就是这样!!
您的网络浏览器上有来自 IP 摄像头/网络摄像头的实时视频流,可用于安全和监控目的。
如果你喜欢读这篇文章,请支持我。点击上图。谢谢你****
参考我的 GitHub 代码 。
注意 :本文中已经提到了开始工作所需的所有资源及其链接。希望你好好利用:)
我希望这篇文章能让你对尝试计算机视觉领域的新事物感兴趣,并帮助你增加知识。如果你喜欢读这篇文章,请与你的朋友和家人分享。谢谢你的时间。
越南零售景观:零售足迹分析(上)
在一个过去 5 年以+10%的速度增长但被实体渠道主导的零售市场中,“下一家店开在哪里”是决定一个品牌成败的问题。
这篇博文是我在 IBM-Coursera 应用数据科学峰会上的工作的一部分。
1.介绍
2013 年至 2020 年间,越南零售业快速增长了+10%。作为东南亚中产阶级增长最快的国家,其零售业的这一惊人增长率预计至少在未来五年内将持续下去。德勤越南公司在其关于越南零售业 2019 的报告中报告了以下关键统计数据:
德勤对越南零售业的主要统计数据
根据这份报告,尽管越南的零售业拥有巨大的增长潜力,但竞争程度非常激烈。通过不同的商店形式:商业中心、超市、杂货店和便利店,越南的国内外零售巨头正在进行一场争夺主导权的战争,因为他们开始了积极的扩张战略。与此同时,尽管数字渠道兴起,但实体渠道继续主导零售领域。
因此,一个有趣的问题是:( 1)这些零售巨头目前在越南的零售足迹如何,( 2)新店的下一个目标应该是哪个省/市/区。谁有兴趣回答这些问题?答案是越南的零售巨头,以及任何计划进入越南零售市场的新玩家。
- 对于越南的零售巨头来说,回答这个问题将为他们决定在哪里扩大商店网络提供关键信息,也许他们当前的商店应该关闭(由于同一地区的竞争商店的数量)。用数据驱动的方法做出这些决定将使这些公司在市场中找到自己的最佳位置,并抓住新的需求。
- 对于计划进入越南零售市场的新玩家来说,通过了解当前在越南的零售足迹,可以了解他们的市场进入策略。
2.数据
2.1。数据来源**
为了进行分析,获得了以下数据来执行分析:
- 越南行政区划列表:省级和区级。该信息来自越南统计总局(GSO)数据库(于 2020 年 4 月 4 日在 GSO 数据库检索)
- 人口普查数据:包括各省的人口、面积、人口密度、人类发展指数、GDP/资本等数据(2020 年 04 月 04 日检索自维基百科)。这一数据由 2019 年 4 月 1 日的 GSO 人口普查报告提供。然而,由于这些数据无法通过 GSO 数据库获得,维基百科是下一个最好的选择。
- 地理空间坐标:是包含来自 OpenDevelopmentMekong 数据库(2020 年 4 月 5 日检索)的越南各省和行政区地理空间数据的多边形数据集。这些数据集(JSON 格式)为项目结果在越南地图上的可视化提供了输入。
- 主要零售连锁店的店铺列表:根据德勤关于越南零售 2019 的报告,确定了以下零售连锁店,其店铺列表通过网络抓取从其官方网站获得。web 抓取的结果是商店列表,其中包含(1)商店名称,(2)商店地址,以及(3)商店的纬度和经度。
- 夫妻店和小型零售店:除了主要零售连锁店的商店,夫妻店仍然是越南零售市场的重要组成部分之一。夫妻店是家庭经营的杂货店。小型零售店由小公司经营,倾向于针对特定客户群的需求(例如,高端进口糖果、葡萄酒和酒类商店等)。).这类商店的数据是通过 Foursquare API 获得的。
关于主要的零售连锁店,以下超市、便利店(CVS)和食品杂货连锁店,这些都是德勤关于越南零售业前景的报告中所报告的,包括在本分析中:
- Vingroup: VinMart —连锁超市,以及 VinMart+ —不同业态的 CVS,从混合型(即生鲜产品 CVS)到传统 CVS。
- 西贡超市: Co.Op Mart 超市、 Co.Op Smile — CVS、 Co.Op Food —生鲜店
- Satra: SatraMart —超市
- 杂货店
- 7-Eleven : CVS(仅在胡志明市)
- 永旺集团: MiniStop — CVS(仅在胡志明市和平阳省)
- BigC :连锁超市
- 圈 K : CVS
- B’mart : CVS
注:Shop & Go 和欧尚连锁店包含在德勤报告中,然而:
因此,假设在收购后,这些商店将被重新命名并纳入收购方商店链,因此它们不包括在分析中。
2.2。数据清理和探索*和*
在此分析的所有数据中,行政区划和人口普查数据是结构化的,不需要进一步的数据清理和格式化。相比之下,从主要零售商的网站上搜集的商店数据没有结构化,存在语法错误、重复记录和质量差。对于此商店列表,在数据准备好进行进一步分析之前,采取了以下步骤:
- 从数据中移除越南语重音符号,以便稍后分类
- 检查每个商店的地址、纬度和经度,以确保一致性和数据质量
- 删除重复记录
使用叶库,以下越南地图是使用上述数据构建的,以反映商店的分布情况:
从左至右:(1)越南各省地图,包括主要零售连锁店的所有超市(蓝点)和便利店(绿点)。(2)右上图为越南北部地区概况(以河内市为中心)。(3)右下方的地图展示了越南南部的概况(以胡志明市为中心)
进行解释性数据分析(EDA)是为了进一步了解数据集并为聚类模型选择数据特征。
3.分析
3.1。方法论
对于这个项目,K-Means 聚类方法将用于根据零售足迹和统计普查来描述各省/地区。从到数据科学,K-Means 聚类是一种无监督的机器学习算法,试图在没有首先用标记数据训练的情况下对数据进行分类。由于本项目的目的是了解越南不同行政区划的零售足迹,因此选择了这种方法。
为了确定此分析中的最佳聚类数,我们将评估聚类数之间的关系以及聚类平方和(WCSS)内的关系,以选择 WCSS 变化开始趋于平稳的聚类数(肘形法)。
3.2。k 均值聚类
从第 2 节中进行的 EDA 中,我选择与其他变量具有低相关性(-0.5,0.5)的变量作为聚类模型的输入。选取了以下变量:人口密度、城市化水平、人类发展指数(HDI)、人均收入、位于各省的各类商店数量(超市、CVS 等。).使用肘方法,三个是此分析的最佳聚类数:
使用三作为聚类的数目,我获得了如下三个聚类:
- 集群#1 —“成熟”市场:包括河内和胡志明市—越南最大的两个城市,拥有最多的商店数量(各+1000 家商店),在人口密度、城市化和人均收入方面名列前茅。
- 集群#2 —“新兴”市场:包括 14 个城市/省份,可视为集群#1 的下一级城市/省份
- 集群#0 —“发展中”市场:包括其他省份。
下文概述了分组过程中使用的输入变量的三个分组。
4.结果和讨论
聚类分析:人均 GDP(百万越南盾)和人口密度(人/平方公里)。气泡大小表示每个省的商店数量。颜色代表聚类结果。
在该图中,我们可以看到三个聚类之间的分离:聚类#0 —蓝色,聚类#1 —棕色,聚类#2 —紫色。在聚类#2 中,我们可以确定人口密度和人均收入较高的省份,但与同一个聚类中的其他省份相比,这些省份的商店数量较少。
分析中最有趣的聚类是聚类 2,其中多个城市/省份具有相似的状态(面积、人口、密度等。)但是有非常不同数量的零售商店。回顾归类为群组 2 的省份清单,可以得出一些有趣的观察结果,例如:
- 北宁市:在人均收入和人口密度方面与海防市非常相似,但是商店的数量要少 50%。尽管北宁市的人口和城市化水平比海防市低约 30%,但两省之间人均收入高出约 50%,这应该为进一步扩大店铺提供了巨大的潜力。
- Can Tho:在其他属性方面与岘港非常相似,但商店数量只有岘港的 50%。尽管同城的城市化和人类发展指数分别比岘港低约 30%和 10%,但商店仍有进一步扩张的潜力,因为这两个省份之间的人均收入和人口密度差距仍低于 10%。
有了这个结果,现在的问题是“那又怎样?这些信息能对任何人有什么帮助?”。如本文开头所述,这项分析最初是针对主要的零售连锁店,或任何有兴趣进入越南市场的公司。进行与本分析类似的聚类分析,并确定与本分析中的聚类 2 类似的聚类,可以帮助这些公司找到潜在市场,在这些市场中,需求和增长没有被完全捕获。
5.未来方向
当然,这种分析是极其简单和幼稚的,没有考虑到各省零售市场的几个不同因素。此分析中的以下一些限制是我进一步扩展此分析并获得更多见解的大好机会:
- 夫妻店数据:与超市和现有零售连锁店的商店不同,夫妻店数据很难使用 Foursquare API 完成。Google API 可能是一个更好的选择,但是,即使使用 Google,获得的数据仍然不能反映该类别商店的实际分布情况。
- 普查数据:这种分析使用的普查数据没有反映每个省的增长潜力(即人口增长、人均收入变化等)。).拥有每个省的历史发展的进一步数据可以通过更复杂的聚类获得进一步的洞察力。
- 区一级的分组:目前的分析是在省一级进行的。像河内或胡志明这样的城市,商店的数量很大(+1000 家商店/每个城市),意味着更高的密度。在区一级的进一步详细聚类分析可以提供关于这两个特殊城市的景观和足迹的更有趣的见解。
使用此链接可以访问此分析的更多详细信息和交互式地图: myGithub
当然,请随时分享您对这一分析的宝贵意见。我很乐意看到你对这个项目及其结果的想法和意见。
越南零售景观:零售足迹分析(下)
一个品牌的门店足迹有多好?如何识别商场足迹中的差距?商店占地面积的所有缺口都需要填补吗?
这篇博客文章是我在 IBM-Coursera 应用数据科学峰会上的后续工作。你可以查看第一部分以了解越南零售市场的概况、最初的问题陈述以及我的分析中使用的数据来源。
在上一部分中,我回顾了主要零售品牌在越南全国的商店足迹,并使用聚类技术找到了应该被视为具有吸引力的扩张市场的省份。正如我之前研究的数据一样,大多数商店位于河内和胡志明市(HCMC)也就不足为奇了——这是越南最大的市场。因此,在第二部分,我想深入了解这两个城市中每个品牌的商店网络。
对于这篇文章,我将主要讨论我对 HCMC 的研究结果,因为两个主要原因:(1) HCM 是更大的市场(考虑到两个城市之间的人口、人口密度和人均收入);(2)河内市场由 Vinmart 商店主导,没有多少品牌可以与 Vinmart 竞争(在河内的零售商店中,不包括夫妻店,Vinmart 商店占 77%),而 HCMC 的情况正好相反。
方法
当深入研究 HCMC 的商店网络和位置时,我遵循了三个步骤:
- 商场占地面积:将商场分配分解到区级,并根据区级的人口密度审查商场密度
- 地理覆盖范围:比较不同品牌的店铺网络的地理覆盖范围,找出覆盖范围最好的店铺网络。对于此分析,覆盖范围定义为网络中每个商店给定距离内所有点的集合。这意味着顾客可以在给定的距离内进入零售店的区域。
- **下一步何去何从:**确定城市中品牌应考虑开店的区域/位置,以增加其在城市中的覆盖面。
调查的结果
1。商店占地面积
为了探索这个方面,我研究了商店相对于同一网络中的其他商店以及城市中的人口密度的位置。例如:对于 Vinmart(超市和便利店网络),我探索了如下不同的可视化:
从左至右:(1)店铺位置;(2)商店集群;以及(3)使用 HCMC 人口密度(人/平方公里,2019 年数据)choropleth 地图,HCMC VinMart 商店(包括超市和便利店)的商店覆盖范围(2020 年 6 月 30 日获得的商店数据)。
从左至右,地图显示 HCMC 人口密度(人口/平方公里,在地区一级,较深的颜色代表较高的密度)和:
要查看上述地图的互动版本,请使用每张地图描述中包含的链接。
看看 HCMC 店铺数量最多的两个品牌的店铺集群——VinMart和 BachHoaXanh (BHX),我们可以看到一个显著的区别:虽然 VinMart 店铺密集地位于市中心(80%的店铺),但 BHX 店铺更分散,不太集中在最密集的区域(3 区、5 区、10 区和 11 区)。这种差异可能反映了关于其目标客户的品牌战略。
从左至右:( 1) VinMart 和(2)BHX(2020 年 6 月 30 日获得的商店数据)的商店集群地图,以及 HCMC 人口密度(人口/平方公里,2019 年数据)choropleth 地图。
2。地理覆盖范围
为了比较不同品牌商店网络的地理覆盖范围,我使用了 geopandas 中的 buffer 函数来获取同一网络中每个商店的给定距离内所有点的集合。
例如,上面的两张地图显示了从 Vinmart 和 BHX 的每家商店 500 米范围内所有点的集合,这两家商店是 HCMC 商店数量最多的商店网络。难怪 Vinmart 商店大多位于人口密度较高的城市中心,基本上覆盖了中心区域。另一方面,尽管假定人口密度很高,但 BHX 的商店网络使得市中心相当大一部分区域没有商店。
从左至右:(1) VinMart 和(2) BHX 商店网络(2020 年 6 月 30 日获得的商店数据)与 HCMC 人口密度(人/平方公里,2019 年数据)choropleth 地图 500 米距离的商店覆盖范围。
为了进一步比较覆盖范围,我查看了 HCMC 不同品牌的每家商店在给定距离内(100 米到 1 公里之间)的面积百分比。交集和。geopandas 的面积函数。
不同距离(以米为单位)的地理覆盖范围(占 HCMC 总面积的百分比)衡量领先零售品牌在越南的表现
因此,该折线图显示了 HCMC 距离 HCMC 的 VinMart、BHX、CircleK、CoOp(包括 Coopfood 和 Coopsmile)、Satra 和其他零售品牌 100 米至 1 公里范围内的商店网络所占的百分比。
按照预期,商店数量越多,观察到的覆盖范围就越大。然而,唯一的例外是,BHX 在 600 米左右或更远的距离的覆盖范围方面超过了文马特,尽管 BHX 的商店比文马特少 20%。这可以用以下事实来解释:80%的 VinMart 商店位于市中心地区,而 BHX 的这一数字仅为 68%。因此,随着缓冲距离的增加,与 BHX 相比,VinMart 商店网络的覆盖范围增长速度较慢。
3。接下来去哪里?
对于领先的零售品牌 :利用缓冲和覆盖分析,公司可以识别其商店网络中的地理差距,并解决差距,以进一步加强其商店网络。
例如,下图显示了 BHX 商店网络的地理差距。如果 BHX 希望通过增加 500 米的覆盖范围来加强网络,该公司可以考虑在下图中突出显示的一些区域进一步开店。
左图:BHX 商店网络 500 米范围内的商店覆盖范围。右图:BHX 商店网络中的地理差距示例
商店占地面积中的所有缺口都需要填补吗?这取决于公司的战略和市场目标。
- 如果一个品牌的目标是让城市中的所有顾客都能在 10-15 分钟的步行距离内到达其商店,也许是的。
- 如果一个品牌的目标是在市场上有效竞争,它应该缩小位于高人口密度地区的差距,或者换句话说,位于更有潜力的细分市场。
- 如果一个品牌的目标是扩大其商店网络,同时支持其供应链网络,则应考虑进一步的标准。
对于较小的零售品牌或新进入者 :他们可以使用相同的技术来寻找其直接竞争对手的商店足迹的差距,或在市场上主要品牌的整体商店足迹中寻找机会。
从左至右:(1)商店集群,以及(2)主要品牌商店足迹 500 米距离内的商店覆盖范围,以及 HCMC 人口密度(人/平方公里,2019 年数据)choropleth 地图。
请随时分享您对此分析的宝贵意见。我很乐意看到你对这个分析和发现的想法和意见。
维拉:一种通用的视觉和语言对抗训练技术
第一个用于图像和文本模型的多模态对抗训练技术
图片由来自 Pixabay 的 Gerd Altmann 提供
为视觉和语言多模态学习建立大规模预训练模型是近年来机器学习研究的一个热点。像 UNITER 、ViLBERT 和 LXMERT 这样的模型在数百万个具有不同目标函数的图像-文本对上进行训练,并且能够学习图像和文本的有效通用联合表示。
然后,这些表示在特定任务上进行微调,以在无数图像和语言任务上实现最先进的性能,如图像 QA、图像-文本检索、图像基础、图像推理等。在对特定任务进行微调时,可用的数据量只是所用预训练数据的一小部分。如此少量的数据通常会导致模型过度拟合,并打破了试图为图像和文本建立一个通用嵌入的目标。
那么我们如何防止这种过度拟合呢?针对图像和文本的单一模态任务的对抗性训练技术已被证明可以使模型更加健壮和可推广。这种培训可以通过以下方式进行
- 创造人类可以理解的对立例子(如 Szegedy 等人)
- 给嵌入空间增加对抗性扰动(如 FreeLB )。
将对抗性训练技术应用于多模态学习是对单模态技术的自然扩展,这正是微软动态 AI 365 研究的研究人员所做的。
他们提出了 VILLA(视觉和语言大规模对抗性训练),这是第一个已知的针对视觉和语言设计的对抗性训练技术。VILLA 遵循第二种对抗性训练方法,因为他们的目标是建立一个健壮的模型,而不管人类是否理解对抗性的例子。对于文本模态,他们增加了对单词嵌入的对抗性干扰。先前关于图像对抗训练的工作向图像像素添加噪声,并且发现鲁棒性是以性能为代价的。在 VILLA 中,这些对立的扰动被添加到所提取的图像区域特征而不是像素,这提高了鲁棒性和性能。在训练期间,扰动一次仅添加到一个模态,而另一个模态保持不变,如图所示。
维拉还利用“免费”训练策略(沙法希等人,2019;Zhang et al. 2019)在计算输入的梯度时,几乎没有额外的成本就获得了参数的梯度。通过这种方式,模型可以在不增加成本的情况下看到更多的示例,并且培训变得更具成本效益。
对抗性训练技术通常确保对抗性示例的标签与原始示例的标签相同。VILLA 不仅试图做到这一点,还试图使用 KL-divergence 来匹配两个例子的预测类别概率。通过这样做,训练损失函数变得更平滑,并且模型可以更好地估计它。这进一步提高了模型的性能。
VILLA 可以应用于预训练和微调阶段,以提高学习嵌入的泛化能力。当应用于 UNITER-large 时,VILLA 进一步提高了其性能,在 VQA 上从 74.02%提高到 74.87%,在 VCR 上从 62.8%提高到 65.7%。集成后,VQA 性能进一步提高到 75.85%。维拉还在另外 4 项任务上将尤尼特的成绩提高到了最高水平。
VILLA 也是模型不可知的。它被应用于另一个大规模预训练模型 LXMERT,并在 VQA 上显示出性能的提高。
如果你想更详细地了解维拉是如何工作的,这里有一个链接到论文,点击这里看更多他们的出版物和其他工作。
参考文献
- 日元-陈春、李林杰、李成玉、艾哈迈德·埃尔·科利、费萨尔·艾哈迈德、哲甘、于成、刘晶晶、统一者:学习通用的图像-文本表示法、欧洲计算机视觉会议(ECCV) 2020
- J iasen Lu , Dhruv Batra , Devi Parikh , Stefan Lee , ViLBERT:预训练任务不可知的视觉-语言任务的视觉-语言表征,arXiv 预印本,arXiv:1908.02265
- 郝坦和莫希特·班萨尔, Lxmert:从变形金刚学习跨通道编码器表示,EMNLP 2019。
- C 赫里斯蒂安·塞格迪,沃伊切赫·扎伦巴,伊利亚·苏茨克弗,琼·布鲁纳,杜米特鲁尔汉,伊恩·古德费勒,罗布·弗格斯,神经网络的耐人寻味的性质 (2013),arXiv 预印本,arXiv:1312。
- 、于成、哲干、孙思齐、汤姆·戈尔茨坦、刘晶晶、 FreeLB:语言理解的强化对抗训练 (2019),学习表征国际会议,ICLR 2020
- A.沙法希,m .纳吉比,a .吉亚西,z .徐,j .迪克森,c .斯图德,l .戴维斯,g .泰勒,t .戈尔茨坦,对抗性训练免费!、神经信息处理系统、NeurIPS 2019
- 张定淮,张天元,陆,朱占兴,董斌,你只传播一次:最大原理无痛对抗训练,神经信息处理系统,NeurIPS 2019
- 哲淦,晏,李林杰,诸宸,于成,刘晶晶,视觉-语言表征学习的大规模对抗性训练,arXiv 预印本,arXiv:2006.06195。
“Vim —无处不在的文本编辑器”
Vim 很牛逼
McDobbie Hu 在 Unsplash 上的照片
第一次遇到 Vim 时,我被通过命令行编辑文本的完全不同的方式所征服,以至于我没有再回头看它。
但是耐心地试验过之后,我就迷上了。Vim 有一些很棒的高级特性,我已经读到过,但还没有探索过。这篇文章是为了说服你并让你开始使用 Vim。我们将讨论基本命令,然后研究如何为 Vim 启用语法高亮显示。
vim(VIIMproven)是 Bill Joy 的 vi 文本编辑器程序在 Unix 和苹果 OS X 上的克隆版,可以在这里下载。
为什么使用 Vim?
当使用 bash 终端时,Vim 是必不可少的。例如,您可以直接使用命令行界面编辑像.bash_profile
这样的文件。这是一项伟大的技能。作为一个高度可定制的文本编辑器,它可以被任何人使用——软件开发人员、数据分析师、数据科学家。这是一个免费的强大的工具,你不能把它扔出窗外。作为一个控制台编辑器,它与 shell 密切配合。这是熟悉 shell 的第一步,之后你就可以做程序员需要做的几乎所有事情了。
基本命令:
要在 Vim 中打开一个文件,在终端中键入vi <name-of-the-file>
。我将使用一个空的bash
脚本,script1.sh
作为例子。
vi script1.sh
:打开文件。
空文件- 0 行和 0 个字符
如果您尝试键入任何内容,将不会显示任何内容,因为它处于NORMAL
模式。要编辑文件,按键盘上的i
。这是进行编辑的INSERT
模式。
注意窗口底部黄色的INSERT
。
一旦你对这些变化感到满意,你就必须脱离INSERT
模式。要在不同模式之间切换,我们使用ESC
键。
保存:按下ESC
和:w
。
还可以看到写的行数和字符数。
保存后退出::q
这两个命令可以组合为::wq
不保存就退出::q!
记得按ESC
来切换模式!
语法突出显示:
永久地(因为,当然,我们不希望它是一次性的!)添加语法高亮,我们编辑.vimrc
文件(隐藏文件)。
*.vimrc*
代表 Vim 运行时配置。当编辑器打开时,它保存编辑器的默认设置,允许用户自定义编辑器的选项。
为了在 Vim: vi ~/.vimrc
中打开.vimrc
文件,这个文件驻留在您的主目录中,为了避免更改目录,我们添加了一个~
(这是主目录的快捷方式)。
编辑文件:按i
并添加syntax on
。
ESC
和:w
保存。
当您保存时,您将在文件中看到语法高亮显示。
:q
退出。
要获得可用配色方案的列表:
ls -l /usr/share/vim/vim*/colors/
这在你的根目录中,如果你想找到它,不要着急。/usr
是一个隐藏的文件夹,按下command
+ shift
+ .
就可以看到
现在,要对这些配色方案进行采样并选择您最喜欢的方案,请在 vim 中打开一个文件。
类型::colorscheme <name-of-colorscheme-to-test-out>
按下ENTER
。
(诶,不喜欢)
不断尝试不同的方案,直到你选定了你最喜欢的方案!
请注意,通过 Vim 更改的配色方案仅适用于当前 Vim 会话,不会被保存。要永久使用特定的配色方案,我们必须将其添加到.vimrc
:
colorscheme <name-of-colorscheme>
如果您想禁用配色方案,则按照上述相同的步骤编辑您的.vimrc
文件,并将syntax on
更改为syntax off
。
自从我掌握了这个窍门,我就喜欢使用 shells 和 Vim。希望你也是!
蒂华纳市的暴力和当地商业
在这项工作中,使用 Foursquare API 识别了提华纳的暴力街区,并找到了它们最常见的场所
专业证书期末项目 IBM 数据科学
该报告的 pdf 版本在 my Github 中
1 简介1.1 背景
T 伊瓜纳是墨西哥最大、发展最快的城市之一,2014 年有 340 万人口[1],是美墨边境上最大的墨西哥城市。“这个城市是下加利福尼亚州大约 49 %人口的家园,而只占该州领土的大约 2%”[10]。蒂华纳每天接纳来自墨西哥其他地方的移民,增加近 96 名新居民。
蒂华纳是北美的医疗设备制造之都,一项研究估计,该地区约占该地区所有视听产品制造的 40%[34]。但是工作的丰富并不意味着生活质量的提高。根据国家社会发展政策评估委员会(CONEVAL,在西班牙语中是他的名字)2018 年的一项最新研究,近 70 %的人口生活在贫困状态中[9],有很多工作岗位,但工资很低,社会流动条件很差。
鉴于该城市的地理位置,在过去几十年中,与贩毒和有组织犯罪集团有关的暴力事件有所增加[11]。这个城市也有很高的药物使用水平,这是由它靠近美国造成的,但仍然没有对真正问题的分析甚至数据[27]。毒品暴力继续在蒂华纳占据主导地位,2017 年的凶杀案比墨西哥其他任何城市都多,这是全国凶杀案数字创纪录的一年,2017 年,墨西哥 20 起谋杀案中有 1 起发生在蒂华纳。政府没有对该市的暴力事件进行简明的分析。这项工作是我希望成为简明分析的开始,从关注暴力对当地商业的影响开始。
1.2 个人动机
我在蒂华纳长大,在那里生活了 18 年。自从我有记忆以来,暴力一直是这座城市的一部分,生活在暴力最严重的街区之一(“Sanchez Taboada”)帮助我从年轻时就意识到了这一点。从我的个人经验来看,过一段时间你习惯了,暴力就变得正常了,是意料之中的,害怕被抢劫、被枪击,或者,对于女人来说,害怕被强奸,这种事情并不总是在你的脑海中出现,但它总是在你的背后,在袖手旁观。晚上在街上意味着危险,如果你听到你家附近有枪响,你不会报警,因为有时警察比罪犯更危险。在墨西哥其他城市的街道上行走的恐惧是我生活中的一个常数,我已经习惯了,我可以继续我的生活,但每次我去蒂华纳看望我的父母,我都很害怕,每次我回来,恐惧都成倍增长,就像暴力和贫困一样。举个例子,一年前,出租车和像优步这样的应用程序服务开始拒绝在晚上 7 点后去我的旧社区,因为害怕被抢劫或被杀。
我不想害怕我成长的城市,害怕墨西哥,我越来越需要了解影响它的问题。也许,如果我理解了这个城市的错综复杂,我的恐惧会开始成为一种燃料,以一种小的方式提供帮助,并最终提供做出真正改变的工具。那么,暴力事件上升的原因是什么?为什么我长大的地方是这个城市里比较暴力的地方之一?也许生活贫困是暴力的原因,或者是缺乏良好的司法系统,还是卡特尔的错?或者是我们社会基础中一个更深层次的问题?。这些问题必须由城市和政府的负责人来回答。但是在我过去几个月所做的研究中,我没有发现墨西哥政府
对提华纳暴力原因的明确调查。我发现的唯一明确的调查是“为墨西哥伸张正义”(Justice for Mexico),这是一个总部位于美国的项目,有一些有趣的分析,但还有很大的发展空间。墨西哥政府的答案总是一样的,需要把“坏人”关进监狱,暴力就会消失,但这几十年来没有奏效,而且永远不会奏效[18,8]。
图 1:蒂华纳 Camino Verde 社区的国民警卫队[36],这是新政府在过去一年里对暴力和移民危机增加的回应。许多人认为这是该国军事化的第一意图。图片来自【36】。
1.3 问题
这个项目的大背景是分析蒂华纳的可用数据,犯罪、教育、移民和经济搜索暴力背后的故事;相关性在哪里?为什么某些街区的暴力事件会增加?这是一个雄心勃勃的项目,我知道这一点,我仍在学习数据科学,这种类型的分析对我来说是新的,但背后有这么多个人动机,我可以学得更快,同时找到有趣的结果。这个项目将被分成几个必要的部分,第一部分,我将在 Coursera“IBM 数据科学”专业的期末项目中展示,是关于提华纳暴力最严重的社区中暴力和当地商业之间的关系。问题是,在提华纳市暴力程度较高的社区,有哪些共同之处?
1.4 目标受众
什么类型的客户或人群会对这个项目感兴趣?
- 想要在暴力社区投资的企业家可以识别社区中缺失的商业类型。
- 负责该社区的当局可以看到机会之窗,帮助更常见类型的企业繁荣发展,提供信贷或管理指导。
- 居民可以更好地理解他们社区的数据
2 数据采集和清理
本节使用的程序是在我的 Github 下面 这个链接
2.1 犯罪
关于蒂华纳在线的数据很少,但由于几年前政府的新政策,更多的数据变得可用。在犯罪案件中,我只能在一个地方找到可用信息,即国家安全和国家调查卫队的官方网站(Guardia Estatal de Seguridad e investigación),但这一信息非常不完整。让我们开始回顾数据集,引用
网站的话,“本节包含的数据库仅细分了被认为具有高度和中度影响的犯罪选择,这些犯罪威胁到人们的生命和完整性以及他们的遗产”,因此数据是不完整的,无法找到更完整的数据集。我尽了最大努力将犯罪数据从西班牙语翻译成英语,但在法律术语中,每项犯罪的定义可能会有一些差异。这些罪行的分类如下:
- 暴力和非暴力车辆盗窃
- 暴力和非暴力入室盗窃
- 暴力和非暴力的商业盗窃
- 在公路上暴力抢劫
- 公共场所的简单抢劫
- 其他没有暴力的抢劫
- 其他暴力抢劫
- 恶意伤人
- 非法伤害
- 凶杀(暴力)
- 绑架
正如你所看到的,分类遗漏了一些非常重要的犯罪,如敲诈勒索、杀害女性和性侵犯,这些在蒂华纳非常常见的犯罪[13,30,23]。出于某种原因,国家检察官不认为强奸属于“被认为具有威胁人的生命和完整性的高度和中度影响的犯罪”的类别。现在,为了理解数据库中包含的字段,需要做一些解释。首先,墨西哥各州划分为市,而不是像美国那样划分为县。蒂华纳是下加利福尼亚州的一个直辖市。蒂华纳市分为行政区或“代表区”。行政区又被划分为“殖民地”,对“殖民地”的最佳翻译是邻居。我将把我的分析集中在“Colonias”上,所以我将使用那个翻译。
- 犯罪:指已登记的犯罪
- 犯罪分类:指上面引用的犯罪分类。
- 犯罪地附近:指犯罪地附近。
- 犯罪记录日期:犯罪报告开始的日期。该日期用于根据月、日和年进行统计计数。
- 犯罪日期:犯罪发生的日期(有时与犯罪登记的日期不同),因为犯罪可能在某一天报案,而在另一天实施。
- 犯罪时间:犯罪发生的时间。
- 自治市:犯罪登记的自治市。
这些数据的来源是州检察长,并由州情报中心统计协调处处理。
2.2 当地企业
鉴于某些社区的犯罪信息,我想探索这些社区的当地企业。我使用 Foursquare API 来获取一个给定街区的场地,但要做到这一点,我需要坐标。这比预期的要困难。我的第一个想法是使用城市的 12 个区(“Delegaciones”)并根据每个区的犯罪情况进行分析。这个想法给我带来的最大问题是,我找不到每个地区的社区列表。在蒂华纳都市规划研究所(IMPLAN)的官方网站上有一个交互式地图,您可以在其中选择区域,区域会出现在地图上[17],但是在蒂华纳有 3000 多个社区,并且用这种方式寻找每个社区的每个社区太复杂了;令人惊讶的是,在蒂华纳政府的任何官方网站上,我都找不到更多关于该地区的信息。我能做的下一个最好的分析是集中在更暴力的社区。
现在,理解什么类型的本地企业是被期待的也是棘手的。例如,近年来所谓的医疗旅游浪潮如此之大,以至于该市在 2018 年接待了约 120 万名来自美国寻求健康治疗的患者。“咨询、程序、药物和手术的低成本——价格比美国低 30 %至 70%——使这座城市成为一个伟大的健康中心”[3]。
因此,预计会有许多药房,但也有许多非正规商业,据估计,蒂华纳超过 30%的企业是非正规的,因此 Foursquare API 可以提供的信息将无法提供该市当地企业的清晰画面。
2.3 街区坐标
为了获得每个邻域的坐标,我使用了 geopy,这是几个流行的地理编码 web 服务的 Python 2 和 3 客户端,geopy 使 Python 开发人员可以使用第三方地理编码器和其他数据源轻松定位全球各地的地址、城市、国家、
和地标的坐标[32]。问题是提华纳的许多社区似乎没有 geopy 中的坐标,结果是 NaN。目前的解决方案
是手动输入其余的坐标,问题是这里有超过 3000 个社区,所以我选择关注 100 个更暴力的社区。这一部分做了一些考虑:
- Mariano Matamoros Centro 街区在谷歌或其他在线网站上没有坐标,所以我将其重命名为最近的街区,在这种情况下,Mariano Matamoros。
- 我找不到 Tres de Octubre 街区的坐标,问题是“Tres”,所以我把它改成了数字 3。
- Obrera Seccion 1 和 Fraccionamiento Natura 街区存在与 Mariano Matamoros Centro 相同的问题,完成了相同的过程,在这种情况下,最近的街区是 Obrera 和 Fraccionamiento Hacienda las Delicias。
- Sanchez Taboada Produsta 和 Sanchez Taboada 街区之间的划分是不存在的。这两个街区总是被视为一体,所以我也这样做了。
- Foranea 和 Hacienda Las Fuentes 社区与 Mariano Matamoros Centro 有同样的问题,但这次我在任何在线地图上都找不到它们的位置。我决定从数据中剔除他们两个。
3 方法论
本节中使用的直方图的程序在我的 Github 中如下 链接 而对于地图 这个
图 2:2014-2019 年期间犯罪分类的频率
下加利福尼亚州是全国汽车盗窃案的第一名[25],在蒂华纳,这种犯罪的数量如此之大也就不足为奇了。对每一项犯罪的分析都很重要,但在这项工作中,重点将放在暴力犯罪上,特别是暴力盗窃和杀人。因此,我们可以将暴力犯罪的数据划分如下:
- 暴力抢劫(公共区域)
- 暴力盗窃生意
- 暴力盗车
- 其他暴力抢劫
- 暴力入室盗窃
- 恶意伤人
- 凶杀(暴力)
这些暴力犯罪仅占数据显示的犯罪总数的 31.49%,但这些类型的犯罪对城市生活的影响更大。
图 3:2014-2019 年期间暴力犯罪的频率
从图 3 中可以看出,对企业的暴力盗窃是更常见的犯罪,这是一个私营部门一直要求当局注意的问题[2]。
图 4:最暴力的街区正如所料,这份名单一直都是一样的
图 4 显示了 15 个最暴力的街区。图 5 显示了 100 个暴力程度较高的社区的犯罪数量集群,通过描述中的链接可以看到每个社区的犯罪数量。
图 5:显示 100 个最暴力的社区和每个社区暴力犯罪数量的地图。点击此链接观看互动地图。
现在我们将关注:对企业的暴力盗窃和杀人;这些都是社区安全的有力指标。
3.1 暴力盗窃企业
图 6:暴力盗窃案件数量最多的社区
在图 6 中,显示了 15 个对企业暴力盗窃较多的街区。图 7 是聚类图,其中红色表示此类犯罪数量较多。
图 7:显示 100 个暴力程度较高的社区中针对企业的暴力盗窃数量的地图,
红色的强度意味着该区域的盗窃数量较高。点击链接观看互动地图。
图 8 显示了企业暴力盗窃的频率。我们可以看到,这种类型的犯罪在晚上更常见,在 0 点时有一个高峰。2017 年是对企业更危险的一年,2015 年是最危险的一年,2018 年和 2019 年没有变化。
图 8:按年份和小时划分的暴力盗窃发生频率
3.2 凶杀案
图 9:凶杀案数量最多的社区
图 9 显示了凶杀案较多的 15 个街区。图 10 是一个聚类图,其中红色显示了这类犯罪的高数量。
图 10:显示 100 个暴力程度较高的社区的凶杀案数量的地图,红色的强度表示该地区有更多的凶杀案。点击链接观看互动地图。
图 11 显示了凶杀案的发生频率。我们可以看到,令人惊讶的是,这种类型的犯罪通常发生在白天和下午高峰的 7、20、21 和 22 小时。2018 年是最危险的一年,2014 年是最危险的一年,2019 年显示出了一点好转。
图 11:按年份和小时分列的凶杀频率
3.3 当地企业
图 12:暴力社区中更常见场所的出现频率
图 12 显示了暴力街区中更常见的场所的出现频率。这张直方图是使用 Foursquare API 搜索该市 100 个暴力程度较高的社区中更常见的场所制作的。最常见的是电子商店,在 Foursquare 城市指南中快速搜索,主要是指智能手机及其配件和互联网提供商办公室的销售。第二和第三常见的是甜甜圈店和潜水酒吧。
图 13:凶杀案较多的 4 个街区和最常见的地点
图 14:对企业实施暴力盗窃较多的 5 个社区及其常见场所
图 14 显示了凶杀案较多的 4 个街区中最常见的公共场所。更多的公共场所是酒吧和食品摊贩。
图 Foursquare API 在 18 个街区没有找到场地
图 15 显示了 Foursquare 中没有场地的 18 个社区。
图 16:城市暴力街区中最常见场所的集群。紫色和红色的
点大多是餐馆和酒吧,绿色的点大多是便利店。点击链接观看互动
地图。
4 结果和讨论
从数据中可以看出,凶杀案的数量在括号中伴随着暴力这个词。对我来说,这很奇怪,我找不到更多关于这种分类定义的信息。我能推断的是,这些数据只显示了被认为是暴力杀人的案件,其余的都被忽略了,这非常令人不安。不被认为是暴力的凶杀案的数量可能会更高。
关于社区中最常见的场馆的信息很少,18 个没有显示任何场馆。剩下的一个被认为是不完整的,考虑到城市中的非正规商业[33]非常高,Foursquare 基于用户输入,但 43 %的墨西哥人是数字文盲,只有 39 %的家庭有网络连接[16]。Foursquare 上提供的信息并不能展示该城市商业的全貌。
考虑到所有这些问题,我们可以看到更重要的本地商业都与食物有关:餐馆、甜点店和街头小吃。酒吧都在离边境最近的社区,至少在暴力地区是这样。
凶杀和暴力盗窃案件较多的 5 个社区如下:
凶杀案(暴力)
- 绿色卡米诺
- 北带
- 桑切斯·塔博达
- 中央区
- 10 月 3 日
暴力盗窃一家企业
- 马里亚诺·马塔莫罗斯
- 中央区
- 北马里亚诺·马塔莫罗斯
- 埃尔弗洛里多 1 区和 2 区
- 埃吉多·弗朗西斯科别墅
只有 Zona Centro 重复出现在两项犯罪的前 5 名中。考虑到凶杀率对一个社区的影响,我将把重点放在凶杀率较高的 5 个社区,并将这些数字放在上下文中。
卡米诺·维德和桑切斯·塔博达
图 17:谷歌地图上的 Camino Verde 和 Sanchez Taboada 街区
在图 17 中显示了 Camino Verde 和 Sanchez Taboada 社区的地图,可以看出它们是并排的,没有明显的分界线。这两个街区可以被认为是一个凶杀率非常高的大区域。
图 18:地质断层和下沉摧毁了 Sanchez Taboada 社区的数千所房屋。图片来自【31】。
几年来,地质断层和下沉摧毁了 Sanchez Taboada 社区的数千所房屋[31,26],导致大约 2000 人无家可归。暴力和吸毒对一个已经贫困的社区的影响还没有被调查过。
北部区域和中部区域
图 19:谷歌地图上的 Zona centro(蒂华纳市中心)附近
在图 19 中显示了 Zona Norte 和 Zona Centro 街区的地图,与 Camino Verde 和 Sanchez Taboada 相同,它们是并排的。它可以被认为是另一个大的暴力区域。Zona Centro 是该市最古老的街区之一,也是游客最多的地方之一,因为它靠近边境。
靠近北部区域和中部区域的是蒂华纳河,它至少从 20 世纪初就被用作废水管道。这条河的隧道里住着大量无家可归者、吸毒者和移民,他们正等着越境去美国或者已经被驱逐出境。这条河是暴力犯罪的热点。
北部区域是这个城市的红灯区。摘自报纸" La voz de la frontera "的一篇文章[15]:圣地亚哥州立大学的维克多·克拉克·阿尔法罗教授估计,蒂华纳是世界上与性旅游有关的一切都最繁荣的城市之一。专家指出,只有在城市的北部,有 2000 名性工作者在工作。这还不包括酒店、夜总会和出租车司机的员工,他们靠直接从国际线接游客为生。“这个地区的酒吧不仅有来自美国的顾客,还有来自欧洲的顾客,他们专门来寻求这种服务。从事性旅游的人是带着巨大的经济能力来到蒂华纳市的,”他说。许多受性服务驱使来到蒂华纳的游客的经济实力如此强大,以至于一些俱乐部和酒吧每天 24 小时都有一辆国际线路的豪华轿车,负责接送他们最尊贵的客户,并将他们直接送到容忍区。
没有官方数据显示它给这个城市带来的经济溢出。人口贩卖和毒品销售是这个地区的大问题,也是暴力犯罪的另一个热点。
十月三日
图 20:10 月 3 日街区的极端贫困。照片来自【7】。
10 月 3 日街区是蒂华纳许多不规则形成的街区之一,只是占据了一部分土地。这导致了基本服务的缺乏,比如水、电力设施和许多其他服务。极端贫困是暴力犯罪的另一个热点。
5 个结论
图 21:“在墨西哥,杀人容易,不进监狱难”【24】。图片来自 Pixabay (CC0)的mizer _ X94
在这项工作中,使用 Foursquare API 确定了蒂华纳最暴力的社区,并找到了它们最常见的场所,得出了以下结论:
- 在暴力街区,更重要的当地商业是酒吧和食品相关的,例如,餐馆、甜品店和街头小吃。在数据采集部分预测的药店的预期高数量是错误的。
- 鉴于墨西哥的数字文盲,从 Foursquare 获得的信息并不能展示该城市商业的全貌。
- 为了完成一部更完整的作品,需要该城市当地商业的完整数据。这些数据可以在政府部门找到。
- 更暴力的社区与贫困、卖淫、吸毒和移民有关
- 蒂华纳的暴力事件只是墨西哥正在发生的事情的一个例子,一个需要改变的失败的系统。例如,记者在《动物政治》上的研究发现:“在墨西哥,杀人很容易,而且永远不会进监狱。每 100 起谋杀案中,只有 5 起有人被定罪。如果我们只专注于寻找那些在 2010 年至 2016 年期间犯下杀人罪的人,我们将需要 124 年才能做到这一点,因为按照这个速度,墨西哥司法系统是有效的”[24]。
“我不可能回墨西哥。我无法忍受身处一个比我的画更超现实的国家。”
著名画家萨尔瓦多·达利的这句话再好不过了,墨西哥是一个充满矛盾的国家。蒂华纳只是一个例子:尽管高度的不安全和暴力,这个城市仍然保持着稳定的经济增长。
参考文献
[1]国家发展规划委员会。下加利福尼亚和城市人口。2014 年 1 月。网址:http://www . copladebc . gob . MX/seis/pdf/apuntepoblacionbcymunicipiosene 14 . pdfpdf(2020 年 4 月 13 日访问)。
[2]Julieta aragón . preo cupa a empresioners robos a commercios,pes a Baja incidents in El Estado .2020 年 1 月 27 日。网址:【https://zetatijuana.com/2020/01/preocupa- a-empresarios-robos-a-comercios-pese-a-la-Baja-incidencia-en-El-Estado/(2020 年 4 月 16 日访问)。
[3]达罗·布鲁克斯。墨西哥的墨西哥旅游:蒂华纳是一个旅游胜地。2019 年 4 月 9 日。网址:https://www.bbc.com/mundo/noticias-美洲-拉丁- 47809220 (于 2020 年 4 月 16 日访问)。
[4] 尤金妮亚·希门尼斯·卡利斯。蒂华纳港,移民和吸毒者的家园。七月 31, 2014. url: https://www.milenio.com/politica/el-borde-de-tijuana-hogar-de-migrantes-y-吸毒者 (访问 04/17/2020)。
[5] 格拉西拉·迪亚兹(Graciela Dìaz),马赫主义-制造-普塔斯(Machism-Fabrica-Putas)。url: https://feminismoinc.org/2018/03/machismo-
fabrica-putas.html(访问于 2020 年 4 月 17 日)。
桑德拉·迪布尔。什么驱动 Tijuana’s Next Major?2013 年 7 月 14 日,URL:https://www.sandiegouniontribune.com/news/border-baja-california/sdut-what-drives-tijuanas-next-mayor-2013jul14-story.html(访问于 04/13/2020)。
[7] 拉斐尔·科罗拉多和埃德加·卡拉皮亚。10 月 3 日的。Feb 的。19,2019.url: https://www.facebook.com/TijuanaTelevisa/videos/416565892220378/(访问时间 04/17/2020)。
[8] 以弗所 AMLO 的安全策略不起作用:专家;墨西哥将在 2019 年以更多暴力解雇
Dec.网址:https://www.sinembargo.mx/22-12-2019/3700383(访问于 04/13/2020)。
[9] 国家社会发展政策评估委员会(CONEVAL)。国家贫困 2018.2018.url:https : / / www 。Coneval。组织。mx / 协调 / 实体 / 下加利福尼亚州 / char / Pobreza_2018.aspx (visited on 04/13/2020).
[10] 奥克塔维奥·罗德·拉塔涅格斯·费雷拉和大卫·A。饰 Shirk 蒂华纳暴力犯罪的复苏:墨西哥司法的分析。May 18, 2018. url: https://justiceinmexico.org/el-resurrection- del-crime-violento-en-tijuana-new-spanish-translation-of-justice-in-mexico-working-paper/ (visited on 04/13/2020)。
[美] 温迪·弗莱 Tijuana still Mexico’s bloodiest city 提华纳仍然是墨西哥最血腥的城市。毒品暴力 Blame Drug Violence 简。7,
2020 url: https://www.latimes.com/world-nation/story/2020-01-07/tijuana-drug-violence (访问于 04/13/2020)。
[12] 大卫·加涅蒂华纳的警察腐败现象普遍存在:报告。Feb 的。18, 2016. url: https://es .insightcrime.org/新闻/新闻- del-day/corruption-police-tijuana-generalized-report/ (visited on 04/17/2020)。
[13]胡安·米格尔·埃尔南德斯。杀害妇女,不受惩罚。02 月。http://www . elsoldetijuana . com . MX/local/murders-de-women-sin-un-punishment-489276 . html(访问日期:2020 年 3 月 4 日)。
[14]胡安·米格尔·埃尔南德斯。提华纳在经济上保持稳定。02 月。2,2019 . URL:https://wwwelsoldetijuana。-是啊。mx / local / tijuana —经济上保持—稳定— 3009856。html(于 2020 年 7 月 4 日访问)。
[15]胡安·米格尔·埃尔南德斯/。容忍区仍然存在于提华纳。八月 20,2019 . URL:https://www . lavozdelafrontera . com . MX/local/tolerance zone-persistent-en-Tijuana-404833 . html(访问日期:2020 年 7 月 4 日)。
[16] idc。43 %的墨西哥人是数字文盲。打开它。8,2019. url: https : / / idconline。MX/corporate/2019/04/08/43-de-los-Mexican-son-文盲-数字(访问日期:2020 年 7 月 4 日)。
[17]部署。2014 年各国代表团/2014 年殖民地基本地图。2014 . URL:http://implan . Tijuana . gob。MX/services/map/map . aspx(访问时间:2004/17/2020)。
[18]卡洛斯·加西亚。墨西哥的劳动者洛佩斯安全策略有什么缺陷?七个。5,2019. url: https : / /当前。rt 你好吗?com/current/326183-故障-战略-安全性-Lopez-labor-Mexico(访问日期:2020 年 13 月 4 日)。
[19]劳拉·桑切斯·雷。-卖淫。提华纳的儿童地狱。02 月。页:1。elnivasal . com . MX/article/States/2016/02/28/prostitution-El-hell-infantil-in-Tijuana # image-1(访问日期:2020 年 4 月 17 日)。
[20]米格尔马歇尔。提华纳和贸易的未来。2015 年 5 月 7 日,URL:https://www . weforum . org/agenda/2015/05/Tijuana-and-the future-of-trade/(访问日期:2020 年 13 月 4 日)。
[21]安东尼奥玛雅。在桑切斯塔布达发生的抢劫和暴力事件。2019 年 5 月 4 日,URL:https://www . elsoldetijuanacom . MX/policia/assault-y-violence-en-Sanchez-tabada-3570659 . html(访问日期:2020 年 13 月 4 日)。
[22]伊莎贝尔市场。在当局的漠视下,边缘再次被重新定位。2017 年 7 月 24 日,URL:https://zeta Juana。com/2017/07/ante----对当局无动于衷----返回----重新部署/(访问日期:2020 年 7 月 4 日)。
[23] 亚当·蒙德拉贡在下加利福尼亚州,有超过 7,800 起强奸和 18,000 起性犯罪。Aug。17,2019.url: https://cadenanoticias.com/regional/2019/08/en-baja-california-mas-de-7-mil-800-强奸和 18-mil-性犯罪(访问 04/13/2020)。
[24] 政治动物在墨西哥杀人:有罪不罚的保证。六月 19, 2019. url: https://www.animalpolitico.com/muertos-mexico-凶杀案-有罪不罚/ (访问于 04/17/2020)。
[25] Lourdes Loza Romero。BC:汽车盗窃的第一个国家。Apr。13,2020 URL:https 😕 / zetatijuana 。com / 2020 / 04 / bc — 第一 — 地方 — 国家 — 在 — 盗窃 — 从 — 车 / (访问 04/16/2020).
[26] 丹尼尔·安赫尔·卢比奥迫切需要在 Sánchez Taboada 重新安置 2,000:Rosas。Dec。22, 2019. url: https : // www.elsoldetijuana.com.mx/local/urge- 重新定位- a- 2-mile-en-桑切斯-塔布阿达-玫瑰- 4619362.html (访问 04/17/2020).
[27] 格伦·桑切斯蒂华纳需要研究成瘾。七个。26,2019.url: https://www.elimparcial .com/tijuana/tijuana/Tijuana-required-studio-de-瘾-20190926-0005.html (visited on04/13/2020)。
[28] 国家安全和调查警卫队。犯罪行为数据库。url: https://www.seguridadbc.gob.mx/content/statisticas3.php (visited on 04/13/2020)。
[29] 辛提斯,在你脚下。url:https : / / synesistv 。com。mx /卖家 - 街头小贩 - 在 - 的 - 不规则 - 通过 - 延迟 - 通过 - 约会/下 5 / (visited on 04/17/2020)。
[30] 提华纳的太阳他们在 BC 的电话勒索中筹集了大量资金。May 4, 2019.url:https : / / www 。Elsoldetijuana。com。mx / 本地 / 增加 — 金额 — 从 — 钱 — 在 — 勒索 — 电话 — 从 bc-3573103.html (visited on 04/13/2020).
[31] 提华纳的太阳。他们将拆除 Sánchez Taboada 分裂的房屋。Dec。2018 年 2 月 28 日,URL: https: / / www 。Elsoldetijuana。com。mx / 警察 / 拆除 — 房屋 — 在 — 分割 — 桑切斯 — —
taboada-jaime-bonilla-4632848.html (visited on 04/17/2020).
[32]python geooding toolbox . geo 1 . 21 . 0 .2018 . URL:https://pypi . org/project/geo/(访问时间:2020 年 13 月 4 日)。
[33]卡琳·托雷斯。非正规贸易造成了数百万美元的损失:卡纳克。八月 7,2019 . URL:https://www . elsoldetijuana . com . MX/local/commerce-非正式-代表损失-百万美元-canaco-4005433.html(访问日期:2020 年 7 月 4 日)。
[34]美国-墨西哥研究中心。无边界的工作:就业、工业集中,以及在卡利巴地区的比较优势。2014 . URL:https://usex . ucsd . edu/_ fil/2014 _ report _ jobs withoutdaters . pdf(访问时间:2020 年 13 月 4 日)。
[35]戴维·维森特诺和德国瓦努阿图。国民警卫队是国家的军事化:联阿援助团的学者。-简!10,2019 . URL:https://www . excelsior . com . MX/national/guard-es-la-军事化-del-Pais-academic-de-la-unam/1289456(访问日期:2020 年 4 月 16 日)。
[36]卡罗莱纳·巴斯克斯。国民警卫队开始沿绿线和桑切斯塔布达巡逻。2019 年 7 月 12 日,URL:https://psn . si/Guardia-national-start-patrol-cv/2019/07/(访问日期:2020 年 4 月 16 日)。
[37]劳拉·沃登贝格。被驱逐者的炼狱。2013 年 6 月 9 日,URL:https://www . vice . com/es _latam/article/z9 JMX/El-purgatorio-de-los-expulsado-0000410-v6n4(访问日期:2020 年 17 月 4 日)。
[38]奥斯瓦尔多·扎瓦拉。国民警卫队和边境军事化。2019 年 7 月 12 日,URL:https://www . process . com . MX/592118/la-Guardia-national-y-la-armitation-de-las-fronteras(访问日期:2020 年 4 月 16 日)。
Python 和 OpenCV 中视频会议的虚拟背景——一种愚蠢的方法
用 Python 和 OpenCV 创建视频会议的虚拟背景。基本方法教程和思想。
虚拟背景是目前远程工作的员工的热门话题之一。由于新冠肺炎疫情,我们中的一些人目前被隔离,许多人不得不进行视频通话,以便继续他们的工作。一些用于视频会议的软件工具允许设置虚拟背景,以便用户可以为接听这些电话营造更友好的氛围。
作为一名程序员,我第一次使用这样的虚拟背景时,自然被激起了兴趣。我想知道它是如何工作的。我能建立这样的虚拟背景吗?如果是的话,我该怎么做?剧透:进展不顺利!尽管如此,我认为这是一个很好的教育练习,在研究这个话题的时候,我没有找到太多的信息。因此,正如我对所学的一切所做的那样,我决定把它记录在这里,也许其他人会从中受益。
因此,在本教程中,我们将尝试一种用计算机视觉技术构建虚拟背景的基本方法,使用 Python 和 OpenCV。
介绍
这个项目的目标是拍摄一段视频,试着找出视频的背景和前景,去掉背景部分,用一张图片代替——虚拟背景。因为在这个项目中,我们将使用平凡的方法,我们将需要假设,在一般情况下,前景将有不同于背景的颜色。但是首先,让我们看看我们的工具是什么。
计算机视觉
计算机视觉是一个跨学科领域,研究计算机如何处理和(也许)理解图像和视频。我们说它是一个跨学科领域,因为它从不同学科(计算机科学、代数、几何等等)借用了很多概念,并将它们结合起来解决了很多不同的复杂任务,比如图像和视频中的对象跟踪、对象检测、 对象识别、对象分割。
OpenCV
OpenCV 是为解决计算机视觉任务而构建的库。它是开源的,可用于几种编程语言,包括 Python 和 C++。它有大量的计算机视觉功能,其中一些基于数学和统计方法,另一些基于机器学习。
计算机编程语言
如果您已经阅读了本文,那么您可能知道 Python 是什么😀
构建虚拟背景
我尝试的方法如下。我将展示每一步的代码片段,在文章的最后,您将看到完整的代码。
- 导入依赖项
import numpy as np
import cv2
2.从本地环境加载视频并初始化数据
ap = cv2.VideoCapture('video6.mp4')
ret = True
frameCounter = 0
previousFrame = None
nextFrame = None
iterations = 0
3.从本地环境加载替换背景图像
backgroundImage = cv2.imread("image1.jpg")
4.逐帧分割视频
while (ret):
ret, frame = cap.read()
5.取每一对两帧
if frameCounter % 2 == 1:
nextFrame = frame if frameCounter % 2 == 0:
frameCounter = 0
previousFrame = frame frameCounter = frameCounter + 1
iterations = iterations + 1
6.求两帧的绝对差值并转换成灰度->获取蒙版。
if iterations > 2:
diff = cv2.absdiff(previousFrame, nextFrame)
mask = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
每幅图像都由像素组成——你可以把它想象成一个由行和列组成的 2D 矩阵,矩阵中的每个单元都是图像中的一个像素(当然,对于彩色图像,我们有不止 2 个维度,但为了简单起见,我们可以忽略这一点)。
我们通过在第一幅图像中逐个像素地(在第一矩阵中逐个单元地)替换另一幅图像中的相应像素(在另一矩阵中的相应单元)来获得差异。
这里有一个窍门:如果在两帧之间,一个像素没有被修改,那么结果当然会是 0 。*2 帧之间像素怎么会不一样?*如果视频是完全静态的(图像中没有任何东西移动),那么所有像素的每一帧之间的差异将为 0,因为没有任何东西发生变化。但是,如果图像中有物体移动,那么我们可以通过检测像素差异来识别物体在图像中的移动位置。我们可以假设,在视频会议中,移动的东西在前景中——也就是你——而静止的部分是背景。
还有这个 0 有什么重要的?图像中每个为 0 的像素将显示黑色,我们将利用这一点。
7.找到遮罩中超过阈值的单元格—我选择了 3 作为阈值,但是您可以使用不同的值。较大的值将从背景中移除更多,但也可能从前景中移除更多。
th = 3
isMask = mask > th
nonMask = mask <= th
8.创建一个空图像(每个单元格为 0),大小为两个帧中的任意一个。
result = np.zeros_like(nextFrame, np.uint8)
9.调整背景图像的大小,使其与框架大小相同。
resized = cv2.resize(backgroundImage, (result.shape[1], result.shape[0]), interpolation = cv2.INTER_AREA)
10.对于遮罩中大于阈值的每个单元,从原始帧复制。
result[isMask] = nextFrame[isMask]
11.对于低于阈值的遮罩中的每个单元格,从替换背景图像中复制。
result[nonMask] = resized[nonMask]
12.将结果帧保存到本地环境。
cv2.imwrite("output" + str(iterations) + ".jpg", result)
结果和结论
那么结果如何呢?老实说,我对这个结果有点失望。然后我做了更多的研究,原因变得更加明显。你需要更先进的方法来解决这个问题,大公司在这类问题上投入大量资源也就不足为奇了。
下面是我试的视频截图。基本上就是我的手在墙前移动的视频。
虚拟背景 Python 和 OpenCV 教程—输入
这是输出图像的截图。作为背景,我用了一张我在罗马尼亚拉斯诺夫的照片。
虚拟背景 Python 和 OpenCV 教程—输出
正如我所说的,我对结果不是很满意。但是我对从这个项目中学到的东西很满意。这是一次有趣的学习经历,也是一种很好的方式来花时间处理我不习惯处理的概念。
创建虚拟背景的其他方法
如果你认为一个问题非常复杂,需要你在计算机软件中看到的不寻常的智能水平,那么答案可能是机器学习。😀
已经有深度学习模型可以执行这种任务。但是这样一个模型需要大量的数据集来训练和大量的处理能力,而在我写这篇文章的时候,我还没有这样的能力。这样的深度学习模型要解决的任务叫做图像分割。
另一种方法是计算机视觉方法,用于寻找照相机和图像中的物体之间的距离。然后你可以建立一个阈值来区分前景和背景。在那之后,你可以使用我用来移除背景的相同遮罩,并引入一个新的遮罩。
本文原载于 程序员背包博客 。如果你想阅读更多这类的故事,一定要访问这个博客。
非常感谢您阅读本文!对更多这样的故事感兴趣?在 Twitter 上关注我,地址是@ b _ dmarius,我会在那里发布每一篇新文章。
使用机器学习的视频会议的虚拟背景
使用 DeepLab v3 图像分割模型和 OpenCV Python 实现
每当我们的环境发生变化,技术也随之发展。COVID 期间增加的视频会议突出了虚拟背景的概念。说出任何一种视频通信服务,无论是 Google Meet、Zoom 还是 MS Teams,你都会注意到这个功能。保护一个人的隐私或者只是隐藏他们混乱的环境,虚拟背景真的很有帮助。
好奇如何用简单的编码实现?本文包含理解并在您自己的系统中执行它所需的所有信息。图像分割和掩蔽的概念用分步编码来解释。
虚拟背景
虚拟背景的目的是为了各种个人原因定制一个人的背景。为了能够修改我们的,让我们了解细节。你如何定义背景?在数码相框中,除了你的身体定义之外的一切都可以被认为是背景。想象一下你的网络摄像头的画面,一个像素一个像素地把你的身体描述从其余部分中分离出来。
https://dahtah.github.io/imager/foreground_background.html中西蒙·巴塞尔姆拍摄的图片
同样,这幅图像也描述了手头的任务。没有背景的分割前景鹦鹉是主要焦点。它可以叠加在任何图像/背景上,形成一个整体图像。使用一个简单的 OpenCV 代码来导入一个虚拟的背景图像
图象分割法
图像分割是一种计算机视觉算法,用于将任何图像分成各种片段。分割的输出完全基于应用。对于对象检测,分割的图像将包含不同颜色的汽车、人、道路、停车标志、树和场景中存在的其他对象。
https://www.anolytics.ai/semantic-segmentation-services/中的图像
我们的目标是如前所述分割背景和前景。因此,如果我们检测到一个人的数字,它的像素化分割应该执行。这种分割是使用 TensorFlow 的 DeepLab v3 模型实现的。它相当于迄今为止最好的开源实现之一,甚至能够在视频分割上给出体面的帧速率。
编写以下代码来下载模型。下载后,将其复制到工作目录并删除该块。它必须使用此代码下载,不能通过链接手动完成。
导入必要的库。PIL 和 OpenCV 主要用于分割后的图像处理,而其他的则用于运行 DeepLab 类。该模型能够在以下提到的标签之间进行分类。它接收一个 zip 模型文件并分别预测输出。
声明 DeepLab 类和分割图像所需的其他函数。以下代码段可以在 DeepLab 在其自述文件中提供的笔记本参考中找到。如果您过于担心这段代码的复杂性,请不要担心。一般来说,所有分割模型都是使用 Coco 或 ImageNet 数据集训练的。根据架构、输入和输出格式的不同,下面的代码会有所不同。
让我们做一个状态检查。我们导入了需要的虚拟背景,下载了模型,加载了模型,定义了 DeepLab 类。通过调用该类的 run 函数可以获得分段输出。总的来说,我们有我们的背景和分割需要叠加在它上面。
OpenCV
OpenCV 在我们的应用程序中的主要任务是在虚拟背景中创建分割的遮罩,将所有正在使用的图像调整到相同的尺寸,最后添加被遮罩和分割的图像。从加载的模型继续,让我们看看 OpenCV 中的每一步是如何执行的。
第一步:视频拍摄
视频的每一帧都必须被提取、分割并添加到虚拟背景中。OpenCV video capture 用于加载网络摄像头视频并提取每一帧。一般来说,这个过程会导致延迟,但是轻量级模型和最少的预处理能够提供不错的帧速率。
步骤 2:帧分割
每一帧都通过 MODEL.run()函数来获得结果分割。该类返回 2 个值:调整大小的原始图像和分割的地图轮廓。分割图用于形成描绘边界的图像。
分段掩码的输出
步骤 3:分段地图处理
分割的图像用于从每一帧中提取原始姿态。首先使用下面的方法将它转换成黑白图像。进行这种转换是为了简化掩蔽过程。
在 seg_im 预处理之后
第四步:遮盖
简单来说,遮罩就是在图像上创建一层遮盖物。一方面,我们有一个黑白分段帧,另一方面,原始网络摄像头帧。在 seg_img 中有分段(黑色/0)的地方,原始帧的相应像素保持不变,否则转换为黑色。这是原始帧中分割的遮罩。使用类似的逻辑,在虚拟背景上执行相反的操作。哪里有分割,哪里的像素就转换成黑色。
a.原始帧的屏蔽分割 b .虚拟背景屏蔽
输出
我们就要到达终点了。在对每个所需图像进行遮罩后,只剩下加法。在显示视频的每一帧之前,添加 seg_img 和 back 。
最终输出
结论
我们已经通过 TensorFlow DeepLab v3 模型实现了图像分割。通过使用遮罩和其他 OpenCV 预处理,可以看到最终的虚拟背景。这种方法符合当前的技术标准。虽然这也可以通过其他计算机视觉和图像处理算法来完成,即使不包括深度学习,也可以观察到许多缺陷。让我们列举一些例子:
- 简单的图像处理算法依赖于颜色变化来分离背景和前景。然而,这是一个深度学习模型,侧重于识别。
- 实时输出的准确性,尤其是在视频中,有时会很差。
- 在一个好的系统中,帧速率相当不错,但否则,输出可能会包含巨大的滞后。为了克服这一点,代码可以在 CUDA 上托管或实现。
- 代码主要使用 TensorFlow 和 OpenCV。它可以很容易地编码并在任何系统上运行,没有太多的依赖性问题。
这篇文章大体上到此为止。我希望这有助于理解虚拟背景是如何实现的。对于最初的 DeepLab v3 实现,请访问 DeepLab 笔记本。结果的准确性可能不太令人满意,因此我期待任何改进的建议。如果你遇到任何错误或有任何疑问,请评论。
关于我
我是一名三年级的 CSE 学生。我的主要兴趣和工作主要在于深度学习、强化学习、遗传算法和计算机视觉。如果你对这些话题感兴趣,可以看看我以前的博客,关注我,了解最新动态。我的项目和个人资料可以在 Github 和 LinkedIn 上查看。
具有身体分割技术的网络摄像机中的虚拟背景
网络摄像头背景变化不仅限于现在缩放,我只是用 tensorflow.js body-pix 模型在浏览器里做了一下
你有没有过这样的时刻,当你在社交媒体上浏览那些漂亮的旅行自拍时,你会自言自语:“我希望我能在那里”?你猜怎么着,我们今天要让它成真。利用最新的人物分割技术,我们可以在像素级上将身体部分与背景分开。
非常类似于视频会议软件 Zoom 的改变背景功能,可以把你身后凌乱的房间隐藏起来,把你运送到一个荒岛或者宁静的海滩。
在这篇文章中,我将向你展示如何构建一个随处自拍应用程序,它可以通过实时改变自拍的背景,让你置身于那些美丽的旅行场景中。不需要 Photoshop,也不需要绿屏。让我们找点乐子,倒数“3,2,1…说茄子”!
自己试试吧,演示在下面的链接里:
[## 使用 BodyPix - Benson 技术进行随处自拍-人物分割
你有没有过这样的时刻,当你在社交媒体上浏览那些漂亮的旅行自拍时,你会自言自语:“我希望我…
bensonruan.com](https://bensonruan.com/selfie-anywhere-person-segmentation-with-bodypix/)
履行
你在上面拍了一些自拍照,然后给你的朋友看了吗?我希望你喜欢它,这个应用程序利用了一种叫做身体分割的先进技术,它可以识别图像或视频流中的人,并从背景中分割出前景身体。
今年早些时候,谷歌发布了 BodyPix ,这是一个开源的机器学习模型,允许在浏览器中使用 TensorFlow.js 进行人和身体部位分割。我对这项技术感到惊讶,并产生了构建上述自拍随处应用程序的想法。下面请跟随我了解我是如何实现它的。
#步骤 1:包含 tfjs 和 body-pix
首先,简单的在 html 文件的<头>部分包含脚本Tensorflow.js
及其body-pix
模型。
<script src="[https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2](https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2)"></script><script src="[https://cdn.jsdelivr.net/npm/@tensorflow-models/body-pix@2.0](https://cdn.jsdelivr.net/npm/@tensorflow-models/body-pix@2.0)"></script>
或者您可以通过 npm 安装它,以便在 TypeScript / ES6 项目中使用
npm install @tensorflow-models/body-pix
#步骤 2:将网络摄像头传输到浏览器
为了让你的网络摄像头进入浏览器,我使用了 JavaScript 库navigator.mediaDevices.getUserMedia
。要了解更多细节,请参考我以前的文章:
[## 如何使用 JavaScript 访问网络摄像头并拍照
介绍网络摄像头-简易 npm 模块
medium.com](https://medium.com/swlh/how-to-access-webcam-and-take-picture-with-javascript-b9116a983d78)
#步骤 3:加载 BodyPix 模型
为了进行分割,我们首先需要通过调用bodyPix.load(modelConfig)
的 API 来加载预先训练好的 BodyPix 模型。BodyPix 附带了几个不同版本的模型,具有不同的性能特征,在模型大小和预测时间与准确性之间进行权衡。
默认情况下,BodyPix 加载一个带有0.75
乘法器的 MobileNetV1 架构。对于配有中端/低端 GPU 的计算机,建议这样做。对于移动设备,建议使用带有0.50
乘数的型号。ResNet 体系结构推荐用于具有更强大 GPU 的计算机。
**bodyPix.load**({
architecture: 'MobileNetV1',
outputStride: 16,
multiplier: 0.75,
quantBytes: 2
})
#第四步:身体分割
接下来,我们通过调用net.estimatePersonSegmentation(video, outputStride, segmentationThreshold)
的 API,开始通过 body-pix 模型馈送网络摄像机流以执行人物分割。它将图像分割成像素,这些像素是和不是人的一部分。它返回一个二进制数组,对于作为人的一部分的像素为 1,否则为 0。数组大小对应于图像中的像素数。
**net.segmentPerson**(webcamElement, {
flipHorizontal: true,
internalResolution: 'medium',
segmentationThreshold: 0.5
})
**.then(personSegmentation** => {
if(personSegmentation!=null){
drawBody(personSegmentation);
}
});
cameraFrame = requestAnimFrame(detectBody);
flipHorizontal
默认为假。如果分割&姿态应该水平翻转/镜像。对于默认水平翻转的视频(即网络摄像头),此选项应设置为 true,并且您希望分段&姿势以正确的方向返回。
segmentationThreshold
用于确定像素分数的最小值,该值必须被视为一个人的一部分。本质上,较高的值将在人的周围创建更紧密的裁剪,但是可能导致作为人的一部分的一些像素被从返回的分段掩码中排除。
它返回一个用SemanticPersonSegmentation
对象解析的Promise
。图像中的多个人被合并到一个二元蒙版中。除了width
、height
和data
字段,它还返回一个包含所有人姿势的字段allPoses
。所有人的数据数组,包含 307200 个值,640x480 图像的每个像素一个值。
{
width: 640,
height: 480,
data: Uint8Array(307200) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, …],
allPoses: [{"score": 0.4, "keypoints": […]}, …]
}
#第五步:去除背景
在上面的函数中,我们用二进制数组来表示像素是否属于人体,现在我们可以用它来去除背景,只在画布上画出人体。在 ImageData 对象中,每个像素保存红色、绿色、蓝色和 alpha(透明度)的值,移除背景的技巧是将像素的transparency
值设置为 0。
const canvasPerson = document.getElementById("canvasPerson");
let contextPerson = canvasPerson.getContext('2d');
function drawBody(personSegmentation)
{
contextPerson.drawImage(camera, 0, 0, camera.width, camera.height);
var imageData = contextPerson.getImageData(0,0, camera.width, camera.height);
var pixel = imageData.data;
for (var p = 0; p<pixel.length; p+=4)
{
**if (personSegmentation.data[p/4] == 0) {
pixel[p+3] = 0;
}**
}
contextPerson.imageSmoothingEnabled = true;
contextPerson.putImageData(imageData,0,0);
}
#第六步:在背景图片上覆盖画布
一旦我们有了只包含透明背景的身体的画布,那么我们只需要将它覆盖在令人惊叹的自然场景的背景图像上。
<video id="webcam" autoplay playsinline width="640" height="480"></video>
<div id="selfie-container">
**<div id="background-container"></div>**
<canvas id="canvasPerson" width="640" height="480"></canvas>
</div>
在下面应用 css 样式
#background-container {
height: 100vh;
width: 100vw;
**background-image: url(../images/greatwall.jpg);**
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
background-color: transparent;
}
#canvasPerson{
**background-color: transparent;**
position: absolute;
width: 100vw;
height: auto;
z-index: 9999;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
-moz-transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
-o-transform: scale(-1, 1);
transform: scale(-1, 1);
filter: FlipH;
}
#第七步:截图
为了拍照,我使用了第三方 JavaScript 库 html2canvas.js 。它允许你直接在用户浏览器上截取网页或部分网页的“截图”。
$("#take-photo").click(function () {
beforeTakePhoto();
var captureElement= document.getElementById('selfie-container');
var appendElement= document.getElementById('webcam-container');
**html2canvas(captureElement)**.then(function(canvas) {
canvas.id='captureCanvas';
appendElement.appendChild(canvas);
document.querySelector('#download-photo').href = canvas.toDataURL('image/png');
afterTakePhoto();
});
});
代码就这么多了!除此之外,只是使演示看起来不错。选择一个壮观的场景,摆好你最喜欢的姿势,微笑吧!
GitHub 知识库
您可以通过下面的链接下载上述演示的完整代码:
实例分割将人体与背景分离。通过改变,让自己置身于美丽的自然风景中…
github.com](https://github.com/bensonruan/Selfie-Anywhere)
结论
实例分割技术的进步现在显示出从自动驾驶汽车到医疗诊断等许多领域的前景。有了深度学习神经网络,模型现在变得越来越准确。我希望这篇文章只是你学习更多图像分割和计算机视觉的旅程的开始。
感谢您的阅读。如果你喜欢这篇文章,请在脸书或推特上分享。如果你有任何问题,请在评论中告诉我。在 GitHub 和 Linkedin 上关注我。
使用 OpenCV 的虚拟鼓组
学习使用 OpenCV 和 Python 的计算机视觉概念构建虚拟架子鼓
如果你是计算机视觉的新手,或者你有强烈的打鼓冲动,但没有鼓,那么你来对地方了!
在本教程中,我们将使用 OpenCV 的计算机视觉的基本概念建立一个虚拟鼓组。如果你是 OpenCV 的初学者,这将是一个很好的尝试教程。
虚拟鼓在行动
我们将从头开始构建项目,最终你会有一个很酷的项目来炫耀!
所有的源代码都可以在这个 GitHub 资源库中找到。首先,在您的本地机器上派生并克隆存储库。
git clone link_to_your_forked_repo
装置
导航到您的分叉目录(您下载的文件夹)。
通过在终端中运行以下命令,可以在您的环境中安装项目所需的包。
pip install -r requirements.txt
运行文件
在项目文件夹中运行以下命令。
python virtual_drums.py
您将在屏幕上看到添加了鼓的网络摄像头的输出。你可以用一根绿色的棍子敲鼓(钢笔或铅笔都可以)。
需要绿色棒,因为我们使用了一个检测窗口来检测绿色。
在遮光罩下,当窗口(图像中有鼓的部分)检测到绿色物体时,它会将其解释为鼓被击打并播放节拍。
我们现在来看看实现这一点的代码。
代码
在您喜欢的文本编辑器中打开virtual_drums.py
文件。
您可以继续构建您自己的文件,或者编辑您下载的文件。我们现在来看看这一切是如何工作的!
我们从导入必要的库开始。如果没有运行pip install -r requirements.txt
,你需要在你的环境中安装这些
# Importing the necessary libraries
import numpy as np
import time
import cv2
from pygame import mixer
接下来,我们定义一个函数,当在窗口上检测到绿色对象时播放鼓声。
如果检测到的颜色在我们设定的范围内,我们就播放声音。
# This function plays the corresponding drum beat if a green color object is detected in the region
def play_beat(detected,sound):# Checks if the detected green color is greater that a preset value
play = (detected) > hat_thickness[0]*hat_thickness[1]*0.8# If it is detected play the corresponding drum beat
if play and sound==1:
drum_snare.play()
elif play and sound==2:
drum_hat.play()
time.sleep(0.001)
接下来,我们定义一个函数来检测绿色是否出现在我们的窗口中。
# This function is used to check if green color is present in the small region
def detect_in_region(frame,sound):
# Converting to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Creating mask
mask = cv2.inRange(hsv, greenLower, greenUpper)
# Calculating the number of green pixels
detected = np.sum(mask)
# Call the function to play the drum beat
play_beat(detected,sound)
return mask
接下来,我们导入我们的鼓点并存储它。
然后,我们设置应该检测的绿色的上限和下限。你可以把它改变到你想要的颜色的极限。
然后,我们启动网络摄像头并从中读取输入。
# A flag variable to choose whether to show the region that is being detected
verbose = False
# Importing drum beats
mixer.init()
drum_hat = mixer.Sound('./sounds/high_hat_1.ogg')
drum_snare = mixer.Sound('./sounds/snare_1.wav')
# Set HSV range for detecting green color
greenLower = (25,52,72)
greenUpper = (102,255,255)
# Obtain input from the webcam
camera = cv2.VideoCapture(0)
ret,frame = camera.read()
H,W = frame.shape[:2]
kernel = np.ones((7,7),np.uint8)
我们将导入要添加到视频输出中的鼓的图像。在这个例子中,我下载并添加了一顶高帽和一个小鼓。
# Read the image of High Hat and the Snare drumhat = cv2.resize(cv2.imread('./images/high_hat.png'),(200,100),interpolation=cv2.INTER_CUBIC)snare = cv2.resize(cv2.imread('./images/snare_drum.png'),(200,100),interpolation=cv2.INTER_CUBIC)
我们现在将设置应该检测绿色的区域或窗口。在本例中,我们有两个鼓,因此我们创建了两个窗口。
# Set the region area for detecting green color
hat_center = [np.shape(frame)[1]*2//8,np.shape(frame)[0]*6//8]
snare_center = [np.shape(frame)[1]*6//8,np.shape(frame)[0]*6//8]
hat_thickness = [200,100]
hat_top = [hat_center[0]-hat_thickness[0]//2,hat_center[1]-hat_thickness[1]//2]
hat_btm = [hat_center[0]+hat_thickness[0]//2,hat_center[1]+hat_thickness[1]//2]
snare_thickness = [200,100]
snare_top = [snare_center[0]-snare_thickness[0]//2,snare_center[1]-snare_thickness[1]//2]
snare_btm = [snare_center[0]+snare_thickness[0]//2,snare_center[1]+snare_thickness[1]//2]
time.sleep(1)
然后,我们运行一个无限循环,当我们按下键盘上的“Q”时,这个循环就会中断。
我们调用函数在屏幕上显示鼓声,并调用函数检测是否有绿色物体击中窗口。
最后,我们必须在按“Q”退出后清理打开的窗口。
while True:
# Select the current frame
ret, frame = camera.read()
frame = cv2.flip(frame,1)
if not(ret):
break
# Select region corresponding to the Snare drum
snare_region = np.copy(frame[snare_top[1]:snare_btm[1],snare_top[0]:snare_btm[0]])
mask = detect_in_region(snare_region,1)
# Select region corresponding to the High Hat
hat_region = np.copy(frame[hat_top[1]:hat_btm[1],hat_top[0]:hat_btm[0]])
mask = detect_in_region(hat_region,2)
# Output project title
cv2.putText(frame,'Virtual Drums',(10,30),2,1,(20,20,20),2)
# If flag is selected, display the region under detection
if verbose:
frame[snare_top[1]:snare_btm[1],snare_top[0]:snare_btm[0]] = cv2.bitwise_and(frame[snare_top[1]:snare_btm[1],snare_top[0]:snare_btm[0]],frame[snare_top[1]:snare_btm[1],snare_top[0]:snare_btm[0]], mask=mask[snare_top[1]:snare_btm[1],snare_top[0]:snare_btm[0]])
frame[hat_top[1]:hat_btm[1],hat_top[0]:hat_btm[0]] = cv2.bitwise_and(frame[hat_top[1]:hat_btm[1],hat_top[0]:hat_btm[0]],frame[hat_top[1]:hat_btm[1],hat_top[0]:hat_btm[0]],mask=mask[hat_top[1]:hat_btm[1],hat_top[0]:hat_btm[0]])
# If flag is not selected, display the drums
else:
frame[snare_top[1]:snare_btm[1],snare_top[0]:snare_btm[0]] = cv2.addWeighted(snare, 1, frame[snare_top[1]:snare_btm[1],snare_top[0]:snare_btm[0]], 1, 0)
frame[hat_top[1]:hat_btm[1],hat_top[0]:hat_btm[0]] = cv2.addWeighted(hat, 1, frame[hat_top[1]:hat_btm[1],hat_top[0]:hat_btm[0]], 1, 0)
cv2.imshow('Output',frame)
key = cv2.waitKey(1) & 0xFF
# 'Q' to exit
if key == ord("q"):
break# Clean up the open windows
camera.release()
cv2.destroyAllWindows()
就是这样!现在你可以用你的虚拟架子鼓演奏了。尝试更换鼓或将更多鼓添加到项目中。
您可以利用这些知识,通过 OpenCV 构建自己的计算机视觉应用程序。
编码快乐!
虚拟环境:什么,为什么,如何?
使用虚拟环境管理 python 和 python 包
Mac 预装 python 2。通过安装不同版本的 python 和不同的包,可以在 Mac 上的不同目录中安装更多的 python 环境。了解您正在使用哪种 python 非常重要。
您可以通过在终端中键入以下代码来检查当前正在使用的 python:
ericli@ERICYNLI-MB0 ~ % which python
/usr/bin/python
在这个例子中,我目前使用的 python 是预装的 python 2。如果 python 不是您想要使用的,那么您可能会遇到一个小问题。您可以通过将所需 python 的目录放在 Mac 上 path 变量的开头来解决这个问题。但是不推荐这种方法,因为如果您需要为不同的项目使用不同版本的 python 或 python 包,您将不得不一致地升级或降级您的 python 或 python 包。在这种情况下,强烈建议使用虚拟环境。
虚拟环境
虚拟环境是包含特定版本的 python 及其相关包的目录。虚拟环境是完全隔离的,因此您可以在 Mac 上拥有任意多个虚拟环境,并且始终非常清楚您正在使用哪个虚拟环境。
我强烈建议每个人在进入下一步之前安装 Anaconda,因为它很简单。在您安装了 Anaconda(【https://docs.anaconda.com/anaconda/install/】)之后,您需要将 Anaconda bin 的目录添加到路径中。要添加目录,只需输入以下代码并键入您的 Mac 密码:
ericli@ERICYNLI-MB0 ~ % sudo vim /etc/paths
Password:
对于那些感兴趣的人来说,“sudo”的意思是“超级用户 do”,它授予当前用户管理员权限。输入密码并按 enter 键后,您会看到如下内容:
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
在该文件中,创建一个新行,并将 Anaconda bin 目录添加到该文件中。
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
/opt/anaconda3/bin
文件保存后,您可以在终端中使用“conda”命令。
Vim 命令提示:
"o ":在光标下打开新一行
"O ":在光标上方打开新一行
":wq ":保存并退出
":q ":退出
“:q!”:强制退出(当有不需要的更改时)
使用 conda 命令,您可以使用所需的 python 版本和 python 包创建虚拟环境。通过激活虚拟环境,您在 Mac 上的路径被修改——虚拟环境的目录被放在路径文件的开头,因此一旦在虚拟环境中找到,您输入的任何命令都将被搜索和执行。
使用 python 版创建虚拟环境并激活它:
ericli@ERICYNLI-MB0 ~ % conda create --name py38 python=3.8 ericli@ERICYNLI-MB0 ~ % conda activate py38
要检查虚拟环境列表和当前环境(标有星号):
(py38) ericli@ERICYNLI-MB0 ~ % conda env list
# conda environments:
#
base /opt/anaconda3
py38 * /opt/anaconda3/envs/py38
要检查当前环境中安装了哪些软件包,并安装其他软件包:
(py38) ericli@ERICYNLI-MB0 ~ % conda list
(py38) ericli@ERICYNLI-MB0 ~ % conda install PACKAGENAME
激活新环境后,您会发现您正在使用的 python 就是您的虚拟环境中的 python。
(py38) ericli@ERICYNLI-MB0 ~ % which python /opt/anaconda3/envs/py38/bin/python
现在,您的新虚拟环境已经设置好了。您可以通过在终端中输入“python”或“jupyterlab ”(如果您安装了 jupyter lab)来开始使用这个环境。
最初发表于【http://github.com】。
数据科学的虚拟环境:使用 Pipenv 运行 Python 和 Jupyter
为 Python 设置虚拟环境。
作者: Edward Krueger 数据科学家兼讲师和 Douglas Franklin 助教兼技术作家。
在这篇文章中,我们将谈论虚拟环境以及它们为什么有用。您将学习如何在 Pipenv for Python 中设置虚拟环境。您还将学习如何在 Pipenv 环境之外运行 Jupyter 内核!
为什么环境对数据科学至关重要
环境是开发人员工作、学习和创造的空间。例如,如果您计划运行 Python 代码,您必须安装一些本地软件来练习 Python。这种设置被称为编程环境。这些环境包含开发人员创建和测试代码所需的特定工具。例如,一个环境可能包含 Python 和一些包。一旦环境设置正确,开发人员就可以畅通无阻地工作,并与其他人无缝地共享环境规范。
由于缺乏对虚拟环境的了解或经验,新开发人员通常在系统级别安装所有东西。用 pip 安装的软件包被放置在系统级。对每个项目都这样做的结果是一个臃肿且难以管理的单一 Python 环境。
有效的环境管理可以节省时间,并允许开发人员创建一个独立的软件产品,以便合作者或贡献者可以重新创建您的环境并运行您的代码。
Pipenv 将软件包管理和虚拟环境控制结合到一个工具中,用于安装、删除、跟踪和记录您的依赖关系;以及创建、使用和管理您的虚拟环境。Pipenv 本质上是将 pip 和 virtualenv 包装在一个产品中。
我们在开发过程中都遇到过这种错误。
ModuleNotFoundError: No module named 'pandas'
该错误意味着 Python 找不到该模块(也称为依赖项或包)。你肯定你在某个地方安装了熊猫,但是它在哪里呢?
Python 虚拟环境的主要目的是为 Python 项目创建一个隔离的环境。适当的隔离意味着每个项目都可以有自己的依赖项,而不管其他项目有什么依赖项。通过对环境和依赖关系的适当维护,可以避免上述错误和许多其他错误。健康的环境管理实践减少了项目之间的依赖版本冲突,并防止基础开发环境被包所膨胀。
数据科学和部署问题
数据科学家通常是跨学科的,没有受过正式的教育,无法与他人合作,将项目推向生产。因此,通常缺乏良好的环境和模块管理技能。这可能会导致代码可复制性的问题,或者推进或共享项目的困难。可再现的数据科学项目是那些允许其他人在您的分析基础上重新创建和构建,并重用和修改您的代码的项目。
卫生环境管理实践减少了项目之间的依赖版本冲突,并防止基础开发环境变得臃肿和不可管理,从而帮助用户创建可重复的项目。
由 xkcd 提供
Pipenv:更好的工作流程
Pipenv 将包管理和虚拟环境控制结合到一个工具中,使其成为数据科学家和开发人员的绝佳工具。
当您使用 Pipenv 开始一个项目时,该工具会自动创建一个虚拟环境、一个 Pipfile 和一个 Pipfile.lock。当您使用 Pipenv 安装时,Pipfile 会自动使用新的依赖项进行更新。
为了管理复杂的依赖关系,Pipenv 在一个名为 Pipfile.lock 的文件中保存了我们项目的依赖关系树;例如,依赖于其他旧版本依赖项的旧版本依赖项。Pipfile.lock 还验证生产中使用的依赖项版本是否正确。
最后,使用 Pipenv,您向其他人展示了一种安装项目依赖项以及测试和开发需求的标准化方法。
Pipenv 是一个环境管理器和包管理器。这意味着 Pipenv 可以用 Python 创建一个环境,然后用pipenv install
将包下载并安装到一个环境中。
此命令将依赖 Pipfile 来创建 Pipfile 存在的环境;如果没有,Pipenv 将为这个环境创建一个 Pipfile。
附加到该命令的包将被添加到 Pipfile 中。
pipenv install pandas matplotlib keras
Pipenv 工作流:终端
设置您的第一个 Pipenv:安装 Python、Pipenv 和 Pandas
- 安装Python3.7
- 打开端子安装** Pipenv**
pip install pipenv
3.创建一个新目录,并导航至该目录。
mkdir pipenv_test
cd pipenv_test
4.通过运行以下命令为环境安装 pandas 和 NumPy:
pipenv install pandas numpy
注意,Pipenv 将为这个项目创建一个虚拟环境、一个 Pipfile 和一个 Pipfile.lock。
可以用uninstall
关键字类似地删除包。
pipenv uninstall pandas
5.通过以下方式激活项目的虚拟环境:
pipenv shell
测试导入
完成上述操作后,您现在应该能够运行:
pipenv shell
接下来,使用以下命令打开 Python 解释器:
python
然后在 Python 解释器中:
import pandas
成功进口熊猫
如果成功的话,你正在改进你的开发工作流程!
如果出现任何问题,请确保在运行python
之前已经运行了pipenv shell
,并通过运行以下命令来验证环境中是否存在依赖项。
pipenv graph
Pipenv 依赖关系树
Pipenv 工作流:Jupyter
设置您的第一个 Pipenv:安装 Pipenv、Python 和 Jupyter
- 安装Python3.7
注: 3.8 与 Jupyter 在创作时是不兼容的
2.打开一个终端,在你的机器上安装 Jupyter Lab。
**pip install jupyterlab**
3。用以下工具安装管道:
**pip install pipenv**
4.创建一个新目录,并导航至该目录。
**mkdir pipenv_test
cd pipenv_test**
5.通过运行以下命令为环境安装 Ipykernel 和 Numpy:
**pipenv install ipykernel numpy**
注意,Pipenv 将为这个项目创建一个虚拟环境和一个 Pipfile。
6.激活项目的虚拟环境:
**pipenv shell**
7.连接环境到内核:
**python -m ipykernel install --user --display-name pipenv_test --name pipenv_test**
完成上述操作后,您现在应该能够运行:
**jupyter notebook**
或者您更喜欢实验室用户界面和附加功能。
**jupyter lab**
****在 Jupyter Notebook 中,选择“新建”查看下拉列表,查看可用内核列表。请注意,上面第 3 步中创建的“example_env”是内核的名称。
在笔记本中选择一个内核
****在 Jupyter Lab 中,你必须点击右上角的内核框来访问内核列表。或者,您可以单击“内核”选项卡,然后选择“更改内核”来访问同一个下拉菜单。
在实验室中选择内核
测试导入
在一个新的。ipynb 文件,尝试在单元格中运行以下代码。
**import pandas**
如果成功的话,你正在改进你的开发工作流程!
如果出现任何问题,请确保您选择了正确的内核,在运行jupyter lab
或jupyter notebook
以及连接内核之前,您已经运行了pipenv shell
。同样,您可以通过运行。
**pipenv graph**
Pipenv 依赖关系树
环境管理:
Pipenv 可用于指定 Python 版本和包版本。
**pipenv install django=1.11.10**
Python 规范:
**pipenv --python <path>
#or
pipenv --python python3**
Pipenv 可以从 requirements.txt 文件构建:
**$ pipenv install -r requirements.txt**
并且一个 requirements.txt 文件可以用包 pipenv-to-requirements 从 Pipfile 中创建。
**pipenv install pipenv_to_requirements**
然后运行:
**pipenv run pipenv_to_requirements**
这将在当前目录中生成 requirements.txt 和 requirements-dev.txt(如果适用)。
开发依赖性
Pipfile 将依赖项组织成两类,开发包和包。通过附加一个 dev 标志,可以将一个包指定为一个开发依赖项(不在生产中使用)。
**pipenv install black --dev**
管道文件结构
删除环境
使用pipenv —-rm
命令可以轻松删除环境。要再次创建环境,使用命令pipenv install
。
项目目录中的文件将保留。如果您希望删除它们,请删除整个目录。
结论
当您想要重现代码时,将所有的包安装在一个环境中会成为一个问题。想象一下,当项目只需要 6 个包时,导出一个列出 200 个包的 requirements.txt 文件。
Pipenv 将软件包管理和虚拟环境控制结合到一个工具中,用于安装、删除、跟踪和记录您的依赖关系;以及创建、使用和管理您的虚拟环境。
将 Pipfiles 添加到您的 Git 存储库中很好,这样其他用户就可以克隆存储库并在他们的系统上安装 Pipenv ,然后键入:
**pipenv install**
Pipenv 然后定位 Pipfiles ,创建一个新的虚拟环境,并安装必要的包。
Pipenv 之所以伟大是因为。
- 虚拟环境可以很容易地从 Pipfile 中重建
- 虚拟环境可轻松部署到服务器上
- Pipenv 使卫生包装和环境管理变得容易
- 适当管理的环境使协作者能够轻松地与您的代码交互并运行您的代码
有关更多信息,请查看虚拟环境的 Pipenv 文档说明。