基於百度AI開放平台的人臉識別及語音合成


基於百度AI的人臉識別及語音合成課題

課題需求

(1)人臉識別
在Web界面上傳人的照片,后台使用Java技術接收圖片,然后對圖片進行解碼,調用雲平台接口識別人臉特征,接收平台返回的人員年齡、性別、顏值等信息,將信息返回到Web界面進行顯示。
(2)人臉比對
在Web界面上傳兩張人的照片,后台使用Java技術接收圖片,然后對圖片進行解碼,調用雲平台接口比對照片信息,返回相似度。
(3)語音識別
在Web頁面上傳語音文件,判斷語音文件格式,如果不是wav格式進行轉碼處理,然后調用平台接口進行識別,最后將識別的文本內容返回到Web界面進行顯示。
(4)語音合成
在Web界面上傳文本內容和語音類型,后台接收文本內容和語音類型后,調用平台接口生成語音數據,最后將數據轉碼成mp3格式文件,Web界面可以下載到本地。

課題設計

課題基於客戶端—服務端-平台端構架,客戶端主要實現功能界面展示、數據上傳和處理結果展示;服務器端接收客戶端數據、數據轉碼處理、平台接口調用、請求結果相應;平台端介紹服務端數據、人臉識別、人臉比對、語音識別、語音合成等。

總體架構

總體邏輯

前端設計(包括首頁、人臉檢測、人臉對比、語音識別及語音合成)

index.html

<!DOCTYPE html>
<html lang="zh-cn">

	<head>
		<meta charset="UTF-8">
		<title>人工智能 未來已來</title>
		<link rel="stylesheet" href="css/button.min.css" />
		<link rel="stylesheet" href="css/style.css" />
		<script type='text/javascript' src='js/jquery-1.11.1.min.js'></script>
		<script type='text/javascript' src='js/jquery.particleground.min.js'></script>
		<script type='text/javascript' src='js/ai.js'></script>
	</head>
	<body>
		<div id="context">
			<div class="intro">
					<div class="position">
                        <h1>人工智能 未來已來</h1>
						<!--start button, nothing above this is necessary -->
						<div class="svg-wrapper">
							<svg height="140" width="450" xmlns="http://www.w3.org/2000/svg">
								<rect id="shape" height="140" width="300" />
								<div id="text">
									<a href="face_recognition.html"><span class="spot"></span>人臉檢測</a>
								</div>
							</svg>
						</div>
						<div class="svg-wrapper">
							<svg height="140" width="450" xmlns="http://www.w3.org/2000/svg">
								<rect id="shape" height="140" width="300" />
								<div id="text">
									<a href="face_match.html"><span class="spot"></span>人臉比對</a>
								</div>
							</svg>
						</div>
						<!--Next button -->
						<div class="svg-wrapper">
							<svg height="140" width="450" xmlns="http://www.w3.org/2000/svg">
								<rect id="shape" height="140" width="300" />
								<div id="text">
									<a href="speech_recognition.html"><span class="spot"></span>語音識別</a>
								</div>
							</svg>
						</div>
						<!--Next button -->
						<div class="svg-wrapper">
							<svg height="140" width="450" xmlns="http://www.w3.org/2000/svg">
								<rect id="shape" height="140" width="300" />
								<div id="text">
									<a href="speech_produce.html"><span class="spot"></span>語音合成</a>
								</div>
							</svg>
						</div>
						<!--End button -->
					</div>
				</div>
		</div>
	</body>
</html> 

face_recognition.html

