本篇推文共计2000个字,阅读时间约3分钟。

华为云—华为公司倾力打造的云战略品牌,2011年成立,致力于为全球客户提供领先的公有云服务,包含弹性云服务器、云数据库、云安全等云计算服务,软件开发服务,面向企业的大数据和人工智能服务,以及场景化的解决方案。

华为云用在线的方式将华为30多年在ICT基础设施领域的技术积累和产品解决方案开放给客户,致力于提供稳定可靠、安全可信、可持续创新的云服务,做智能世界的“黑土地”,推进实现“用得起、用得好、用得放心”的普惠AI。华为云作为底座,为华为全栈全场景AI战略提供强大的算力平台和更易用的开发平台。

华为云官方网站

ModelArts华为云产品中面向开发者的一站式AI开发平台,为机器学习与深度学习提供海量数据预处理及半自动化标注、大规模分布式Training、自动化模型生成,及端-边-云模型按需部署能力,帮助用户快速创建和部署模型,管理全周期AI工作流。

华为云官方网站

手把手教你利用ModelArts实现人脸年龄预测

年龄预测,是指自动识别出一张图片中人物的年龄。这项技术有很多应用,如视频监控、产品推荐、人机交互、市场分析、用户画像、年龄变化预测等。

年龄预测场景

年龄预测场景

本实验将对图片中的人脸进行识别并根据人脸进行年龄预测。本实验将首先使用MTCNN模型检测出人脸区域,然后根据人脸区域使用SSR-Net模型预测年龄。

年龄检测结果图

实验将介绍如何利用华为云一站式AI开发平台ModelArts中的Notebook开发环境进行模型代码部署,使用和调试模型,预测出图片中人物的年龄。

ModelArts集成了基于开源的Jupyter Notebook,Jupyter Notebook是一个交互式笔记本,支持运行 40 多种编程语言。可为用户提供在线的交互式开发调试工具。用户无需关注安装配置,在ModelArts管理控制台直接使用Notebook,编写和调试模型训练代码,然后基于该代码进行模型的训练。

Notebook开发环境代码运行图

手把手利用ModelArts进行人脸年龄预测

1.准备实验环境

2.数据和代码下载

3.mtcnn库快速检测人脸

4.MTCNN模型实现检测人脸

5.SSR-Net模型预测年龄

6.实验小结

1

1.1密钥准备

首先需要进入华为云官方网站

https://www.huaweicloud.com/

点击页面的“控制台”切换至控制台界面,在账号名称的下拉菜单中点击“我的凭证”,进入创建管理访问密钥(AK/SK)的界面。位置如下图所示:

什么是访问密钥?

访问密钥即AK/SK(Access Key ID/Secret Access Key),是您通过开发工具(API、CLI、SDK)访问华为云时的身份凭证,不能登录控制台。系统通过AK识别访问用户的身份,通过SK进行签名验证,通过加密签名验证可以确保请求的机密性、完整性和请求者身份的正确性。

选择“访问密钥”,点击“新增访问密钥

妥善保存系统自动下载的“credentials.csv”文件中的AK(Access Key Id)SK(Secret Access Key)以备后续步骤使用。

1.2 创建Notebook开发环境

进入ModelArts主页:

https://console.huaweicloud.com/modelarts/?region=cn-north-4#/dashboard

选择全局配置:

进入全局配置页面后,点击“添加访问密钥

打开1.1下载的csv文件:

填写访问密钥后,点击确定即可:

在ModelArts服务主界面依次点击“开发环境”、“Notebook”、“创建

点击了“创建”后,填写创建Notebook所需的参数:

名称:自定义

工作环境:Python3

资源池:公共资源池

类型:GPU

规格:[限时免费]体验规格GPU版

存储配置:EVS

磁盘规格:5GB

配置好Notebook参数后,点击下一步,进入Notebook信息预览。

确认无误后,点击“立即创建

创建完成后,返回开发环境主界面,等待Notebook创建完毕:

点击进入刚才创建的Notebook:

创建一个Python3环境的的Notebook。点击右上角的"New"

然后选择TensorFlow 1.13.1开发环境。

点击左上方的文件名"Untitled"

输入一个与本实验相关的名称,如"age_face"

在Notebook中,我们输入一个简单的打印语句:

print("Hello,world!")

