实验六 图像分割
数据分割是由图像处理到图像分析的关键步骤,是图像识别和计算机视觉至关重要的预处理,图像分割后提取的目标可用于图像识别、特征提取,图像搜索等领域。图像分割的基本策略主要是基于图像灰度值的两个特性,即灰度的不连续性和灰度的相似性,因此图像分割方法可分为基于边缘的分割方法和基于区域的分割方法。本次实验通过完成简单的图像分割进一步加深对图像分割的理解。
一、实验目的
进一步掌握MATLAB程序设计方法;
巩固图像分割理论与方法;
编程实现图像分割,比较基于阈值分割方法和基于边缘分割方法的效果,分析影响分割效果的因素。
二、实验基础
1.基于阈值的分割
基于阈值的分割属于区域分割的一种,是图像分割中最常用的一类方法,对于一个具有双峰分布的简单图像阈值分割方法,实际上是将输入图像f(i,j)通过变换得到输出图像g(i,j)的过程,即二值化过程。
阈值分割方法的关键是阈值T的确定,如果能确定一个合适的阈值,就可以准确地将图像分割开来,对于灰度直方图具有双峰分布的图像。可以选择古典处的灰度值作为阈值,在许多情况下物体和背景的对比度在图像中的各处是不同的,很难用一个统一的阈值将物体与背景分开。此时可以根据图像的局部特征分别采用不同的阈值进行分割。并分割的方法包括判断分析法,最佳熵自动阈值法,最小误差分割等。
阈值分割的优点是直观计算简单,运算效率较高,速度快。
2.基于边缘的分割
图像分割的另一种方式是通过边缘检测时限的边缘是指通过中像素灰度有阶跃或屋顶变化的像素级和边缘能勾画出物体轮廓,对图像识别和分析十分有用,是图像识别时提取的重要信息,由于边缘处的灰度是不连续的,因此可以利用边缘检测算子将边缘点检测出来,常用的边缘检测算子有梯度算子、Prewitt算子、Sobel算子、LOG算子和Canny算子等。
通过edge函数可以利用各种边缘检测算子检测图像边缘。
3.边缘跟踪
将检测的边缘点连接成线称为边缘跟踪,在识别图像中的目标时,往往需要对目标边缘做跟踪处理,即按一定顺序找出边缘点来绘制出编辑,如果图像是二值图像或图像中不同区域具有不同的像素值,但每个区域内的像素只是相同的,则可以完成基于四联通或八连通区域的轮廓跟踪。
利用bwtraceboundary函数可以在二值图像中追踪目标的轮廓线。
4.Hough变换检测
Hough变换是Paul Hough于1962年提出,是图像处理技术中用于识别几何形状的一种常用方法,它实现了一种从图像空间到参数空间的映射关系。Hough变换的基本原理是利用点线间的对偶性,将原始图像空间的给定曲线通过曲线表达形式变换成为参数空间的一个点。
MATLAB中常用的关于Hough变换的函数有:hough、houghpeaks和houghline。
三、实验仪器及设备
计算机、Matlab图像处理软件、待处理图像
四、实验内容及步骤
- 熟悉MATLAB中相关函数,掌握各函数的具体用法
(1)edge:边缘检测函数。
BW = edge(I)
采用灰度或一个二值化图像I作为它的输入,并返回一个与I相同大小的二值化图像BW,在函数检测到边缘的地方为1,其他地方为0。
BW = edge(I,'sobel') 自动选择阈值用Sobel算子进行边缘检测。
BW = edge(I,'sobel',thresh) 根据所指定的敏感度阈值thresh,用Sobel算子进行边缘检测,它忽略了所有小于阈值的边缘。当thresh为空时,自动选择阈值。
BW = edge(I,'sobel',thresh,direction) 根据所指定的敏感度阈值thresh,在所指定的方向direction上,用Sobel 算子进行边缘检测。Direction可取的字符串值为horizontal(水平方向)、vertical(垂直方向)或both(两个方向)。
[BW,thresh] = edge(I,'sobel',...) 返回阈值
(2)graythresh:利用Otsu算法(最大类间方差)获取全局阈值。
(3)im2bw:将灰度影像转换为二值图像。
(4)bwtraceboundary:在二值图像中追踪目标轮廓线。
help bwtraceboundary
bwtraceboundary Trace object in binary image.
B = bwtraceboundary(BW,P,FSTEP) traces the outline of an object in a binary image BW, in which nonzero pixels belong to an object and 0-pixels constitute the background. P is a two-element vector specifying the row and column coordinates of the initial point on the object boundary. FSTEP is a string or char vector specifying the initial search direction for the next object pixel connected to P. FSTEP can be any of the following strings or char vectors: 'N','NE','E','SE','S','SW','W','NW', where N stands for north, NE stands for northeast, etc. B is a Q-by-2 matrix, where Q is the number of boundary pixels for the region. B holds the row and column coordinates of the boundary pixels.
B = bwtraceboundary(BW,P,FSTEP,CONN) specifies the connectivity to use when tracing the boundary. CONN may be either 8 or 4. The default value for CONN is 8. For CONN equal to 4, FSTEP is limited to 'N','E','S' and 'W'.
B = bwtraceboundary(...,N,DIR) provides the option to specify the maximum number of boundary pixels, N, to extract and direction, DIR, in which to trace the boundary. DIR can be either 'clockwise' or 'counterclockwise'. By default, or when N is set to Inf, the algorithmextracts all of the pixels from the boundary and, if DIR is not specified, it searches in the clockwise direction.
(5)hough:Hough变换函数。
1.hought函数
语法:[H, theta, rho] = hough(BW)
[H, theta, rho] = hough(BW, ParameterName, ParameterValue)
描述:[H, theta, rho] = hough(BW)计算二值图像BW的标准hough变换。函数返回的H称为hough转换矩阵。theta和rho是一维数组,theta记录径,rho记录角度。BW可以是逻辑型,也可以是数值型。
(6)houghpeaks:Hough变换峰值识别。
peaks = houghpeaks(H, NumPeaks)
peaks = houghpeaks(..., 'Threshold', val1, 'NHoodSize', val2)
其中,"…"指出来自默认语法和peaks的输入是持有峰值行和列坐标的Q×2大小的矩阵。Q的范围是0到NumPeaks,H是霍夫变换矩阵。参数val1是非负的标量,指定了H中的什么值被考虑为峰值;val1可以从0到Inf变化,默认值是0.5*max(H(:))。参数val2是奇整数的两元素矢量,指定量围绕峰值的邻域大小。
(7)houghline:基于Hough变换提取线元。
lines = houghlines(f, theta, rho, peaks)
lines = houghlines(..., 'FillGap', val1, 'MinLength', val2)
其中,theta和rho是来自函数hough的输出,peaks是函数houghpeaks的输出。输出lines是结构数组(可能检测到多条直线),长度等于找到的线段数。结构中的每个元素可以看成一条线,并含有下列字段:
point1:两元素向量[r1, c1],指定了线段起点的行列坐标。
point2:两元素向量[r2, c2],指定了线段终点的行列坐标。
theta:与线相关的霍夫变换的以度计量的角度。
rho:与线相关的霍夫变换的ρ轴位置。
其他参数如下:
val1是正的标量,指定了与相同的霍夫变换相关的两条线段的距离。当两条线段之间的距离小于指定的值时,函数houghlines把线段合并为一条线段(默认的距离是20个像素)。参数val2是正的标量,指定合并的线是保留还是丢弃。如果合并的线比val2指定的值短,就丢弃(默认值是40)。
- 简单图像的阈值分割
(1)利用直方图进行阈值分割
图一 阈值分割
(2)利用最大类间方差自动确定阈值进行分割
图二 最大类间方差
3. 基于边缘的阈值分割
(1)利用各种边缘检测算子检测边缘
图三 边缘算子
思考:比较不同
Roberts算子检测方法对具有陡峭的低噪声的图像处理效果较好,但是利用roberts算子提取边缘的结果是边缘比较粗,因此边缘的定位不是很准确。
Sobel算子检测方法对灰度渐变和噪声较多的图像处理效果较好,sobel算子对边缘定位不是很准确,图像的边缘不止一个像素。
Prewitt算子检测方法对灰度渐变和噪声较多的图像处理效果较好。但边缘较宽,而且间断点多。
Laplacian算子法对噪声比较敏感,所以很少用该算子检测边缘,而是用来判断边缘像素视为与图像的明区还是暗区。
Canny方法不容易受噪声干扰,能够检测到真正的弱边缘。优点在于,使用两种不同的阈值分别检测强边缘和弱边缘,并且当弱边缘和强边缘相连时,才将弱边缘包含在输出图像中。
(2)边缘跟踪(bwtraceboundary)函数
图四 边缘跟踪
思考:通过修改起始点的横纵坐标,可以改变找到的硬币边缘。
- Hough变换检测线段
clc;clear;
i=imread('circuit.tif');
i1=imrotate(i,30,'crop');%用crop方式显示,旋转后的图像跟原图像大小一样,多余的地方舍去
bw=edge(i1,'canny');
subplot(2,3,1);imshow(i);xlabel('原始图像');
subplot(2,3,2);imshow(i1);xlabel('旋转后的图像');
subplot(2,3,3);imshow(bw);xlabel('边缘检测图像');
[H,theta,rho] = hough(bw);%利用hough函数进行hough变换
subplot(2,3,4);hold on;imshow(imadjust(mat2gray(H)),[],'XData',theta,'YData',rho,'Initialmagnification','fit');
title('峰值检测');
xlabel('\theta(degrees)');ylabel('\rho');
axis on,axis normal,hold on
P=houghpeaks(H,10,'threshold',ceil(0.3*max(H(:))));
x=theta(P(:,2));
y=rho(P(:,1));
plot(x,y,'s','color','red');
lines=houghlines(bw,theta,rho,P,'FillGap',5,'MinLength',7);
subplot(2,3,5),imshow(i1);title('检测到的线段');hold on;
max_len=0;
for k=1:length(lines)
xy=[lines(k).point1;lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'color','green');
%绘制线段起终点
plot(xy(1,1),xy(1,2),'LineWidth',2,'color','yellow');
plot(xy(2,1),xy(2,2),'LineWidth',2,'color','blue');
%确定最长线段的端点
len=norm(lines(k).point1-lines(k).point2);
if(len>max_len)
max_len=len;
xy_long=xy;
end
end
%突出显示最长一条直线
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'color','red');
图五 hough变换
五、实验心得体会
- 图像分割是图像处理的重要步骤之一,在图像分割过程中算法是其主要的手法之一,但是每种算法有每种算法的特点,它的运行成果也行差万别。
- 实验中算法的编写总是出现各种各样的错误,经过细心的检查和耐心的改正错误基本都会改正错误。类型大致可分为:语法错误,函数调用,错误函数无法调用等类型。
Original: https://blog.csdn.net/chengzilhc/article/details/124556845
Author: nochengzi
Title: 数字图像处理:实验六 图像分割
相关阅读1
Title: 语音识别热词_TICA 2019 小爱同学语音识别评测
阿里QA导读:小米AI智能音响小爱同学,大家都听说过吧?你可以对它说"小爱同学,播放周杰伦的晴天,小爱同学,我要吃麦当劳",那小爱同学是经历了怎样的测试才与大家见面的呢?
大家好,我是董沐,今天很高兴来到IoT&线下智能专场来聊一下我们的工作。我来自小米人工智能智能部的小爱同学团队,是一位研发同学,主要是做一些工程效率平台的开发以及语音算法的评测,今天我主要从语音识别的点来展开聊我们具体是怎么做评测的。今天的内容主要是讲语音识别这块,语音识别也简称为ASR,为了简便之后我就叫ASR。我的分享包括以下三部分:第一部分,ASR是什么;第二部分,ASR模型评测;第三部分,全流程的ASR质量保证。
Part1 ASR是什么
在开始之前,我认为有必要认识一下小爱同学。
小爱同学是一个机器人,可以搭载在音响、电视、手环以及各种各样的设备上,小爱同学搭载的一个最奇葩的产品是马桶盖。小爱同学上有各种各样的技能,可以让它发微信、播放音乐等等。我昨天从北京过来的时候,就问小爱同学,明天要去杭州需要穿秋裤吗,小爱同学说你穿上吧,杭州明天挺冷的,我今天确实穿上了秋裤,确实好冷。
我们可以看到,小爱同学其实是有和用户做这样的语音类型的交互。那么,我们会比较好奇这里面究竟发生了什么事情?我们看一下整个交互的过程,最开始是唤醒,唤醒是发生在本地,不是发生在服务端的,用户说了"小爱同学",小爱同学和用户说"我在",后面的三个模型分别:一是ASR(语音识别),二是NLP(自然语音处理),三是TTS(语音播报)。以上是整个和小爱同学交互的过程。
我今天就专门讲一下语音识别的评测过程,其实刚才已经看到了,用户可以和小爱同学说任何的话,它的输入是无线的,那么,我们怎样实现无线输入的功能呢?
我们一般会借助人工智能模型,我们来看一下模型的训练过程,首先要准备一些训练的数据,组成迅速集,去把这些模型经过一些训练得到一些输出。这个输出和标注做一些对比,看看误差值是多少,然后反复调整参数,得到一个我们足够满意的误差值,这样的模型就训练完成了,训练完成的模型就可以处理它没有见过的一些新数据了。实际上,训练过程比这个复杂的多,但是今天不是讲怎么去训练模型,只是想通过这个过程发现几个点:第一点,要知道模型处理的一些输入的数据全是在它的训练过程中没有见过的数据。第二点,我们训练的过程中是非常复杂的,没有办法通过检查一些模型内部的流程,我们找不到这样的东西,没有办法通过一些简单的逻辑对它进行修复和更换。第三点,我们可以看到它最终还是有一个误差值,它的loss可以非常小,但是无论它怎么小,也总是存在的。也就是说,ASR的模型哪怕再好,总有很多的情况是识别不到的。那么,实际上对于输入来说,它还有一个特点,哪怕是同一个人对小爱同学说一句话,比如说今天星期几这样很简单的话,但是因为你每次说话的时候,你的语音、语调、停顿都不太一样,就导致每次录出来的音频是完全不一样的,所以说ASR的识别可能还有一个特点,哪怕是同样一个人说同样一句话,有的时候可能识别对,有的时候可能识别错。
更麻烦的情况是在很多情况下,我们拿到的输入音频可能就是不正确的,举个例子,比如说有些用户有很重的地方口音,还有一些用户的发音是不标准的,甚至说一些大白字,还有一些时候是因为录音的质量问题,导致输入的音频是有很大的一些背景杂音的,有可能是前端的一些硬件设备损坏了。还有一些情况是用户和小爱同学输入的时候,同时背景还有其他人的声音在说话,就会把用户的指令和其他的人声叠加在一起,这样是很难区分开来。我们在碰到以上这些情况的时候,是很难都完全去处理的,只能尽量优化。
第二部分,ASR模型评测
我们看到ASR模型有这样的一些问题,那么我们怎样去衡量它的质量呢?说到质量,我们首先想到的就是测试,我们看一下这个测试在ASR模型上能否行得通。
第一,测试的时候,我们会使用黑盒测试去定义它的输入输出的等价类。第二,你可以在测试的时候使用白盒测试去Chack代码内部的逻辑,但是模型是做不到的。第三,测试的时候,是要测试用力全部通过的,甚至大部分是通过的,至于失败的case会把当成bug去提,而ASR总是有识别错误的,那它很难被完全的修复。
那么,我们怎样去衡量它的质量呢?我们其实是用这样的方式去做的,首先也有一个测试的数据集,这个测试的数据集和训练数据集有点类似,也是有一段音频和标注,标注的就是标注音频说的是什么。评测的数据集和训练的数据集是一定要严格隔离的。怎么做呢?我们有一个数据集,把这个数据集里的音频一个个注入模型,得到好多的结果,最后得到一个有统计意义上的指标项的衡量。我给大家举一个例子,比如说这个数据集一共有一万条语料,我们全部都输入模型,成功识别出九千条,那么我们就说这个数据集在这个模型上的识别率是90%。
再看一下指标,主要的指标有以上四种:字准确率、句准确率、响应时间、场景完成率。以上这些指标,一般最看重的起来字准确率,因为有时候一句话识别错一个字,可能整个意思都走样了。比如说用户说"12×34",如果你识别成"12÷34",只是一个字的区别,整个意思都变了,小爱同学再聪明也不可能把用户的用意理解对。前面我们说过了评测是基于数据集做出的一个统计意义上的结果,那么我们用什么样的数据集去做评测,就会得到模型在哪方面能力上的体现。
我们使用什么样的数据集呢?分为以下几类:一是通用数据集。它的搜集方式就是随机从线上取若干条query,目的是衡量模型的普适性。这个数据集是我们最重要的数据集,我们只需要把线上的数据进行定期取样、定期更新通用数据集,就可以衡量大概用户实际请求时的体验。二是高频数据集。这个数据集取的是线上请求频次最高的TOP1000的query,每个query取若干条,这个数据集是衡量模型对于头部请求的稳定性。经过我们一些数据上的分析,发现不同设备上TOP1000的query会覆盖到整体场景的40%-60%,也就是说如果你把这1000个query好好处理了,至少有接近一半的场景都可以被高频的数据集覆盖。换句话说,如果高频的数据集出了问题,那一定是要集中精力去修复的。三是Bad Case数据集。主要是通过用户反馈、数据挖掘找出用户实际发生的错误,用于发现模型的共性问题。四是特殊场景数据集。包括中英文混合、强背景音、方言、纯英文、小声耳语、空音频等,用于衡量模型在特定场景下的表现,为不同的设备选择模型提供依据。五是专项数据集。打电话、打开应用、导航、时间等,用来衡量用户在特定操作时的表现。比如说,我们有一个车载的导航设备,我们给它挑选模型的时候就一定会选择在导航数据集上表现比较好的模型。
实际上,我们在设备选择模型的时候,除了去关注它在一些特定数据集上的表现,其实也要考虑到它是多通道的设备还是一般通道的设备,因为这些对模型的训练来说都是需要单独训练的,所以我们在准备数据集的时候也一定是要严格按照这些维度切开的。
最后,我们就给这个设备选择一个合适的模型,然后把这个设备上线以后,也会定期从线上搜集一些数据,过所有的模型,看看我们之前选择的模型是否是正确的,如果有更好的识别模型,我们会进行更换。接下来讲一下模型的发布和监控。模型训练完成以后,会过自动化的上线验收评测,实验室如果评测没有问题的话,会交给人工盲测,可能交给一些手工测试的人去做一些体验,这个体验主要是为了避免人的主观体验和实验室的动态结果有冲突的情况发生。如果这三方面的评测都没有问题的话,就要有一个小流量的发布,在发布期间,会在线上搜集一些流量进行抽查,看看识别的准确率有没有下降,如果没有问题会进行全量的发布,监控线上的场景,随机取一些数据作为通用数据集的语料。
我们做过质量的同学都知道,有的时候已经做了很充分的测试、评测,可是一到上线的时候还是会遇到很多突发的情况。我们现在遇到的一些主要突发情况是这样的,就是有些高频的Bad case以及运营临时起的什么样的活动,还有新歌星、新电影等。我举个例子,当时很火的一个电影叫《西虹市首富》,我们在训练模型的时候并没有"西虹市"这三个字,所以在它训练的时候就没有加到语言模型里去,这个模型无论如何都不可能识别对。我们遇到这些情况,会做一个干预的规则,把以前识别错的西虹市首富印射到对的西虹市首富的结果中去,通过这样的印射保证用户体验到的query是正确的。
另外,我们通常会做一些主动的干预,它的做法是我们拿到线上一些高频的词汇,包括即将发布的电影,我们把这些词汇拿到以后,通过TTS模型组成一个音频,然后这个音频注入ARS模型,这样就会找到那些识别错误的热词,我们都会找到。我们找到这些热词之后,可以断定这些热词应该没有加入ASR模型规则里去,然后我们通过相关日志去请求以下错误的高频句式,把它自动加入到ASR的规则里,这样就能够保证不发模型还不会影响用户的体验。
我们整个的评测系统是这样的,最开始是一个数据的平台,这个数据的平台主要做一些Bad case这样的一些数据挖掘,包括爬取一些榜单、新歌以及新电影等等,也有运营的同学进行标注,然后会分发给其他的一些平台,说这样是什么样的问题,给到ASR模型,它还会抽取各个方面的一些数据,把它进行一个标准的格式化。ASR评测部分。它首先有一些数据集的管理,有数据集不行,还要有标注,方便标注同学进行人工标注。还有一个每日评测,就是监控线上目前质量的评测过程,接下来就是评测的主要计算。在ASR的评测都是基于客户端去做的,ASR评测的时候还要管理这些客户端,对评测的任务进行调度,还有就是结果的一些对比和展示。还有,ASR的评测里需要集成一些外部的平台数据导入进来,一起展示出来。它还有两个ASR干预的流程,包括人工添加的干预规则,就是人工审核,还有干预自动的回传。关于干预的规则,比如说一个运营活动到期了就下线了,或者人工发现这个东西不合理,可能会人工下限等等,如果这个干预规则命中的太少了,也会有问题。最后是一些效率工具,包括问题的定位和回放,还有一些音频的处理和转化的平台。第三部分,全流程的ASR质量保证。ASR评测只是保证语音识别整体流程中的一部分,我们想看一下除了做ASR模型评测之外,如何保证语音识别的质量,还需要做哪些事情。
ASR质量保证
大家有没有注意到,这是小爱同学3.0的宣传片,在这里面有一个全声控的功能,就是我们发现最明显的一点,就是之前用户唤醒一次小爱同学,用户输入一次指令,小爱同学回答一次,这个流程就结束了。但是现在不是这样的,你会看到很多场景下用户只要唤醒一次,用户会连续和小爱同学说一些很多的指令,说指令1、指令2、指令3、指令4,其实对于整个识别来说,它的挑战有很多。举个例子,用户在下一个指令有可能和小爱同学之前的TTS叠合在一起,形成了我们之前提到的多人对话的场景,这个场景是很难被识别成功的。还有一点就是小爱同学可能在前端需要去判断用户有没有开始/结束指令,如果小爱同学判断你已经开始了,小爱同学可能就少说点话,或者它判断用户指令已经结束了,它就会尽快回答你,等于它要及时看开始和结束,才能给ASR模型一个正确的输入。我们怎么去解决这几个问题?
先看第一个问题,小爱同学回答和用户的指令叠加到一起。其实实际的做法是这样的,在小爱同学的前端有一个前端的AEC模块,这个算法模型主要是过滤到噪声和杂音,也会过滤掉一些回声,当然我们在全声控的场景下也要过滤掉小爱同学自己的TTS。我们通过AEC过滤小爱同学自己的TTS,保证了ASR模型得到的是一个正确的输入。
除了在前端去做AEC的过滤,在服务端同样还会去做一层过滤,这个服务端过滤的时候就比较强大了。经过两层过滤的话,大致会把小爱同学或者一些其他的背景杂音过滤掉。我们在做这件事情的时候,也会做AEC算法的评测,分别评测前端能够过滤到多少小爱同学TTS,还要看一下云端能够过滤掉多少,再看一下两个模型协同的时候能够过滤掉多少,把这个比重算出来。接下来是我们说的小爱同学的前端需要去判断开始和结束,那么这个功能是通过前端的VAD模型实现的。
简单介绍一下VAD模型的评测,首先,我们会使用大量的音频,让标注同学去标注音频的起始的时间段,这样会有模型开始和结束的时间。我们再算出误识别和漏识别,我们通常会把一个数据集里的误识别和漏识别都加起来,看看是多少。但是我们在实际的过程中,误识别和漏识别在VAD的场景下并不是等价的,比如说对于人声的漏检,相当于你被截断了,这个ASR就没有办法得到正确的输入了,漏检比误检要严重的多,所以说在VAD过程中,漏检和误检不能简单相加。还有一个结果是不同的VAD模型,再过一下ASR模型,看一下ASR能得到正确结果的比重是多少。
由于功能和通道也不一样,我们在保证它的质量的时候,其实也要把模型放到实验室里去评测,评测的维度有可能包括噪声、回声(回声类型、信回比)、空间(空间类型、面积、混响时间)、设备(位置、高度、音量、工作状态)、声源(性别、年龄、距离、角度)等。关于声源,还包括小爱同学自己的声源,我们还是要过滤掉。这些东西有些是在实验室里做,有些是把实验室的数据拿出来做自动回放的评测。
最后,我们看一下全流程的ASR质量保证。在最开始的过程中,是一个录音的过程,这个过程绝大部分是和硬件设备相关的,包括录音的质量、格式的转化、压缩的损失,这些要单独做评测。还有就是设备的前端,刚才讲过的AEC算法和VAD算法的评测,通过前端两个算法的评测,保证ASR模型能够拿到的输入至少是一个正确的。接下来就是我们的语音识别过程,我们会考虑到不同的噪声发生距离、发音的类型,计算一下显示时间。最后是一个结果干预,除了刚才说的ASR干预规则,还要对它的格式进行整理。以上是我的分享,谢谢大家!
关注「阿里巴巴技术质量」阅读更多
Original: https://blog.csdn.net/weixin_39668898/article/details/113037724
Author: weixin_39668898
Title: 语音识别热词_TICA 2019 小爱同学语音识别评测
相关阅读2
Title: Anaconda3和tensorflow2的安装
首先,说一下这篇文章写于2022年1月份,如果你看到这篇文章的时候离这个时间太远,那不建议往下看了(超过一年就不建议看了)
其次,Anaconda的版本是
目前对应的python版本是3.9,tensorflow版本是2.7.0,其实安装完Anaconda后,python和tensorflow的版本我们就无需关心了,一切交给conda就行了
接下来是完整的安装步骤
- 如果你的电脑以前有python,那么把它卸载掉,因为Anaconda是自带python的,避免冲突
- 下载Anaconda的安装包:清华源Anaconda,找到这两个:
根据你的操作系统来选择64或者32位的版本 - 下载完成后双击安装包进行安装
这里的安装路径不要带中文
只勾选下面的那个就行,上面那个如果勾选了,后续使用的时候可能会出现问题
这里等的时间可能会稍微长一点,不要着急
把这两个勾取消就行,不取消的话会自动打开两个网页,是Anaconda的使用教程
- 安装完成后,点击电脑左下角的开始,找到Anaconda Prompt,打开
我是根据这个官方的教程安装的tensorflow:
https://docs.anaconda.com/anaconda/user-guide/tasks/tensorflow/
执行命令,安装CPU版本
conda create -n tf tensorflow
输入y,回车
接下来需要等待一段时间
安装完成后执行
conda activate tf
输入python,进入python环境
执行下列代码,检查是否安装成功
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
hello = tf.constant('hello,tensorflow')
sess= tf.compat.v1.Session()
print(sess.run(hello).decode())
每执行完一行代码,中间可能会输出一些信息,一般不用管,往下输入就行了,看到"hello,tensorflow",说明安装成功
这里只安装了CPU版本,如果想把GPU版本也安装上,可根据上方的官方教程里给出的方法进行安装,方法和GPU版本类似,也是两条指令:
我们可以查看一下自己安装的tensorflow版本:
import tensorflow as tf
print(tf.__version__)
Original: https://blog.csdn.net/qq_53281219/article/details/122308320
Author: leemh1999
Title: Anaconda3和tensorflow2的安装
相关阅读3
Title: React同构直出原理浅析
通常,当客户端请求一个包含React组件页面的时候,服务端首先响应输出这个页面,客户端和服务端有了第一次交互。然后,如果加载组件的过程需要向服务端发出Ajax请求等,客户端和服务端又进行了一次交互,这样,耗时相对较长。服务端是否可以在页面初次加载时把所有方面渲染好再一次性响应给客户端呢?
「React同构直出」就是用来解决这个问题的,做到「秒开」页面。过程大致是这样滴:
1、在需要同构直出的页面(比如是index.html)放上占位符
<div id="root">@@@</div>
###
以上,当客户端发出首次请求,服务端渲染出组件的html内容放@@@这个位置,然后服务端再渲染出类似 <script>renderApp()</script>
这样的js代码段把组件最终渲染到DOM上。也就是说,renderApp方法实际上就是在渲染组件。
2、而为了直接调用renderApp方法,必须让renderApp方法成为window下的方法
window.renderApp = function(){ReactDOM.render(...)}
3、服务端取出index.html,渲染出占位符的内容,替代占位符,并一次性响应给客户端
通过一个例子来体会。
文件结构
browser.js(在这里把渲染组件的过程赋值给window.renderApp)
bundle.js(把browser.js内容bundle到这里)
Component.js(组件在这里定义)
express.js(服务端)
index.html(同构直出的页面)
package.json
index.html,直出页面放上占位符
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
</head>
<body>
<div id="root">@@@</div>
<script src="bundle.js"></script>
###
</body>
</html>
Component.js,在这里定义组件
var React = require('react');
var ReactDOM = require('react-dom');
var Component = React.createClass({
clickHandler: function(){
alert(this.props.msg)
},
render: function(){
return React.createElement('button', {onClick: this.clickHandler}, this.props.msg)
}
})
module.exports = Component;
browser.js,把组件渲染过程赋值给window对象
var React = require('react');
var ReactDOM = require('react-dom');
var Component = React.createFactory(require('./Component'));
window.renderApp = function(msg){
ReactDOM.render(Component({msg: msg}), document.getElementById('root'));
}
可以通过 <script>render()</script>
来触发组件的渲染。稍后,在服务端会把这段代码渲染出来。
express.js,服务端
以上,需要直出的页面有了占位符,定义了组件,并把渲染组件的过程赋值给了window对象,服务端现在要做的工作就是:生成组件的html和渲染组件的js,放到直出页面index.html的占位符位置。
var express = require('express');
var React = require('react');
var ReactDOMServer = require('react-dom/server');
var fs = require('fs');
var Component = React.createFactory(require('./Component'));
//原先把文件读出来
var BUNDLE = fs.readFileSync('./bundle.js',{encoding:'utf8'});
var TEMPLATE = fs.readFileSync('./index.html',{encoding:'utf8'});
var app = express();
function home(req, res){
var msg = req.params.msg || 'Hello';
var comp = Component({msg: msg});
//@@@占位符的地方放组件
var page = TEMPLATE.replace('@@@', ReactDOMServer.renderToString(comp));
//###占位符的地方放js
page = page.replace('###', '<script>renderApp("'+msg+'")</script>')
res.send(page);
}
//路由
app.get('', home);
app.get('/bundle.js', function(req, res){
res.send(BUNDLE);
})
app.get('/:msg', home);
app.listen(4000);
package.json中的配置
"scripts": {
"start": "watchify ./browser.js -o ./bundle.js"
},
运行:npm start
运行:node express.js
浏览:localhost:4000
项目地址:https://github.com/darrenji/ReactIsomorphicSimpleExample
Original: https://www.cnblogs.com/darrenji/p/5649895.html
Author: Darren Ji
Title: React同构直出原理浅析