<!DOCTYPE html>
<html>

	<head>
		<meta charset="utf-8" />
		<title>人臉識別</title>
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<script src="js/jquery-2.1.0.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/jquery.particleground.min.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/ai.js" type="text/javascript" charset="utf-8"></script>
		<link rel="stylesheet" type="text/css" href="css/style.css" />
		<style type="text/css">
			.cent_bg {
				width: 80%;
				height: 22em;
				border: 1px solid rgba(255, 255, 255, 0.5);
				margin: auto;
				padding: 3% 6%;
				border-radius: 10%;
				font-size: 1.5em;
				line-height: 2em;
				position: relative;
			}
			
			.cent {
				margin-top: 1.5em;
				overflow-y: auto;
				height: 80%;
				text-indent: 2em;
				text-align: left;
				padding-right: 0.2em;
			}
			
			
			::-webkit-scrollbar {
				width: 10px;
				background-color: rgba(255,255,255,0.2);
			}
			/*定義滾動條軌道 內陰影+圓角*/
			
			::-webkit-scrollbar-track {
				border-radius: 5px;
				background-color: transparent;
			}
			/*定義滑塊 內陰影+圓角*/
			::-webkit-scrollbar-thumb {
				border-radius: 10px;
				background-color: rgba(255,255,255,0.7);
			}
			
			.btn{
				margin-top: 20px;
				width: 70%;
				height:80px;
				transition: 0.4s;
				border-radius: 1em;
				border: 1px solid rgba(255, 255, 255, 0.5);
				border-top:none;
				z-index: 66;
				background: rgba(255, 255, 255, 0.2);
			}
			.btn:hover{
				border: 1px solid rgba(255, 255, 255, 0.8) !important;
				border-top:none !important;
			}
			
			.btn span{
				width: 40%;
				height: 84%;
				margin-top:6px;
				line-height: 38px;
				display: inline-block;
				border: 1px solid #009FFD;
				color: #fff;
				background: rgba(255,255,255,0.4);
				border-radius: 4px;
				cursor: pointer;
			}
			.btn span:nth-of-type(1){
				margin-right: 15px;
			}
			.btn span:nth-of-type(2){
				margin-left: 15px;
			}
			.img{
			width: 70%;
			height: 100%;
			float: left;
			position: relative;
			}
			.xinxi{
			width: 30%;
			height: 100%;
			float: left;
			}
			.biankuang{
			width: 92%;
			height: 150%;
			top: -100px;
			position: absolute;
			background: url(img/biankuang.png) no-repeat;
			background-size: 100% 100%;
			}
			.xinxi{
			text-align: left;
			}
			.xinxi span{
		    margin-top: 50px;
			}
			.xinxi span a{
			color: #FFFFFF;
			text-decoration: none;
			}
			#neirong{
				color: red;
			}
		</style>
	</head>

	<body>
		<div id="context">
			<div class="intro">
				<div class="cent_bg">
				<div class="img">
				<div class="biankuang">
				<img src="img/img111.jpg" id='img' style="width: 83%;height: 55%;position: absolute;left: 49px;top: 150px;"/>	
				</div>
				</div>
				<div class="xinxi">
				<span style="display: block;">性別:<a href="" id="sex"></a></span>
				<span style="display: block;">年齡:<a href="" id="age"></a><span style="margin-left: 10px;">歲</span></span>				
				<span style="display: block;">表情:<a href="" id="expression"></a></span>
				<span style="display: block;">顏值:<a href="" id="beauty"></a></span>
				<span style="display: block;"><a href="" id="neirong"></a></span>
				</div>
				</div>
				<div class="btn">
				<form id="renlian" method="post">
				<span style="position: relative;">提交圖片
				<input type="file" name="image" value="" id="uploading" onchange="test()" style="opacity: 0;width: 100%;position: absolute;height: 100%;display: block;top: 0px;" />
				</span>
				<span id="tijiao">開始識別</span>
			    </form>
				</div>
			</div>
		</div>
	</body>

</html>
<script type="text/javascript">
	function test() {
			var file = document.getElementById("uploading").files[0];
			var fr = new FileReader;
			var filePath = document.querySelector("#uploading").value;
			fileFormat = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
			if(!fileFormat.match(/.png|.jpg|.jpeg/)) {
				alert('上傳錯誤,文件格式必須為:png/jpg/jpeg');
				return;
			} else {
				fr.readAsDataURL(file);
				fr.onload = function(e) {
					document.getElementById("img").src = this.result;
				}
			}
		}
		$("#tijiao").click(function() {
			$.ajax({
				type: "post",
				url: basePath + "/FaceDetect",
				dataType: "json",
				data: new FormData($('#renlian')[0]),
				processData: false,
				contentType: false,
				beforeSend: function() {
					uploading = true;
				},
				success: function(res) {
					if(res.status=="200"){
						$("#neirong").text("");
						$("#sex").text(res.data.gender);
						$("#age").text(res.data.age);
						$("#expression").text(res.data.expression);
						$("#beauty").text(res.data.beauty);
					}else{
						$("#neirong").text("無法識別");
					}
				},
				error(xhr,status,error){
					$("#neirong").text("后台服務異常");
					return;
				}
			})
		})