点击上方的运行按钮:

可以查看语句执行的结果:

至此,开发环境准备好啦,

我们接下来可以开始写代码了!

2

2.1数据和代码下载

运行下面代码,进行数据和代码的下载和解压:

from modelarts.session import Session
sess = Session()if sess.region_name == 'cn-north-1':bucket_path="modelarts-labs/notebook/DL_face_age_prediction/ssr.tar"
elif sess.region_name == 'cn-north-4':bucket_path="modelarts-labs-bj4/notebook/DL_face_age_prediction/ssr.tar"
else:print("请更换地区到北京一或北京四")sess.download_data(bucket_path=bucket_path, path="./ssr.tar")

运行结果如下:

运行下面代码,解压下载好的ssr.tar文件:

!tar -xf ssr.tar

运行结果如下:

至此,数据和代码准备完毕。

3

3.1mtcnn库快速检测人脸

运行下面代码,安装mtcnn库:

!pip install mtcnn==0.0.8

运行结果如下:

使用mtcnn库检测人脸,这种使用方式比较简单,但是无法对mtcnn库自带的人脸检测模型进行调优。在此,可体验一下这个库的用法。

运行下面代码:

import numpy as np
import cv2
import tensorflow as tf
import random
from PIL import Image

运行结果如下:

可以通过Notebook的upload功能上传测试图片:

这里上传的是我准备好的两张照片,当然也可以用自己的照片。

上传好照片,就可以开始测试,运行下面代码:

image_path = "./M.jpg"
img = Image.open(image_path)
img = np.array(img)

image_path的路径改为你的照片上传后所在路径。

调用mtcnn库,进行人脸区域检测:

from mtcnn.mtcnn import MTCNN as mtcnndetector = mtcnn()
detected = detector.detect_faces(img)# 打印检测结果
detected

运行结果如下:

将检测结果绘制在图片上:

# 绘图部分
box = detected[0]["box"]
res_img = cv2.rectangle(img, (box[0],box[1]),(box[0]+box[2],box[1]+box[3]), 0, 1)keypoints = detected[0]["keypoints"]
res_img = cv2.circle(res_img, keypoints['left_eye'], 1, 255, 4)
res_img = cv2.circle(res_img, keypoints['right_eye'], 1, 255, 4)
res_img = cv2.circle(res_img, keypoints['nose'], 1, 255, 4)
res_img = cv2.circle(res_img, keypoints['mouth_left'], 1, 255, 4)
res_img = cv2.circle(res_img, keypoints['mouth_right'], 1, 255, 4)res_img = Image.fromarray(res_img)
res_img

运行结果如下:

试试另外一张图片,运行结果如下:

4

4.MTCNN模型实现检测人脸

MTCNN网络分为三部分:PNet RNet ONet

如上所示,数据依次经过PNet,RNet和ONet,每经过一组网络,就进行一次NMS和边界框回归,最后在ONet网络输出中获得检测结果,人脸区域坐标及人脸关键点坐标。

NMS(non maximum suppression)非极大值抑制
当进行人脸检测时,可能会对同一张人脸区域有多个边界框检测结果,虽然这些检测结果都有很高的置信度,但是只需要置信度最高的检测结果,所以进行局部最大值检测,将不是最大值的预测结果去掉,完成边界框筛选的任务。

NMS被应用在很多目标检测模型当中,例如R-CNN,Faster R-CNN,Mask R-CNN等。

接下来,我们使用代码搭建MTCNN神经网络结构:

from src.align.detect_face import Network
from src.align.detect_face import rerec, pad
from src.align.detect_face import nms
from src.align.detect_face import imresample
from src.align.detect_face import generateBoundingBox

运行结果如下:

PNet

我们使用全卷积网络:Proposal 网络(PNet),来生成人脸区域备选框,备选框通过边界框回归进行校正。校正后,应用NMS来将高度重复的备选框进行筛选。

PNet构建代码如下所示:

class PNet(Network):def setup(self):(self.feed('data') .conv(3, 3, 10, 1, 1, padding='VALID', relu=False, name='conv1').prelu(name='PReLU1').max_pool(2, 2, 2, 2, name='pool1').conv(3, 3, 16, 1, 1, padding='VALID', relu=False, name='conv2').prelu(name='PReLU2').conv(3, 3, 32, 1, 1, padding='VALID', relu=False, name='conv3').prelu(name='PReLU3').conv(1, 1, 2, 1, 1, relu=False, name='conv4-1').softmax(3,name='prob1'))(self.feed('PReLU3') .conv(1, 1, 4, 1, 1, relu=False, name='conv4-2'))