</script>

face_match.html

<!DOCTYPE html>
    <html>
    
    	<head>
    		<meta charset="UTF-8">
    		<title>人臉比對</title>
    		<script src="js/jquery-2.1.0.js" type="text/javascript" charset="utf-8"></script>
    			<script src="js/jquery-2.1.0.js" type="text/javascript" charset="utf-8"></script>
    		<script src="js/jquery.particleground.min.js" type="text/javascript" charset="utf-8"></script>
    		<script src="js/ai.js" type="text/javascript" charset="utf-8"></script>
    		<link rel="stylesheet" type="text/css" href="css/style.css" />
    		<style type="text/css">
    			#dianji:hover{
    				transition: 0.5s;
    				background: skyblue;
    			}
    			.sss{
    				display: inline-block;
    				line-height:100px ;
    				border-radius: 100%; 
    				width: 200px;
    				margin: auto; 
    				height: 200px; 
    				border: 1px solid white;
    				margin-top: 10%;
    			}
    		</style>
    	</head>
    
    	<body>
    		<div id="context">
    			<div class="intro">
    				<div style="overflow: hidden; position: relative;top: 40%; overflow: hidden;margin: auto;text-align: center;">
    					<div style="border: 1px solid white; width: 30%; height: 400px; float: left;"><img id="ig1" src="" alt="" style="width: 100%; height: 100%"/></div>
    					<div class="sss">相似度</div>
    					<div style="border: 1px solid white; width: 30%; height: 400px; float: right;"><img id="ig2" src="" alt="" style="width: 100%; height: 100%;"/></div>
    				</div>
    
    				<form id="tttt" method="post" style="width: 80%;  margin:40px auto;">
    					<div style="width: 40%;float: left; position: relative;">
    						<span style="position: absolute;left: 0px;background: skyblue;display: inline-block;height: 40px;line-height: 40px;width: 160px;">
    						點擊上傳
    						</span>
    						<input style="opacity: 0; position: absolute;left: 0px; height: 40px;" id="uploading" type="file" onchange="upload1()" name="image1">
    					</div>
    					<div style="float: right;bwidth: 40%;float: right;position: relative;">
    					  <span id="" style="position: absolute;right: 0px;background: skyblue;display: inline-block;height: 40px;line-height: 40px;width: 160px;">
    					 	點擊上傳
    					 </span>
    					 <input  id="up" type="file" onchange="upload2()" name="image2" style="opacity: 0; position: absolute;right: 0px; height: 40px;" >
    					 </div>
    				</form>
    				<div id="dianji" style="border: 1px solid white;width: 140px;height: 40px;line-height: 40px;border-radius: 15px; margin: auto;">開始比對</div>
    			</div>
    
    		</div>
    	</body>
    	<script type="text/javascript">
    		function upload1() {
    			var file = document.getElementById("uploading").files[0];
    			var fr = new FileReader;
    			var filePath = document.querySelector("#uploading").value;
    			fileFormat = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
    			if(!fileFormat.match(/.png|.jpg|.jpeg/)) {
    				alert('上傳錯誤,文件格式必須為:png/jpg/jpeg');
    				return;
    			} else {
    				fr.readAsDataURL(file);
    				fr.onload = function(e){
    					document.getElementById("ig1").src = this.result;
    				}
    			}
    		}
    		function upload2() {
    			var file = document.getElementById("up").files[0];
    			var fr = new FileReader;
    			var filePath = document.querySelector("#up").value;
    			fileFormat = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
    			if(!fileFormat.match(/.png|.jpg|.jpeg/)) {
    				alert('上傳錯誤,文件格式必須為:png/jpg/jpeg');
    				return;
    			} else {
    				fr.readAsDataURL(file);
    				fr.onload = function(e){
    					document.getElementById("ig2").src = this.result;
    				}
    			}
    		}
    		$(function() {
    			$("#dianji").click(function() {
    				$.ajax({
    					url: basePath+"/FaceMatch",
    					type: 'post',
    					cache: false,
    					data: new FormData($('#tttt')[0]),
    					processData: false,
    					contentType: false,
    					dataType: "json",
    					beforeSend: function() {
    						uploading = true;
    						
    					},
    					success: function(data) {
    						if(data.status==200){
    							document.querySelector(".sss").innerHTML="相似度<br>"+data.data.score;
    						}else{
    							$(".sss").html("相似度<br><span style='color:red'>"+data.msg+"</span>");
    						}
    						
    					},
    					error(xhr,status,error){
    						$(".sss").html("相似度<br><span style='color:red'>后台服務異常</span>");
    						return;
    					}
    				});
    			});
    		});
    	</script>
    
    </html>
    
    speech_recognition.html
    
    <!DOCTYPE html>
    <html>
    
    	<head>
    		<meta charset="utf-8" />
    		<title>語音識別</title>
    		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    		<script src="js/jquery-2.1.0.js" type="text/javascript" charset="utf-8"></script>
    		<script src="js/jquery.particleground.min.js" type="text/javascript" charset="utf-8"></script>
    		<script src="js/ai.js" type="text/javascript" charset="utf-8"></script>
    		<link rel="stylesheet" type="text/css" href="css/style.css" />
    		<style type="text/css">
    			.cent_bg {
    				width: 80%;
    				height: 22em;
    				border: 1px solid rgba(255, 255, 255, 0.5);
    				margin: auto;
    				padding: 3% 6%;
    				border-radius: 10%;
    				font-size: 1.5em;
    				line-height: 2em;
    				position: relative;
    			}
    			
    			.cent {
    				margin-top: 1.5em;
    				overflow-y: auto;
    				height: 80%;
    				text-indent: 2em;
    				text-align: left;
    				padding-right: 0.2em;
    			}
    			
    			::-webkit-scrollbar {
    				width: 10px;
    				background-color: rgba(255, 255, 255, 0.2);
    			}
    			/*定義滾動條軌道 內陰影+圓角*/
    			
    			::-webkit-scrollbar-track {
    				border-radius: 5px;
    				background-color: transparent;
    			}
    			/*定義滑塊 內陰影+圓角*/
    			
    			::-webkit-scrollbar-thumb {
    				border-radius: 10px;
    				background-color: rgba(255, 255, 255, 0.7);
    			}
    			#ttttt{
    				display: none;
    			}
    			
    			.btn {
    				margin-top: 20px;
    				width: 70%;
    				height: 80px;
    				transition: 0.4s;
    				border-radius: 1em;
    				border: 1px solid rgba(255, 255, 255, 0.5);
    				border-top: none;
    				z-index: 66;
    				overflow: hidden;
    				position: relative;
    				background: rgba(255, 255, 255, 0.2);
    			}
    			
    			.btn:hover {
    				border: 1px solid rgba(255, 255, 255, 0.8) !important;
    				border-top: none !important;
    			}
    			
    			.btn span {
    				width: 40%;
    				height: 84%;
    				margin-top: 6px;
    				line-height: 38px;
    				display: inline-block;
    				border: 1px solid #009FFD;
    				color: #fff;
    				background: rgba(255, 255, 255, 0.4);
    				border-radius: 4px;
    				cursor: pointer;
    			}
    			
    			.btn span:nth-of-type(1) {
    				margin-right: 15px;
    				position: relative;
    			}
    			
    			.btn span:nth-of-type(2) {
    				margin-left: 15px;
    			}
    			input{
    				width: 100%;
    				height: 100%;
    				border: 1px solid red;
    				position: absolute;
    				top: 0;
    				left: 0;
    				opacity: 0;
    			}
    			.img{
    				width: 60px;
    				height: 60px;
    				margin: auto;
    				text-align: center;
    				position: relative;
    			}
    			.img img{
    				width: 100%;
    				height: 100%;
    				position: absolute;
    				top: 0;
    				left: 0;
    			}
    			.mmm{
    				width: 100%;
    				height: 100%;
    				position: absolute;
    				top: 0;
    				left: 0;
    				z-index: 999;
    				display: none;
    				cursor: pointer;
    				background: #b9fff4;
    				color: aqua;
    				line-height: 80px;
    			}
    		</style>
    	</head>
    
    	<body>
    		<div id="context">
    			<div class="intro">
    				<div class="cent_bg">
    					<h3>語音識別內容:</h3>
    					<div class="cent">
    					</div>
    				</div>
    				<div class="btn">
    					<span>上傳文件
    					</span>
    					<span>開始識別</span>
    					<div class="mmm">
    						正在識別...
    					</div>
    				</div>
    				<form id="ttttt" action="" method="post">
    					<input type="file" name="voice" value="">
    				</form>
    			</div>
    		</div>
    	</body>
    
    </html>
    <script type="text/javascript">
    	$(function() {
    		$(".btn span:nth-of-type(1)").click(function() {
    			$('#ttttt input[name="voice"]').click();
    		})
    		$(".btn span:nth-of-type(2)").click(function() {
    			if(document.querySelector("input").value==""){
    				return alert("未選擇文件");
    			}
    			$(".mmm").css("display","block");
    			$(".cent").html('<div class="img"><img src="img/timg.gif"/></div>');
    			$.ajax({
    				url: basePath + "/VoiceRecognize",
    				type: 'post',
    				cache: false,
    				data: new FormData($('#ttttt')[0]),
    				processData: false,
    				contentType: false,
    				dataType: "json",
    				beforeSend: function() {
    					uploading = true;
    				},
    				success: function(data) {
    					if (data.status=="200") {
    						$(".cent").html(data.data.text);
    						$(".mmm").css("display","none");
    					} else{
    						$(".cent").html("未能識別 "+data.msg);
    						$(".mmm").css("display","none");
    					}
    				}
    			});
    		});
    	});
    </script>