RNet

RNet生成的所有人脸备选框都被输入另一个卷积网络,叫做Refine网络(RNet)。RNet将大量错误的人脸信息去掉,同样通过边界框回归进行校正,以及通过NMS进行筛选。

RNet构建代码如下所示:

class RNet(Network):def setup(self):(self.feed('data') #pylint: disable=no-value-for-parameter, no-member.conv(3, 3, 28, 1, 1, padding='VALID', relu=False, name='conv1').prelu(name='prelu1').max_pool(3, 3, 2, 2, name='pool1').conv(3, 3, 48, 1, 1, padding='VALID', relu=False, name='conv2').prelu(name='prelu2').max_pool(3, 3, 2, 2, padding='VALID', name='pool2').conv(2, 2, 64, 1, 1, padding='VALID', relu=False, name='conv3').prelu(name='prelu3').fc(128, relu=False, name='conv4').prelu(name='prelu4').fc(2, relu=False, name='conv5-1').softmax(1,name='prob1'))(self.feed('prelu4') #pylint: disable=no-value-for-parameter.fc(4, relu=False, name='conv5-2'))

ONet

ONet与RNet相似,但是在ONet将输出5个人脸关键点位置,全称为Output Network,作为最后一层网络,将输出人脸区域坐标以及人脸关键点坐标。

ONet构建代码如下所示:

class ONet(Network):def setup(self):(self.feed('data') #pylint: disable=no-value-for-parameter, no-member.conv(3, 3, 32, 1, 1, padding='VALID', relu=False, name='conv1').prelu(name='prelu1').max_pool(3, 3, 2, 2, name='pool1').conv(3, 3, 64, 1, 1, padding='VALID', relu=False, name='conv2').prelu(name='prelu2').max_pool(3, 3, 2, 2, padding='VALID', name='pool2').conv(3, 3, 64, 1, 1, padding='VALID', relu=False, name='conv3').prelu(name='prelu3').max_pool(2, 2, 2, 2, name='pool3').conv(2, 2, 128, 1, 1, padding='VALID', relu=False, name='conv4').prelu(name='prelu4').fc(256, relu=False, name='conv5').prelu(name='prelu5').fc(2, relu=False, name='conv6-1').softmax(1, name='prob1'))(self.feed('prelu5') #pylint: disable=no-value-for-parameter.fc(4, relu=False, name='conv6-2'))(self.feed('prelu5') #pylint: disable=no-value-for-parameter.fc(10, relu=False, name='conv6-3'))

三个网络代码运行结果如下:

网络代码运行结束后,进行数据准备:

# 打开原图
test_img = Image.open(image_path)
test_img

运行结果如下:

图片预处理:

# 进行图片预处理
test_img = np.array(test_img)
img_size = np.asarray(test_img.shape)[0:2]
factor_count=0
minsize = 20
total_boxes=np.empty((0,9))
points=np.empty(0)
h=test_img.shape[0] # h=410
w=test_img.shape[1] # w=599minl=np.amin([h, w]) # minl = [410,599] 中最小值 410
m=12.0/minsize # m=12/20
minl=minl*m # minl = 410*12/20 = 410* 0.6
factor = 0.709
scales=[]while minl>=12:scales += [m*np.power(factor, factor_count)]minl = minl*factor factor_count += 1# first stage
for scale in scales:hs=int(np.ceil(h*scale)) #大于等于该值的最小整数ws=int(np.ceil(w*scale))im_data = cv2.resize(test_img, (ws, hs), interpolation=cv2.INTER_AREA)im_data = (im_data-127.5)*0.0078125img_x = np.expand_dims(im_data, 0)img_y = np.transpose(img_x, (0,2,1,3))

运行结果如下:

运行PNet

运行PNet,并加载预训练权重:

with tf.Graph().as_default():with tf.Session() as sess:with tf.variable_scope('pnet'):data = tf.placeholder(tf.float32, shape=(None, None, None, 3), name="input")pnet = PNet({'data':data})pnet.load("./src/align/PNet.npy", sess)out = sess.run(('pnet/conv4-2/BiasAdd:0', 'pnet/prob1:0'), feed_dict={'pnet/input:0':img_y})# boundingbox regression 结果
out0 = np.transpose(out[0], (0,2,1,3))
# face classification 结果
out1 = np.transpose(out[1], (0,2,1,3))threshold = 0.5
boxes, reg = generateBoundingBox(out1[0,:,:,1].copy(), out0[0,:,:,:].copy(), scale, threshold)
print("PNet产生结果为:"+str(boxes.shape))total_boxes = boxes.copy()

运行结果如下:

边界框绘制函数:

# 边界框绘制函数
def draw_bboxes(img, total_boxes):for i in range(total_boxes.shape[0]):r = random.randint(0, 255)g = random.randint(0, 255)b = random.randint(0, 255)x1 = int(total_boxes[:,0][i])y1 = int(total_boxes[:,1][i])x2= int(total_boxes[:,2][i])y2 = int(total_boxes[:,3][i])img = cv2.rectangle(img,(x1,y1),(x2,y2), (r,g,b), 2)return img

运行结果如下:

将PNet预测结果进行筛选和回归,

结果绘制在图片上:

img = Image.open(image_path)
img = np.array(img)
Image.fromarray(draw_bboxes(img,total_boxes))
total_boxes=np.empty((0,9))
pick = nms(boxes.copy(), 0.7, 'Union')if boxes.size>0 and pick.size>0:boxes = boxes[pick,:]total_boxes = np.append(total_boxes, boxes, axis=0)
print("筛选之后结果为:"+str(total_boxes.shape))
# 绘制筛选后的边界框
img = Image.open(image_path)
img = np.array(img)# 进行nms计算 参数为0.7
pick = nms(total_boxes.copy(), 0.6, 'Union')
total_boxes = total_boxes[pick,:]
print(total_boxes.shape)# 边界框回归
regw = total_boxes[:,2]-total_boxes[:,0]
regh = total_boxes[:,3]-total_boxes[:,1]
qq1 = total_boxes[:,0]+total_boxes[:,5]*regw
qq2 = total_boxes[:,1]+total_boxes[:,6]*regh
qq3 = total_boxes[:,2]+total_boxes[:,7]*regw
qq4 = total_boxes[:,3]+total_boxes[:,8]*regh
total_boxes = np.transpose(np.vstack([qq1, qq2, qq3, qq4, total_boxes[:,4]]))
print(total_boxes.shape)
img = Image.open(image_path)
img = np.array(img)# 将边界框形状转为正方形
total_boxes = rerec(total_boxes.copy())
print(total_boxes)# 将边界框坐标整理成整数
total_boxes[:,0:4] = np.fix(total_boxes[:,0:4]).astype(np.int32)
print(total_boxes)
dy, edy, dx, edx, y, ey, x, ex, tmpw, tmph = pad(total_boxes.copy(), w, h)img = Image.open(image_path)
img = np.array(img)
Image.fromarray(draw_bboxes(img,total_boxes))

运行结果如下:

运行RNet

MTCNN的PNet计算结束后,可以看到已经有若干个边界框已经被预测出来。接下来我们将进行RNet预测,通过RNet预测之后,边界框将更加准确。

numbox = total_boxes.shape[0]
tempimg = np.zeros((24,24,3,numbox))
for k in range(0,numbox):tmp = np.zeros((int(tmph[k]),int(tmpw[k]),3))tmp[dy[k]-1:edy[k],dx[k]-1:edx[k],:] = img[y[k]-1:ey[k],x[k]-1:ex[k],:]if tmp.shape[0]>0 and tmp.shape[1]>0 or tmp.shape[0]==0 and tmp.shape[1]==0:tempimg[:,:,:,k] = imresample(tmp, (24, 24))else:print(0)
tempimg = (tempimg-127.5)*0.0078125
tempimg1 = np.transpose(tempimg, (3,1,0,2))
with tf.Graph().as_default():with tf.Session() as sess:with tf.variable_scope('rnet'):data = tf.placeholder(tf.float32, shape=(None, 24, 24, 3), name="input")rnet = RNet({'data':data})rnet.load("./src/align/RNet.npy", sess)out = sess.run(('rnet/conv5-2/conv5-2:0', 'rnet/prob1:0'), feed_dict={'rnet/input:0':tempimg1})# 检测到的人脸坐标
out0 = np.transpose(out[0])
out1 = np.transpose(out[1])score = out1[1,:]
threshold = 0.7
ipass = np.where(score>0.2)
total_boxes = np.hstack([total_boxes[ipass[0],0:4].copy(), np.expand_dims(score[ipass].copy(),1)])
mv = out0[:,ipass[0]]
if total_boxes.shape[0]>0:pick = nms(total_boxes, threshold, 'Union')total_boxes = total_boxes[pick,:]print(total_boxes)img = Image.open(image_path)
img = np.array(img)from src.align.detect_face import bbreg
# 边界框回归
total_boxes = bbreg(total_boxes.copy(), np.transpose(mv[:,pick]))
print(total_boxes)
# 边界框整理成正方形
total_boxes = rerec(total_boxes.copy())
print(total_boxes)img = Image.open(image_path)
img = np.array(img)
Image.fromarray(draw_bboxes(img,total_boxes))

运行结果如下:

运行ONet

最后,我们进行ONet预测,不仅使人脸的边界框检测更加准确,这一步还将关键点检测出来。

numbox = total_boxes.shape[0]
total_boxes = np.fix(total_boxes).astype(np.int32)
dy, edy, dx, edx, y, ey, x, ex, tmpw, tmph = pad(total_boxes.copy(), w, h)tempimg = np.zeros((48,48,3,numbox))
for k in range(0,numbox):tmp = np.zeros((int(tmph[k]),int(tmpw[k]),3))tmp[dy[k]-1:edy[k],dx[k]-1:edx[k],:] = img[y[k]-1:ey[k],x[k]-1:ex[k],:]if tmp.shape[0]>0 and tmp.shape[1]>0 or tmp.shape[0]==0 and tmp.shape[1]==0:tempimg[:,:,:,k] = imresample(tmp, (48, 48))else:print(0)
tempimg = (tempimg-127.5)*0.0078125
tempimg1 = np.transpose(tempimg, (3,1,0,2))
with tf.Graph().as_default():with tf.Session() as sess:with tf.variable_scope('onet'):data = tf.placeholder(tf.float32, shape=(None, 48, 48, 3), name="input")onet = ONet({'data':data})rnet.load("./src/align/ONet.npy", sess)out = sess.run(('onet/conv6-2/conv6-2:0', 'onet/conv6-3/conv6-3:0', 'onet/prob1:0'), feed_dict={'onet/input:0':tempimg1})# 人脸区域边界框预测结果
out0 = np.transpose(out[0])
# 人脸关键点预测结果
out1 = np.transpose(out[1])
# 人脸区域置信度
out2 = np.transpose(out[2])score = out2[1,:]
points = out1
# threshold = 0.7
ipass = np.where(score>0.7)
points = points[:,ipass[0]]
total_boxes = np.hstack([total_boxes[ipass[0],0:4].copy(), np.expand_dims(score[ipass].copy(),1)])
mv = out0[:,ipass[0]]w = total_boxes[:,2]-total_boxes[:,0]+1
h = total_boxes[:,3]-total_boxes[:,1]+1
points[0:5,:] = np.tile(w,(5, 1))*points[0:5,:] + np.tile(total_boxes[:,0],(5, 1))-1
points[5:10,:] = np.tile(h,(5, 1))*points[5:10,:] + np.tile(total_boxes[:,1],(5, 1))-1
if total_boxes.shape[0]>0:total_boxes = bbreg(total_boxes.copy(), np.transpose(mv))pick = nms(total_boxes.copy(), 0.7, 'Min')total_boxes = total_boxes[pick,:]points = points[:,pick]
img = Image.open(image_path)
img = np.array(img)r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)point_color = (r, g, b) for i in range(5):cv2.circle(img,(int(points[i]),int(points[i+5])),1, point_color, 4)Image.fromarray(draw_bboxes(img,total_boxes))

运行结果如下:

5

5.SSR-Net模型预测年龄

我们使用SSR-Net模型预测年龄:

首先我们将模型结构和权重加载,预训练模型位置存储在weight_file中。

from SSRNET_model import SSR_netweight_file = "./ssrnet_3_3_3_64_1.0_1.0.h5"img_size = 64
stage_num = [3,3,3]
lambda_local = 1
lambda_d = 1
model = SSR_net(img_size,stage_num, lambda_local, lambda_d)()
model.load_weights(weight_file)

运行结果如下:

模型层级结构,运行下面代码,可查看模型的各层级结构:

model.summary()

运行结果如下:

准备输入数据:

faces = np.empty((len(detected), img_size, img_size, 3))
faces.shape

运行结果如下:

获取人脸区域图片,并缩放

将人脸检测结果进行裁剪和缩放

ad = 0.4img_h, img_w, _ = np.shape(img)for i,d in enumerate(detected):if d['confidence'] >=0.95 :x1,y1,w,h = d['box']x2 = x1 + wy2 = y1 + hxw1 = max(int(x1 - ad * w), 0)yw1 = max(int(y1 - ad * h), 0)xw2 = min(int(x2 + ad * w), img_w - 1)yw2 = min(int(y2 + ad * h), img_h - 1)img = cv2.resize(img[yw1:yw2+1, xw1:xw2+1, :], (img_size, img_size))faces[i,:,:,:] = imgres_img = Image.fromarray(img)
res_img

运行结果如下:

预测年龄

将人脸区域图片输入模型,获得预测结果

res = model.predict(faces)
print("预测年龄为:"+str(int(res[0])))

运行结果如下:

至此,年龄预测实验结束。

最后,大家使用的云端资源记得全部删除或停用,如本次实验的Notebook开发环境,实验结束后记得停用或删除,以免造成不必要的花费。

6

6.实验小结

通过本次实验,学习到的是如何在华为云ModelArts的Notebook开发环境中使用MTCNN模型进行人脸区域检测,同时学习了如何使用SSR-Net模型预测年龄,并且学习了如何在华为云ModelArts的Notebook开发环境中调试代码。

如果大家对结果不太满意,可以试着在代码中进行调参,以提高检测的精确度,或者试着用你的照片来检测一下,看看你的预测年龄。

文中涉及到的MTCNN模型,SSR-Net模型的论文,以及代码已经整理完毕。

可后台回复“年龄预测

获取上述资源。

如果看了这么多,您也想体验一下华为云AI的魅力,可点击下方[阅读全文]活动链接,参加已于5月18日开始的

《2020|华为云AI实战营》

与华为云技术专家和全国华为云AI爱好者们一起领略华为云AI魅力,让你轻松Get AI技能,获取丰厚的奖品,一起升级打怪,变成最好的自己。

风里雨里,华为与我,在等你!

华为,中国骄傲!中华有为!

往期回顾

【玩转华为云】这个夏日,我与华为云青年班AI实战营的遇见

华为加油,中国加油!

欢迎各位读者在下方进行提问留言

☆ END ☆

你与世界

只差一个

公众号

扫描上方二维码,获取千元“编程学习资料”大礼包

【玩转华为云】手把手教你利用ModelArts实现人脸年龄预测相关推荐

  1. 【玩转华为云】手把手教你利用ModelArts识别偶像的声音

    本篇推文共计2000个字,阅读时间约3分钟. 华为云-华为公司倾力打造的云战略品牌,2011年成立,致力于为全球客户提供领先的公有云服务,包含弹性云服务器.云数据库.云安全等云计算服务,软件开发服务, ...

  2. 【玩转华为云】手把手教你利用ModelArts实现垃圾自动分类

    本篇推文共计2000个字,阅读时间约3分钟. 华为云-华为公司倾力打造的云战略品牌,2011年成立,致力于为全球客户提供领先的公有云服务,包含弹性云服务器.云数据库.云安全等云计算服务,软件开发服务, ...

  3. 【玩转华为云】手把手教你利用ModelArts实现数据集的图像标注

    本篇推文共计2000个字,阅读时间约3分钟. 华为云-华为公司倾力打造的云战略品牌,2011年成立,致力于为全球客户提供领先的公有云服务,包含弹性云服务器.云数据库.云安全等云计算服务,软件开发服务, ...

  4. 华为表哥手把手教你利用Jenkins持续集成iOS项目,教不会我花式拉翔!!!

    手把手教你利用Jenkins持续集成iOS项目: 前言 众所周知,现在App的竞争已经到了用户体验为王,质量为上的白热化阶段.用户们都是很挑剔的.如果一个公司的推广团队好不容易砸了重金推广了一个APP ...

  5. 【玩转华为云】手把手教你用Modelarts实现猫狗数据集的智能标注

    本篇推文共计2000个字,阅读时间约3分钟. 华为云-华为公司倾力打造的云战略品牌,2011年成立,致力于为全球客户提供领先的公有云服务,包含弹性云服务器.云数据库.云安全等云计算服务,软件开发服务, ...

  6. 手把手教你利用 python 爬虫分析基金、股票

    手把手教你利用 python 爬虫分析基金.股票 文章目录 手把手教你利用 python 爬虫分析基金.股票 第一步:基金数据爬取 第二步:股票增持计算 第三步:好股基金选取 桌面程序 exe 从前大 ...

  7. jade怎么查计算机用户名,干货 | 黄继武老师手把手教你利用Jade进行物相检索

    原标题:干货 | 黄继武老师手把手教你利用Jade进行物相检索 前言 Jade是一个32位Windows程序,用于处理X射线衍射数据.除基本的如显示图谱.打印图谱.数据平滑等功能外,主要功能有物相检索 ...

  8. 华为云计算机玩游戏,华为云电脑到底能不能玩游戏?体验一下绝地求生游戏效果...

    华为云电脑到底能不能玩游戏?华为云电脑说白了其实就是一个整合了云桌面服务系统的APP应用.可以下载在手机和平板上使用.可以兼容windows系统生态下的所有应用软件,使用基本和Windows系统一样. ...

  9. 华为云计算机玩游戏,华为云电脑玩游戏怎么样?华为云电脑玩游戏卡吗?

    华为云电脑本质上就是一台个人电脑,当然可以玩游戏啊.我玩一些小型的在线游戏,QQ斗地主,四川麻将,体验还不错. 但是大型游戏,3D游戏等,需要GPU显卡的支持,2018年的时候华为云电脑还没配置GPU ...

最新文章

  1. python文本关键词匹配_NLP利剑篇之模式匹配
  2. word2vec相似度计算_文档相似度助力搜索引擎
  3. (原创)无废话C#设计模式之二十二:总结(针对GOF23)
  4. 不缺流量却变现乏力?穿山甲重磅打造《App 如何变现创收》系列课程帮你找症结...
  5. JavaScript设计一个框架
  6. 【路径规划】基于matlab RRT算法求解机器人避障路径规划问题【含Matlab源码 319期】
  7. A certificate chain processed, but terminated in a root certificate which is not trusted...
  8. debian linux ntfs,让Debian支持ntfs文件系统读写
  9. 新版Burp Suite全模块详细使用篇<宝藏文> -- 小黑渗透工程栈(工具篇2)
  10. 弗兰克赫兹实验计算机仿真实验报告,大学物理实验
  11. 计算机怎么更换硬盘,如何更换电脑新硬盘无需重装系统_换硬盘不重装系统方法...
  12. PS证件照排版计算器
  13. Android原生OS风格ROM包,小米5 的LineageOS14.1刷机包 安卓7.1.1原生风格 20180203更新
  14. Docker的安装部署及优化详解(汇总版,学习docker这一篇就够了)
  15. SEO优化_网站诊断分析方法
  16. glibc 知:手册14:文件系统接口
  17. 外贸软件之纯贸易外贸管理软件
  18. 人工智能OCR文字识别研究
  19. 一个桔子功效等同五味药
  20. 郭嘉的十胜论与诸葛亮的隆中对比较分析

热门文章

  1. 小程序之相对定位与绝对定位
  2. 小编任性,今天就送机械键盘给你!
  3. 微服务系列 - 转贴: 看来微服务就是一把双刃剑
  4. Nik Collection 4都包含那些功能的软件
  5. 华为诺亚ViG架构媲美CNN、Transformer,图神经网络也能用作CV骨干模型
  6. 入手Hi nova9 Pro一周,你们关心的问题都在这里
  7. java 命令行 生成exe_超星尔雅中国古建筑文化与鉴赏期末答案
  8. 【web开发网页制作】Html+Css网页制作关于我的家乡(6页面)【附源码下载】
  9. 什么是绝对路径,什么是相对路径,绝对路径和相对路径的区别?
  10. 图片编辑软件分享!图片编辑软件大合集。​