speech_produce.html

<!DOCTYPE html>
<html>

	<head>
		<meta charset="utf-8" />
		<title>語音合成</title>
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<script src="js/jquery-2.1.0.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/jquery.particleground.min.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/ai.js" type="text/javascript" charset="utf-8"></script>
		<link rel="stylesheet" type="text/css" href="css/style.css" />
		<style type="text/css">
			#error {
				width: 60%;
				height: 120px;
				line-height: 120px;
				text-align: center;
				font-size: 1.5em;
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -65%);
				z-index: 999;
			}
			
			.cent_bg {
				width: 80%;
				height: 22em;
				border: 1px solid rgba(255, 255, 255, 0.5);
				margin: auto;
				padding: 3% 6%;
				border-radius: 10%;
				font-size: 1.5em;
				line-height: 2em;
				position: relative;
			}
			
			.cent {
				margin-top: 1em;
				width: 100%;
				background: rgba(0, 0, 0, .5);
				overflow-y: auto;
				height: 80%;
				color: white;
				font-size: 1.3em;
				text-indent: 1em;
				padding: .8em;
				border: none;
				resize: none;
				outline-color: white;
			}
			
			::-webkit-scrollbar {
				width: 10px;
				background-color: rgba(255, 255, 255, 0.2);
			}
			/*定義滾動條軌道 內陰影+圓角*/
			
			::-webkit-scrollbar-track {
				border-radius: 5px;
				background-color: transparent;
			}
			/*定義滑塊 內陰影+圓角*/
			
			::-webkit-scrollbar-thumb {
				border-radius: 10px;
				background-color: rgba(255, 255, 255, 0.7);
			}
			
			.btn {
				width: 70%;
				height: 40px;
				transition: 0.4s;
				border-bottom-left-radius: 1em;
				border-bottom-right-radius: 1em;
				border: 1px solid rgba(255, 255, 255, 0);
				border-top: none;
				z-index: 66;
				background: rgba(255, 255, 255, 0.2);
				padding: 5px 0px;
			}
			
			.btn #btnSub:hover {
				border: 1px solid rgba(255, 255, 255) !important;
				color: white;
			}
			
			.btn #btnSub {
				width: 40%;
				height: 100%;
				line-height: 25px;
				display: inline-block;
				border: 1px solid #009FFD;
				color: #fff;
				background: rgba(255, 255, 255, 0.4);
				border-radius: 4px;
				font-size: 1.1em;
				cursor: pointer;
			}
			
			#select {
				margin: auto;
				margin-top: 10px;
				width: 70%;
				height: 30px;
				border-top-left-radius: 1em;
				border-top-right-radius: 1em;
				transition: 0.4s;
				border-top: none;
				z-index: 66;
				background: rgba(255, 255, 255, 0.2);
			}
			
			#selectBox {
				width: 70%;
				height: 30px;
				margin: 0 auto;
			}
			
			#mantext,
			#womantext {
				font-size: 1.25em;
				line-height: 30px;
				float: left;
			}
			
			#mantext {
				text-align: center;
			}
			
			#woman {}
			
			.inputBox {
				width: 50%;
				height: 30px;
				float: left;
			}
			
			#man,
			#woman {
				margin-top: 6px;
				display: block;
				float: left;
				width: 20px;
				height: 20px;
			}
		</style>
	</head>

	<body>
		<div id="error">請在此輸入文本內容</div>
		<div id="context">
			<div class="intro">
				<form method="post" enctype="multipart/form-data" id="Voice">
					<div class="cent_bg">
						<h3>請輸入要合成的語音文本:</h3>
						<textarea id="Content" class="cent" name="text"></textarea>
					</div>
					<div id="select">
						<div id="selectBox">
							<div class="inputBox">
								<label id="mantext" for="man" style="float: right;">男聲</label><input id="man" type="radio" name="voiceType" checked value="1" style="float: right;" />
							</div>

							<div class="inputBox">
								<input id="woman" type="radio" name="voiceType" value="2" /><label id="womantext" for="woman">女聲</label>
							</div>
						</div>
					</div>
					<div class="btn">
						<button id="btnSub" type="submit">合成語音</button>
					</div>
				</form>
			</div>

		</div>

	</body>
	<script>
		$(function() {
			var cor=0;
			var stop=setInterval(function(){
				$('#error').fadeToggle(700);
				cor++;
				if(cor==3){
					clearInterval(stop);
				}
			},700);
			$('#btnSub').on('click', function() {
				cor=0;
				var Text = $('#Content').val();
				if(Text.length == 0) {
					var stop=setInterval(function(){
						$('#error').fadeToggle(700);
						cor++;
						if(cor==4){
							clearInterval(stop);
						}
					},700);
					return false;
				}
			});
			// 服務器請求地址
			$('#Voice').attr('action', basePath+"/VoiceGen");
		});
	</script>

</html>

ai.js

// 服務器主地址
var basePath="127.0.0.1:8080/AIProject"
// 背景效果
$(document).ready(function() {
  $('#context').particleground({
    dotColor: '#5cbdaa',
    lineColor: '#5cbdaa'
  });
  $('.intro').css({
    'margin-top': -($('.intro').height() / 2)
  });
});

style.css

/*********CSS初始化*********/
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
	margin: 0;
	padding: 0;
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
	display: block;
}

body {
	line-height: 1;
}

ol,
ul {
	list-style: none;
}

blockquote,
q {
	quotes: none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
	content: '';
	content: none;
}

table {
	border-collapse: collapse;
	border-spacing: 0;
}


/* particleground demo */

*{
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
}

html,
body {
	width: 100%;
	height: 100%;
	/*overflow: scroll;*/
}
/*********CSS初始化結束*********/

body {
	background: #202AA3;
	font-family: 'Montserrat', sans-serif;
	color: #fff;
	line-height: 1.3;
	-webkit-font-smoothing: antialiased;
}

#particles {
	width: 100%;
	height: 100%;
	overflow: hidden;
}

.intro {
	position: absolute;
	left: 0;
	top: 50%;
	padding: 0 20px;
	width: 100%;
	text-align: center;
}

h1 {
	text-transform: uppercase;
	font-size: 85px;
	font-weight: 700;
	letter-spacing: 0.015em;
}

h1::after {
	content: '';
	width: 60%;
	display: block;
	background: #fff;
	height: 10px;
	margin: 30px auto;
	line-height: 1.1;
}

p {
	margin: 0 0 30px 0;
	font-size: 24px;
}

.btn {
	display: inline-block;
	padding: 15px 30px;
	border: 2px solid #fff;
	text-transform: uppercase;
	letter-spacing: 0.015em;
	font-size: 18px;
	font-weight: 700;
	line-height: 1;
	color: #fff;
	text-decoration: none;
	-webkit-transition: all 0.4s;
	-moz-transition: all 0.4s;
	-o-transition: all 0.4s;
	transition: all 0.4s;
}

.btn:hover {
	color: #005544;
	border-color: #005544;
}

@media only screen and (max-width: 1000px) {
	h1 {
		font-size: 70px;
	}
}

@media only screen and (max-width: 800px) {
	h1 {
		font-size: 48px;
	}
	h1::after {
		height: 8px;
	}
}

@media only screen and (max-width: 568px) {
	.intro {
		padding: 0 10px;
	}
	h1 {
		font-size: 30px;
	}
	h1::after {
		height: 6px;
	}
	p {
		font-size: 18px;
	}
	.btn {
		font-size: 16px;
	}
}

@media only screen and (max-width: 320px) {
	h1 {
		font-size: 28px;
	}
	h1::after {
		height: 4px;
	}
}

接口規范

數據交互類型:JSON
請求數據:請求數據除了請求參數以外,還需另外發送以下參數:(否則會返回403狀態碼)

返回數據格式:
{"status": "200","msg":"","data": {"namename":"user","password":"password"}}

(1)人臉識別
接口名:FaceDetect
請求參數:

返回參數:

(2)人臉比對
接口名:FaceMatch
請求參數:

返回參數:

(3)語音識別
接口名:VoiceRecognize
請求參數:

返回參數:

(4)語音生成
接口名:VoiceGen

返回參數:
Mp3音頻格式文件

請求注意事項

 請求體格式化:Content-Type為application/json,通過json格式化請求體。
 Base64編碼:請求的圖片需經過Base64編碼,圖片的base64編碼指將圖片數據編碼成一串字符串,使用該字符串代替圖像地址。您可以首先得到圖片的二進制,然后用Base64格式編碼即可。需要注意的是,圖片的base64編碼是不包含圖片頭的,如data:image/jpg;base64,
 圖片格式:現支持PNG、JPG、JPEG、BMP,不支持GIF圖片

實例代碼

1. 人臉識別實例代碼

// 配置請求參數
HashMap<String, String> options = new HashMap<String, String>();
options.put("face_field", "age,gender,glasses,beauty,expression");
options.put("max_face_num", "2");
options.put("face_type", "LIVE");
// 轉換成base64
String image = Base64Util.part2Base64(imagePart);
String imageType = "BASE64";
// 接口調用,並返回JSON數據
JSONObject json = client.detect(image, imageType, options);
// 響應數據處理
Map<String, Object> map = new HashMap<>();
// 獲取人臉信息列表
JSONObject result = json.getJSONObject("result").getJSONArray("face_list").getJSONObject(0);
// 響應數據:性別
JSONObject genderObj = result.getJSONObject("gender");
String genderStr = genderObj.getString("type");
if(genderObj.getDouble("probability") >= 0.6) {//概率並轉換
	if("female".equals(genderStr)) {
		genderStr = "女";
	}else if("male".equals(genderStr)) {
		genderStr = "男";
	}
}
map.put("gender", genderStr);
// 返回接口數據
return ResponseData.success(map);

2. 人臉對比實例代碼

// 轉換成base64
String image1 = Base64Util.part2Base64(imagePart1);
String image2 = Base64Util.part2Base64(imagePart2);
// 封裝平台接口請求對象
MatchRequest req1 = new MatchRequest(image1, "BASE64");
MatchRequest req2 = new MatchRequest(image2, "BASE64");
ArrayList<MatchRequest> requests = new ArrayList<MatchRequest>();
requests.add(req1);
requests.add(req2);
// 人臉匹配
JSONObject json = client.match(requests);
// 響應數據處理
Map<String, Object> map = new HashMap<>();
// 匹配分值
double score = json.getJSONObject("result").getDouble("score");
return ResponseData.success(map);

3. 語音識別實例代碼

// 文件類型
String fileType = voicePart.getContentType();
if(fileType.endsWith("mp3")) {
	fileType = MP3;
}else if(fileType.endsWith("wav")) {
	fileType = WAV;
}else {
	return ResponseData.fail("請上傳mp3、wav音頻");
}
try {
	// 獲取音頻字符流
	InputStream is = voicePart.getInputStream();
	// 保存臨時音頻文件
	String filename = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(Calendar.getInstance().getTime());
	File tmpVoice = new File(workspace + File.separator + filename+fileType);
	VoiceUtil.saveVoiceFile(is, tmpVoice);
	if(fileType.equals(MP3)) {
		File mp3File = tmpVoice;
		tmpVoice = new File(tmpVoice.getPath().replace(MP3, WAV));
		if(!VoiceUtil.mp3ToWav(mp3File, tmpVoice)) {
			return ResponseData.fail("mp3音頻文件錯誤,請用wav音頻。");
		}
		mp3File.delete();
	}
	// 調用百度接口
	JSONObject json = client.asr(tmpVoice.getPath(), "wav", 16000, null);
	tmpVoice.delete();
	Integer status = json.getInt("err_no"); //狀態碼
	if(status != 0) {
		// 異常響應處理
		String msg = json.getString("err_msg");
		log.warn("百度接口調用響應異常,error_code:"+status + " error_msg:"+msg);
		return ResponseData.fail(msg);
	}
	// 響應數據處理
	Map<String, Object> map = new HashMap<>();
	// 獲取結果
	JSONArray jsonArray = json.getJSONArray("result");
	// 識別文本
	String text = jsonArray.getString(0);
	map.put("text", text);
	return ResponseData.success(map);
} catch (Exception e) {
	log.warn("識別音頻文件錯誤:", e);;
}

4. 語音合成實例代碼

// 請求參數
HashMap<String, Object> options = new HashMap<String, Object>();
// 語速,取值0-9,默認為5中語速
options.put("spd", "5");
// 音調,取值0-9,默認為5中語調
options.put("pit", "5");
// 發音人選擇, 0為女聲,1為男聲, 3為情感合成-度逍遙,4為情感合成-度丫丫,默認為普通女
options.put("per", voiceType);
// 調用百度api接口
TtsResponse res = client.synthesis(text, "zh", 1, options);
byte[] data = res.getData();
return data;

效果展示

源碼下載地址:https://github.com/jcdjor/AIProject

PS:歡迎大家給予評論、建議和下載學習,下面為源碼的一些說明

  • AIProject.zip 為后端代碼,為eclipse項目,app.properties文件需要自己配置百度雲開發平台的AppID、APIKey、SecretKey。
  • Web.zip 為前端代碼,前后端分離,可直接運行使用 。
  • 運行環境,對版本沒太大要求,但jdk和tomcat要對應 JDK:我使用的版本為JDK1.8,官方下載地址
    Tomcat:,我使用的版本為tomcat 9,官方下載地址
  • 注意需要百度雲開放平台的AppID、APIKey、SecretKey,百度雲AI開放平台:http://ai.baidu.com/

聲明:本文歡迎大家評論和轉載,使用本文章或代碼還請聲明,且在使用處的明顯位置給出。如有其它問題或有什么建議,可在下方評論,或加QQ(1414782205),或發郵箱jcdjor@163.com。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM